使用场景

  1. 实现代码合并,避免使用 merge 合并分支时产生的 merge commit 污染分支历史记录。最常见的使用场景是在个人分支上开发完想要合并到主分支上前,使用 rebase 操作将主分支新的 commit 作为基底,避免使用 merge 多产生一个无用的 commit。
  2. 将最近的几次提交合并,保持分支的整洁。最常见的使用场景就是开发一个功能过程中有多个 commit,最后提交时合并成一个总的 commit。

原理

变基前:

变基前

变基后:

变基后

这里 master 是基分支,feature 是待变基分支,当执行 rebase 操作时,git 从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面。rebase 叫做变基意思就是待变基分支的基底变成基分支的最新节点,这里就表现为 feature 分支的基底变成 master 分支的 M 节点。

这里要注意新产生的 C' 和 D' 节点和原先的 C 和 D 节点是不同的(git 中两个节点的 commitid 不同两个节点就看作不同)。

命令

代码合并

git checout feature
git rebase master
git rebase master feature

两个命令效果是相同的,效果对应上面的例子。

合并多个 commit 为一个 commit

git rebase -i  [startpoint]  [endpoint]

其中-i的意思是--interactive,即弹出交互式的界面让用户编辑完成合并操作,[startpoint][endpoint]则指定了一个编辑区间,如果不指定[endpoint],则该区间的终点默认是当前分支HEAD所指向的 commit(注:该区间指定的是一个前开后闭的区间)。

执行命令后会进入 vim 界面修改 commit 记录:

pick 91398f93 d1
pick 65efc762 d2
pick b82e050d d3

# Rebase 4652f96d..b82e050d onto 4652f96d (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

pick:保留该 commit(都可以用首字母缩写代替,除了 exec 用 x)

reword:保留该 commit,但我需要修改该 commit 的注释

edit:保留该 commit,但我要停下来修改该提交(不仅仅修改注释)

squash:将该 commit 和前一个 commit 合并

fixup:将该 commit 和前一个 commit 合并,但我不要保留该提交的注释信息

exec:执行 shell 命令

drop:我要丢弃该 commit

vim 界面输入 :wq 保存退出,会进入一个新的 vim 窗口,在此可以进一步编辑新的 commit message,保存后 rebase 即可生效。

将某一段 commit 粘贴到另一个分支上

留坑,暂时用不到,想到再写

git merge 和 git rebase 的优缺点

  • git merge

    • 优点:不会破坏原分支的提交记录。
    • 缺点:会产生额外的提交记录,并进行两条分支线的合并。
  • git rebase

    • 优点:无需新增提交记录到目标分支,reabse 后可以直接将对象分支的提交历史加到目标分支上,形成线性提交历史记录,更加直观。
    • 缺点:不能在一个共享分支上进行 reabse 操作,会带来分支安全问题。

git merge 和 git rebase 的正确使用

  • 合代码到公共分支的时候使用 git merge,书写正确规范的 merge commits 留下记录。
  • 合代码到个人分支的时候使用 git rebase,可以不污染分支的历史提交记录,形成简介的线性记录。

注意事项

Git 官方文档中说“一旦分支中的提交对象发布到公共仓库,就干万不要对该分支进行衍合操作。”

在公共分支上尽量不要用 rebase 操作,而应该使用 merge,因为你使用 rebase 改变了之前节点,而可能影响到同时在使用相同节点的人。

关键就在于 rebase 操作是对 commit 的改写,当 commit 还没有提交到公共仓库时,自己怎么改写都可以,一旦提交到远程仓库再改写 commit,就会与别人的 commit 历史不同,这时 push 时需要push --force,这显然是不可接受的。

如果是只有自己使用的分支,因为对他人不会造成影响,rebase 后使用push --force是可以接受的,只要自己清楚使用这个命令的后果。

最后修改:2023 年 06 月 05 日
如果觉得我的文章对你有用,请随意赞赏