作用:把 A 分支 合并到当前分支 (此时当前分支新增了一次提交,指着指向该提交)
初始状态:
git merge bugFix 后:
此外,如果再把 main
分支合并到 bugFix 即(git checkout bugFix, git merge main)
此时,因为 main
继承自 bugFix
,Git 什么都不用做,只是简单地把 bugFix
移动到 main
所指向的那个提交记录。现在所有提交记录的颜色都一样了,这表明每一个分支都包含了代码库的所有修改!
作为第二种合并分支的方法,实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。Rebase 的优势就是可以创造更线性的提交历史(看起来像是按顺序开发,但实际上它们是并行开发的。),这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。
作用:把当前分支 合并到 A分支 (此时A分支新增了一次提交,指针指向该提交)
初始状态:
git merge main 后:
bugFix 分支上的工作在 main 的最顶端,同时我们也得到了一个更线性的提交序列。
注意,提交记录 C3 依然存在(树上那个半透明的节点),而 C3' 是我们 Rebase 到 main 分支上的 C3 的副本。
此外,有个问题就是 main 还没有更新,则可以: git checkout main , git rebase bugFix ,即
由于 bugFix
继承自 main
,所以 Git 只是简单的把 main
分支的引用向前移动了一下而已。
git 指针即上图中的 * ,一般用HEAD表示,指向某个分支的最后一次提交。
分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:HEAD 指向 main, main 指向 C1(HEAD -> main -> C1)
而 git checkout c1(c1 为某次提交记录的哈希值前几位,提交记录的哈希值一般很长,通过
git log 查看提交记录哈希值)则会变成如下图:
main
^^ 是 main
的第二个 parent 节点)~
向上移动多个提交记录,如 ~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.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 之后就可以把你的更改推送到远程仓库撤销之前的提交。
命令:git cherry-pick <提交号>...
作用:将一些提交复制到当前所在的位置(HEAD
)的下面
例子:将 side
分支上的一些提交,复制到 main
分支
初始状态:
git cherry-pick C2 C4后:
如果不记得提交记录的哈希值,可以利用交互式的 rebase
例子:假如之前在 newImage
分支上进行了一次提交,然后又基于它创建了 caption
分支,然后又提交了一次。此时你想对某个以前的提交记录进行一些小小的调整。比如设计师想修改一下 newImage
中图片的分辨率,尽管那个提交记录并不是最新的了。
方案:
git rebase -i
将提交重新排序,然后把我们想要修改的提交记录挪到最前git commit --amend
来进行一些修改(对之前的commit 提交进行修改,push后取代原来的commit)git rebase -i
来将他们调回原来的顺序初始状态
git rebase -i HEAD~2 可以打开交互框,对前2次提交进行编辑(排序,取舍):
对提交记录进行调整后会出现一个新的分支
将后三步走完之后,效果如下:
分支很容易被人为移动,并且当有新的提交时,它也会移动。tag 可以永久地将某个特定的提交命名为里程碑(大版本),它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。如果你不指定提交记录,Git 会用 HEAD
所指向的位置。
命令:git tag v1 c1 给c1提交打上v1标签,如下:
Git Describe 能帮你在提交历史中移动了多次以后找到方向,用来描述离你最近的 tag
ref
可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会使用你目前所在的位置(HEAD
)
输出:
tag
表示的是离 ref
最近的标签, numCommits
是表示这个 ref
与 tag
相差有多少个提交记录, hash
表示的是你所给定的 ref
所表示的提交记录哈希值的前几位。
当 ref
提交记录上有某个标签时,则只 输出 标签名称。
例:初始状态:
git describe main 会输出: v1_2_gC2
git describe side 会输出:v2_1_gC4