前言
看完本文,你可以用自己的语言解释
什么是git的变基
正文
我(jjq)正在自己的功能分支 dev_jjq
上开发新功能,而主分支 master
也在不断向前推进。
初始状态
一开始,我的工作是从 master
分支的最新提交(假设是提交 B
)切出来的。
css
dev_jjq
↓
A---B master
我后续在 dev_jjq
上做了两次提交(C
和 D
)。
css
C---D dev_jjq
/
A---B master
与此同时,我的同事把他完成的功能合并回了 master
,所以 master
分支也前进了,有了新的提交 E
。
css
C---D dev_jjq
/
A---B---E master
面临的问题
现在,我的分支历史已经和主分支分叉了。如果我现在想把自己的工作合并回 master
,可能会产生一个难看的合并提交,或者更糟------遇到冲突。
我希望我的提交历史看起来是清晰、线性的,就好像我是基于最新的 master
(最新的那就是E咯)开始工作一样,而不是从旧的 B
开始。
变基(Rebase)出场
这时,git rebase
上场。变基 的本质是改变我当前工作的根基。
我原本的"基"是提交 B
。通过变基,我可以把我的工作(C
和 D
)"移动"到新的"基"(也就是 master
现在指向的提交 E
)之上。
我在dev_jjq分支上执行下面的命令:
bash
git checkout dev_jjq # 确保我在自己的分支上
git rebase master # 将当前分支变基到 master 分支
Git 会非常智能地完成以下几步操作:
- 找到当前分支 (
dev_jjq
) 和目标基分支 (master
) 的共同祖先 (提交B
)。 - 临时保存当前分支相对于共同祖先的所有变更 (即提交
C
和D
引入的改动)。 - 将当前分支的指针快进 到目标"基"(提交
E
)。 - 在新的"基" 上,按顺序重新应用 之前保存的每一个变更,生成全新的提交 (我们叫它们
C'
和D'
)。这些新提交的内容和原来的C
、D
一样,但它们的"父提交"变了。
变基后的结果
变基完成后,历史就变成了这样:
css
C---D [原来的 dev_jjq,已经没用了]
/
A---B---E master
\
C'---D' dev_jjq
现在我的 dev_jjq
分支是从 E
开始的,历史变成了一条完美的直线,非常整洁。
最后一步:合并
现在,我就可以回到 master
分支并进行一次快进合并了:
bash
git checkout master
git merge dev_jjq
最终的历史记录:
css
A---B---E---C'---D' master, dev_jjq
这看起来就像是我按顺序完成了所有工作,历史清晰明了,没有多余的分叉和合并节点。
总结
所以,对我来说,变基(rebase)就是把我自己的 commits 从一个旧的基础点(比如旧的 master)上"拔起来",然后"接"到项目最新的基础点(新的 master)上去的过程。
让整个提交历史赏心悦目
这样做最大的好处是能让项目的提交历史保持一条干净的直线,更容易理解和追踪。而不是分叉来分叉去地显得很乱。