先来个故事
小白:前辈,我总是不太明白什么时候该用到 Git Rebase ,您能给我讲讲它的使用背景吗?
前辈:没问题,小白。Git Rebase 通常在几种情况下会特别有用。
首先,当我们想要保持提交历史的线性和整洁时。比如说,一个项目的开发过程中,分支比较多,如果直接合并分支,提交历史可能会显得很杂乱,有很多交叉和分叉。
小白:嗯,我能想象到那种混乱的情况。
前辈:然后呢,如果我们希望自己的分支看起来像是基于最新的主分支顺序开发的,而不是有很多合并的痕迹,Git Rebase 就能派上用场。
小白:这样确实能让代码的发展脉络更清晰。
前辈:还有啊,当团队有一定的代码规范,要求提交历史干净、易读,便于后续的代码审查和维护,Git Rebase 就成为了一个重要的工具。
小白:原来是这样,那在多人协作开发的项目中呢?
前辈:在多人协作中,如果每个人都能合理使用 Git Rebase ,可以减少很多不必要的冲突和合并的麻烦,提高整个团队的开发效率。
小白:这下我明白了,看来 Git Rebase 在很多情况下都能发挥很大的作用。
前辈:对呀,只要用对了地方,它能让我们的开发工作更顺利。
图解rebase
嘿,各位!咱们先通过几张简单易懂的提交节点图,来瞧瞧 Rebase 到底在搞啥名堂。 咱们弄出两个分支,一个叫 master,另一个叫 feature。这 feature 分支呀,是在提交点 B 那旮旯从 master 分支上拉出来的。 这 master 分支可有新动作,来了个新提交叫 M。而 feature 分支也不闲着,整了俩新提交,分别叫 C 和 D。
这时候,咱们切换到 feature 分支上,然后执行 rebase 命令。这就好比咱们在自己的分支 feature 上捣鼓了一阵子,准备从主干 master 那拉点最新的改动来。这场景就跟 git pull --rebase 差不多啦。
bash
# 这两条命令等价于git rebase master feature
git checkout feature
git rebase master
官方的原文解释:当 Rebase 操作的时候,Git 会从两个分支的共同祖先开始,把待变基分支上的修改给提取出来,然后让待变基分支指向基分支的最新提交,最后把刚才提取的修改放到基分支最新提交的屁股后面。
结合咱们这个例子解释解释:当在 feature 分支上执行 git rebase master 的时候,Git 会从 master 和 feature 的共同祖先 B 开始,把 feature 分支上的修改,也就是 C 和 D 这两个提交,先给提取出来。然后呢,让 feature 分支指向 master 分支的最新提交 M。最后把提取出来的 C 和 D 接到 M 后面。这里要注意接的方式哈,官方没讲太明白。实际上呢,会依次拿 M 分别跟 C、D 的内容比较,处理完冲突后就生成新的 C'和 D'。一定要记住哈,这新的 C'、D'跟之前的 C、D 可不一样啦,是咱们处理冲突之后的新玩意儿,feature 分支的指针最后当然也就指向 D'啦!
结合vscode
如果有冲突,根据提示进行相关代码合并。
如何在处理rebase过程中发现有多次变基的操作,可以结合下面的压缩提交进行处理。
rebase 的压缩提交
看着项目的提交历史,这提交历史太乱了吧,不利于后续新成员理解项目的发展过程。那么我们可以用 Rebase 压缩一些琐碎的提交,让历史更清晰。
运行git rebase -i head~x
x 是需要从头开始压缩的数目, -i 表示交互模式 按 i 进入vim的INSERT的输入模式 第二行开始 将pick更改为 fixup 或 f, 第一行的pick不能动,
按 ESC 退出 INSERT 模式,然后输入 :wq或者 :x保存并退出 运行 git push -f 更新新的commit(提交)
erlang
pick cc77998 commit4
pick 1821f6a commit3
pick ed09a6c commit2
pick 415a0be commit1
...
Rebase 与 Merge 的区别
- 合并历史:Merge 保留分支各自的提交历史,有明显合并节点;Rebase 使提交历史直线性,但可能模糊分支关系。
- 历史修改:Merge 保留原始提交,撤销合并较容易;Rebase 可能改变提交历史,撤销困难。
- 冲突处理:Merge 在整个分支层面处理冲突;Rebase 逐个提交处理冲突。
- 使用场景:Merge 适用于分支独立且需保留历史或有冲突;Rebase 适用于重写提交基于最新、保持线性和清晰历史。
无论用 Merge
还是 Rebase
,都要注意冲突等问题,提前备份代码,以防不可逆问题,同时还要结合团队的使用习惯进行决策。