“Git:基本操作”的版本间差异
|  (→命令辨析) | |||
| 第612行: | 第612行: | ||
| === reset、revert与checkout === | === reset、revert与checkout === | ||
| {| class="wikitable" | |||
| |- | |||
| ! style="width: 4%;"| | |||
| ! style="width: 48%;"|Commit-level  | |||
| ! style="width: 48%;"|File-level | |||
| |- | |||
| ! '''<code>checkout</code>''' | |||
| | | |||
| [[File:checkout_Commit.png|center|400px]] | |||
| * '''<code>git checkout <commit/HEAD^?></code>''': | |||
| *: 移动HEAD到另外一个分支(或commit),并更新工作目录。 | |||
| | | |||
| [[File:checkout_file.png|center|400px]] | |||
| * '''<code>git checkout <commit/HEAD^?> <file></code>''': | |||
| *: 将worktree文件<file>重置到指定commit的版本(将丢弃工作区文件<file>未add的修改)。 | |||
| |- | |||
| ! '''<code>reset</code>''' | |||
| | | |||
| [[File:reset_Commit.png|center|400px]] | |||
| * '''<code>git reset [--soft/--mixed/--hard] <commit/HEAD^?></code>''': | |||
| *: 将分支的指向其他commit,以进行版本回退(被跳过的commit成了dangling commit,将在下次git垃圾回收被删除)。 | |||
| | | |||
| [[File:reset_File.png|center|400px]] | |||
| * '''<code>git reset <commit/HEAD^?> <file></code>''': | |||
| *: 将stage文件<file>重置到指定commit的版本。 | |||
| *(<code>[--soft/--mixed/--hard]</code>对此不起作用,stage总会被更新, worktree不会被更新) | |||
| |- | |||
| ! '''<code>revert</code>''' | |||
| | | |||
| [[File:revert_Commit.png|center|400px]] | |||
| * '''<code>git reset <commit/HEAD^?></code>''': | |||
| *: 通过新建commit进行反向修改,以实现撤销某个commit的修改。 | |||
| |  | |||
| |} | |||
2020年9月21日 (一) 22:05的版本
常用操作
仓库
| 命令 | 说明 | 备注 | 
|---|---|---|
| git init | 初始化Git仓库 | 
 | 
| git clone | 克隆Git仓库 | 
 | 
- git clone可以所用不同的协议,包括- ssh,- git,- https等:- git clone git@github.com:fsliurujie/test.git:SSH协议
- git clone git://github.com/fsliurujie/test.git:GIT协议
- git clone https://github.com/fsliurujie/test.git:HTTPS协议
 - (常用ssh,因为速度较快,还可以配置公钥免输入密码)
 
修改
| 命令 | 说明 | 备注 | 
|---|---|---|
| git add | 将工作区新增或修改的文件添加到暂存区 | 
 | 
| git commit | 提交暂存区到本地仓库 | 
 | 
| git status | 查看仓库当前的状态,显示有变更的文件 | Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git status
On branch master
Your branch is up to date with 'eijux/master'.
Changed not staged for commit:
  (use "git add <file>..." to include in what will be committed)
  (use "git restore --staged <file>..." to unstage)
        new file:   1.txt
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   2.txt
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        3.txt
 | 
| git diff | 比较文件的不同,即暂存区和工作区的差异 | 
 | 
| git stash | 保存工作现场 | 
 | 
| git reset | 回退版本 | 
 
 
 关于[HEAD]: 
 版本回退: 
 | 
| git revert | 撤销操作 | 
 | 
| git restore | 文件恢复 | Note1:
 
 
 Note2: 
 | 
| git mv | 移动或重命名工作区文件 | 
 | 
| git rm | 删除工作区文件 | 
 | 
关于撤销工作区修改
- 若工作区修改未add到stage:
- git checkout -- <file>
 
- 若工作区修改已add,但未commit:
- git reset HEAD <file>(1、从版本库commit中恢复到stage)
- git checkout -- <file>(2、撤销工作区修改)
 
分支
| 命令 | 说明 | 备注 | 
|---|---|---|
| git branch | 分支命令 | 
 | 
| git checkout | 签出分支(或文件) | 分支: 
 
 文件:
 
 | 
| git merge | 分支合并 | 
 Note2: 
 | 
| git rebase | 分支(变基)合并 | 
 Note2: 
 | 
| git switch | 切换分支 | 与 
 | 
