1. merge
命令:git merge A
作用:把 A 分支 合并到当前分支 (此时当前分支新增了一次提交,指着指向该提交)
初始状态:
git merge bugFix 后:
此外,如果再把 main
分支合并到 bugFix 即(git checkout bugFix, git merge main)
此时,因为 main
继承自 bugFix
,Git 什么都不用做,只是简单地把 bugFix
移动到 main
所指向的那个提交记录。现在所有提交记录的颜色都一样了,这表明每一个分支都包含了代码库的所有修改!
2. rebase
作为第二种合并分支的方法,实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。Rebase 的优势就是可以创造更线性的提交历史(看起来像是按顺序开发,但实际上它们是并行开发的。),这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。
命令:git rebase A
作用:把当前分支 合并到 A分支 (此时A分支新增了一次提交,指针指向该提交)
初始状态:
git merge main 后:
bugFix 分支上的工作在 main 的最顶端,同时我们也得到了一个更线性的提交序列。
注意,提交记录 C3 依然存在(树上那个半透明的节点),而 C3' 是我们 Rebase 到 main 分支上的 C3 的副本。
此外,有个问题就是 main 还没有更新,则可以: git checkout main , git rebase bugFix ,即
由于 bugFix
继承自 main
,所以 Git 只是简单的把 main
分支的引用向前移动了一下而已。
3. 指针——分支切换
哈希值方式
git 指针即上图中的 * ,一般用HEAD表示,指向某个分支的最后一次提交。
分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:HEAD 指向 main, main 指向 C1(HEAD -> main -> C1)
而 git checkout c1(c1 为某次提交记录的哈希值前几位,提交记录的哈希值一般很长,通过
git log 查看提交记录哈希值)则会变成如下图:
相对引用
- 使用 ^ 向上移动 1 个提交记录(
main
^^ 是main
的第二个 parent 节点) - 使用
~<num>
向上移动多个提交记录,如~3
例1:*原本在main处,
切换到 main 的 parent 节点 (git checkout main^)
也可以将 HEAD
作为相对引用的参照。*原本在main处,下面咱们就用 HEAD
在提交树中向上移动几次:git checkout C3,git checkout HEAD^,git checkout HEAD^,git checkout HEAD^
例2.1:使用~
初始状态 :
git checkout HEAD~4后:
例2.2
初始状态:
git branch -f main HEAD~3 将 main 分支强制指向 HEAD 的(前)第 3 级 parent 提交:
4.撤销
4.1 本地分支 撤销
git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset
向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
例1 初始状态:
git reset HEAD~1后:
Git 把 main 分支移回到 C1
;现在我们的本地代码库根本就不知道有 C2
这个提交了。
(注意:在reset后, C2
所做的变更还在,但是处于未加入暂存区状态。)
4.2 远程分支 撤销
例2:初始状态
git revert HEAD (撤销当前分支main的一次提交)后:
此时,多了一个新提交记录 C2'
引入了更改 —— 这些更改刚好是用来撤销 C2
这个提交的。也就是说 C2'
的状态与 C1
是相同的。revert 之后就可以把你的更改推送到远程仓库撤销之前的提交。