git rebase 替代 git merge 实现分支合并
0x0 引言
网络上关于 git rebase 使用的教程不少,其中一篇把远端操作混入了进来,绘制的 commit tree 放了 hash 码也导致乱乱的,个人觉得不妥。git rebase 的理解应该是和远端独立的,用1~2个数字和字母来替代 hash 码会更加直观;同时结合了 git kraken 这一 GUI 软件进行实践,记录如下。
0x1 git merge 是怎样合并分支的
假设 main 分支有 M1, M2 两个 commit 节点,分支 boxfilter 是基于 M2 节点派生出来,后续创建了 B1 和 B2 节点完成 boxfilter 功能的开发,现在打算把 B1 B2 合并到 main 分支的 M4 节点之后:
最直接的方法是使用 git merge 命令:
git checkout main
git merge boxfilter
或者,在 GitKraken 软件中把 boxfilter 分支拖拽到 main 分支上,选择 "merge boxfilter into main"。总之,会生成一个新的节点:
0x2 git rebase 是怎么合并分支的
实际上可以避免 merge 节点的产生;它本身并没有什么意义;用 git rebase 替代 git merge 可以达成这样的目标(实际上 rebase 后还需要额外执行一些操作,才是完全的“不创建新节点的合并”)。
具体说来,首先是 git rebase:把 boxfilter 分支上的 B1、B2节点剥下来放到临时区,让 boxfilter 分支的拿到 M3、M4 的连接信息,然后从临时区把 B1、B2 连接到 M4 后面:
git rebase main boxfilter
# 这条命令等价于:
# git checkout boxfilter
# git rebase main
# 如果发生冲突,手动解决后需要执行 git rebase --continue
注意:此时对于 boxfilter 分支来说是发生了变化,是塞入了 M3、M4;对于 main 分支来说并没有变化。不过由于 main 分支和 boxfilter 已经是一条线,可以快速合并(不会创建新节点),因此执行:
git checkout main
git merge boxfilter --ff-only
或者在 GitKraken 图形界面工具中,把 boxfilter 分支拖拽到 main 分支,选择 "fast-forward main to boxfilter"。则得到的 commit tree 中的变化是,main 分支快进到 B2 节点,完成 “不创建新节点的 merge”:
0x3 进一步的操作
到这里,已经完成了干净的分支合并,并且只依赖于本地操作。
进一步,还可以推送 main 分支到远端,以及 删除 boxfilter 分支,删除 boxfilter 对应的远程分支(如果存在跟踪的远程分支的话)。具体命令为:
git push origin main
git br -D boxfilter
git push --delete origin boxfilter
总结
本文是对 git rebase 用于分支操作的基本用法讲解,用 commit tree 的变化图,直观的展示了基本原理。涉及到的命令汇总如下:
# 把 main 分支里比 boxfilter 分支多出来的东西,塞到 boxfilter 尾巴节点之前
# 看起来就像是把 boxfilter 分支的东西,接到 main 分支上;但这时 main 分支不受影响
git rebase main boxfilter
# 这里可能要解决冲突,解决后要 git rebase --continue
# 这里可能觉得 boxfilter 分支尾巴节点过多,希望合并
# 则执行 git rebase -i xxx ,然后 squash
# 切换到 main 分支,以快速前进方式,合并 boxfilter 分支
git checkout main
git merge boxfilter --ff-only
# 可选;推送 main 分支到 remote
git push
# 可选;删除本地分支
git br -D boxfilter
# 可选;删除远程分支
git push origin --delete boxfilter