冲突合并:
冲突合并涉及文件添加、移除的操作,还包括文件修改内容的合并。
远程
| 命令 | 说明 | 备注 | 
|---|---|---|
| git remote | 管理远程仓库主机名 | 
 | 
| git pull | 下载远程代码并合并: | Note1: 
 Note2: 
 Note3: 
 | 
| git push | 上传远程代码并合并: | Note1: 
 Note2: 
 Note3:关于推送方式 
 | 
| 
 | 获取远程主机的版本库更新(commit): Download objects and refs from another repository | Note1: 
 Note2: 
 Note3: 
 | 
日志
| 命令 | 说明 | 示例 | 
|---|---|---|
| git log | 查看版本提交历史 | Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git log
commit 5e26159ad738b08b9321eba9ecaeff39c8acc42f (HEAD -> master, eijux/master)
Author: Eijux <chen@eijux.com>
Date:   Fri Nov 1 01:18:47 2019 +0800
    idea commit test 01<E7><82><B9>18<E5><88><86>
commit ffa14211ab7088d9782de019328238dcfe09a4bc
Merge: 3fbc79a fc32a4a
Author: Eijux <chen@eijux.com>
Date:   Thu Oct 31 16:03:24 2019 +0800
    Merge branch 'master' of github.com:Eijux/eijux
commit 3fbc79ae2c8b7199c22133d1f3e4115848dbe749
Author: Eijux <chen@eijux.com>
Date:   Thu Oct 31 04:19:09 2019 +0800
    idea commit test
(END)
Note: 
 | 
| git reflog | 查看版本命令历史 | Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git reflog
5e26159 (HEAD -> master, eijux/master) HEAD@{0}: pull eijux master: Fast-forward
fc32a4a HEAD@{1}: commit: add gitignore file
d07be0a HEAD@{2}: commit: branch management test
492be10 HEAD@{3}: merge dev: Merge made by the 'recursive' strategy.
fc1038b HEAD@{4}: checkout: moving from dev to master
9d0f76e (dev) HEAD@{5}: commit: write a line on branch dev
7640602 (eijux/dev) HEAD@{6}: checkout: moving from master to dev
fc1038b HEAD@{7}: reset: moving to HEAD
fc1038b HEAD@{8}: commit: branch back to master
7640602 (eijux/dev) HEAD@{9}: merge dev: Fast-forward
63fa5ac HEAD@{10}: checkout: moving from dev to master
7640602 (eijux/dev) HEAD@{11}: commit: add dev branch
63fa5ac HEAD@{12}: checkout: moving from master to dev
63fa5ac HEAD@{13}: pull eijux master --allow-unrelated-histories: Merge made by the 'recursive' strategy.
da60d32 HEAD@{14}: commit: add t5.txt
e88cb69 HEAD@{15}: commit: delete rmtest.txt
cc1e40c HEAD@{16}: commit: changed t4 and add t5
1707196 HEAD@{17}: commit: changed t4
378fb5a HEAD@{18}: commit: add t4.txt
e3501ab HEAD@{19}: commit: add t4
ea463d0 HEAD@{20}: commit: add t2.txt
92ad079 HEAD@{21}: commit: git commit single file test
061529e HEAD@{22}: reset: moving to 061529
69e722f HEAD@{23}: reset: moving to head
69e722f HEAD@{24}: reset: moving to head^
061529e HEAD@{25}: reset: moving to 061529
69e722f HEAD@{26}: reset: moving to 69e722
061529e HEAD@{27}: commit: git diff test
69e722f HEAD@{28}: commit: banben test
fd1fd5f HEAD@{29}: commit (initial): git add test
 | 
标签
tag实际就是一个指向commit的指针,将一个有意义的tag名称与commit相关联。
git标签有两种类型:
- 轻量级的(lightweight):实际上它就是个指向特定提交对象的引用。
- 含附注的(annotated):实际上是存储在仓库中的一个独立对象,有自身的校验和信息,包含标签名称,电子邮件地址和日期,及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。 
| 命令 | 说明 | 备注 | 
|---|---|---|
| git tag | git标签 | Note: 
 如: Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git tag
D:\git\eijux>git tag rc1.0
D:\git\eijux>git tag -a rc2.0
# Write a message for tag:
#   rc2.0
# Lines starting with '#' will be ignored.
D:\git\eijux>git tag rc3.0 ffa1
D:\git\eijux>git log --decorate
commit 5e26159ad738b08b9321eba9ecaeff39c8acc42f (HEAD -> master, tag: rc2.0, tag: rc1.0, eijux/master)
Author: Eijux <chen@eijux.com>
Date:   Fri Nov 1 01:18:47 2019 +0800
    idea commit test 01<E7><82><B9>18<E5><88><86>
