git rebase
被翻译为变基,该命令的作用就是整理提交历史,效果是使得提交历史变成连续的,没有分叉。在团队开发时,经常需要进行合并,我们知道,一般使用 git pull
或 git merge
合并远程代码,合并时会优先使用快速合并,若不能快速合并则会采取三方合并,会添加一个 commit,commit 记录了被合并的两个 parent。
其实合并的方式不止默认的这两种方式,rebase/squash 等合并方式更是可以带来干净整洁的提交历史。
git merge
通常合并分支我们有两种方法,merge
和 rebase
,先看看在使用 merge
时合并分支的效果
下图中,灰色表示 commit
橙色表示分支
使用 git merge
将 experiment 合并到 master 后,提交历史变为了:
图示中的这种合并方式称为 三方合并,将两个分支的最新提交与和两个分支的最近共同祖先进行合并,这种合并方式会生成一个新的 commit
,通过 git cat-file
查看该 commit 可发现其包含两个 parent,分别为两个分支的最新提交。
git rebase
用法:
1 | git rebase [-i | --interactive] [<options>] [--exec <cmd>] |
同上面的例子相同,如果使用 git rebase
合并分支
1 | git checkout experiment |
这里
git rebase master
与git rebase master experiment
是等效的。默认的目标分支就是当前分支。
合并时,master
为基底分支,当前分支是 experiment
,两者的最近共同祖先是 c2
。合并时的步骤是:
- 将当前分支相对与祖先分支的全部提交提取为零时文件。
- 将当前分支指向基底分支指向的
commit
,然后将零时文件记录的修改依次应用。
重应用零时文件的内容虽与原来相同,但是会在当前分支上重新提交,commit 信息和原来不同。
最后将 experiment
merge 到 master
后得到一条完美的提交历史
1 | git checkout master |
删除提交
git rebase
还可以删除一定范围内的提交
如分支历史为
1 | E---F---G---H---I---J topicA |
如果使用命令
1 | git rebase --onto topicA~5 topicA~3 topicA |
–onto <newbase> 选项表示以<newbase>为重放差异的基础。会将当前分支重置为 <newbase>,相当于
git reset --hard <newbase>
。
该命令的意思是找出 topicA~3
和 topicA
的差异,并以 topicA~5
为基础重放,操作的分支为 topicA
。
操作结果会删除 F 和 G 提交,最后提交历史变成:
1 | E---H'---I'---J' topicA |
其中 H’/I’/J’ 是原 H/I/J 的新版本