commit ffa14211ab7088d9782de019328238dcfe09a4bc (tag: rc3.0)
Merge: 3fbc79a fc32a4a
Author: Eijux <chen@eijux.com>
Date:   Thu Oct 31 16:03:24 2019 +0800
    Merge branch 'master' of github.com:Eijux/eijux
D:\git\eijux>git show rc3.0
commit ffa14211ab7088d9782de019328238dcfe09a4bc (tag: rc3.0)
Merge: 3fbc79a fc32a4a
Author: Eijux <chen@eijux.com>
Date:   Thu Oct 31 16:03:24 2019 +0800
    Merge branch 'master' of github.com:Eijux/eijux
D:\git\eijux>
 | 
命令辨析
pull 与 fetch
More precisely, git pull runs git fetch with the given parameters and calls git merge to merge the retrieved branch heads into the current branch. With --rebase, it runs git rebase instead of git merge.
在默认模式下,git pull是git fetch后跟git merge FETCH_HEAD的缩写。
更准确地说,git pull使用给定的参数运行git fetch,并调用git merge将检索到的分支头合并到当前分支中。 使用--rebase,它运行git rebase而不是git merge。
fetch理解:
- fetch 是否有下载?
- 当然有下载,拉取的更新内容保存在“.git\objects”及“.git\refs”中,只是没有合并到当前的工作区,所以没有直观的改变;毕竟merge是不会有下载操作的。
 
- fetch 更新的是什么内容?
- fetch 会下载远程分支orign/master的文件存储对象到“.git\objects”;
- fetch 会更新FETCH_HEAD文件(如5e26159ad738b08b9321eba9ecaeff39c8acc42f branch 'master' of github.com:Eijux/eijux),其中commit_ID对应“.git\objects”的对象;
 
- fetch 会下载远程分支
- 本地文件与分支的关系?
- .git\refs\head\ [本地分支] .git\refs\remotes\ [正在跟踪的分支] 
 
merge 与 rebase
merge 与 rebase 同为合并分支,但是还是有区别的:
| merge | rebase | 
|---|---|
|   |   | 
| 产生新的提交 | 没有新提交,但会合并之前的commit历史 | 
| 不改变当前分支的开始位置 | 改变了当前分支的开始位置 | 
| 只处理一次冲突 | 可能会有多次冲突处理 | 
| 合并后的所有 commit 会按照提交时间从旧到新排列 | 合并后的 commit 顺序不一定按照 commit 的提交时间排列 | 
| 合并后分支过程信息更多更复杂 | 合并后分支上每个 commit 点都是相对独立完整的功能单元 | 
关于merge的过程
| merge的过程 | |
|---|---|
|   | 以左图为例, “ git merge origin”将两个分支的最新commit的内容进行合并,进行冲突处理之后作为新的commit提交到“mywork”分支: | 
| git logg查看commit时,其顺序为:(有时间顺序) C1-----C2-----C3-----C4-----C7 └-------C5-----C6---------┘ | |
关于rebase的过程
| rebase的过程 | |
|---|---|
|   | 左图: 
 
 | 
| git logg查看commit时,其顺序为:(C5、C6未按时间顺序) C1-----C2-----C3-----C4-----C5-----C6 | |
关于rebase的冲突
rebase过程中可能出现多次冲突,Git会停止rebase来进行冲突解决;
- 在解决冲突后,用" git add "命令去更新这些内容的索引(无需执行git commit);
- 执行“git rebase --continue”继续rebase过程;
- 在rebase过程的任何时候,都可以用“git rebase --abort”来终止rebase,并且将分支回退到rebase开始前状态。
The Golden Rule of Rebasing rebase
never use it on public branches(不要在公共分支上使用)
| rebase的过程 | |
|---|---|
|   | 如左图,执行 
 所以,在公共分支、需要保留历史的分支,不应该使用rebase! | 
reset 与 revert
reset 与 revert 都是进行“撤销”操作,但其效果并不相同:
| reset | revert | 
|---|---|
| 
 | 
 
 | 
| 对于分支merge的撤销操作(如将“eijux”合并到“master”): 
 | |
reset、revert与checkout
| Commit-level | File-level | |
|---|---|---|
| checkout | 
 | 
 | 
| reset | 
 | 
 | 
| revert | 
 | 





