为什么我们要用git rebase 方式?

161 阅读3分钟

使用git rebase 的工作场景

git 相较于svn/perforce等版本管理工具, git 分支的灵活性成为一个巨大的优势. 带来的麻烦在于假设团队没有采用rebase合并方式进行提交时, 当每个成员开发各自的功能拉一个开发分支再合并到主干时, 主干的提交记录就会变成一团乱麻.

采用非rebase 方式合并会出现什么问题?

假设我们有一个主分支 main 和一个功能分支 feature

  1. 初始状态

    A---B---C  (main)
         \
          D---E  (feature)
    
    
  2. 开发进行

    • main 分支上有提交 ABC
    • feature 分支从 B 分叉,并有提交 DE
  3. 合并 feature 到 main

    • 使用 git merge feature 合并分支。
  4. 合并结果

    A---B---C---M  (main)
         \     /
          D---E  (feature)
    
    

造成合并记录非线性原因如下:

  • 合并提交 MM 是合并提交,包含 main 和 feature 的更改。
  • 分叉历史D 和 E 的开发历史与 C 并行存在。
  • 图形结构:历史不是简单的一条线,而是图形结构

这种非线形的合并让回退变得非常的麻烦, 开发过程中就出现过策划团队提交错误想要回退到之前的某个版本, 结果因为git merge 提交并不是线性的,所以无法直接回退到某个版本,最后只好手动修改通过重新提交的方法复原版本.

所以在开发分支的历史记录存在必要性意义不大的前提下, 保持主干记录的线性提交一方面保持了线性提交记录的整洁, 另一方面也为后续版本回退提供了方便.

git rebase 合并提交方式能让提交记录保持干净的线性提交历史记录.

git rebase 原理

git rebase 的原理是将一个分支上的提交“重新应用”到另一个分支的基础上,从而创建一个线性的提交历史。

工作流程
  1. 找到共同祖先

    • Git 找出当前分支与目标分支的共同祖先。
  2. 提取当前分支的提交

    • 从共同祖先开始,提取当前分支的每个提交,保存为补丁。
  3. 应用补丁

    • 逐个将这些补丁应用到目标分支最新的提交上。
  4. 重写历史

    • 生成新的提交,相当于当前分支的提交历史被“移动”到目标分支之上。

这样所有提交看起来像是在目标分支之后顺序提交的,使得历史记录更加易读.

如何用rebase合并提交

1. 更新本地 Git 配置以启用 rebase
git config —-edit

在编辑器中设置 rebase = true,然后保存退出。

2. 压缩多次提交为一个: 使用交互式 rebase 来合并提交:
git rebase -i HEAD~2

其中HEAD~N为需要压缩的提交的前N次记录

在交互式 rebase 中,选择 squash 或 s 来压缩提交。

3. 假设我们要将开发分支合并到dev分支,你可以使用以下步骤:

首先确保你在dev分支上:git checkout dev 然后执行rebase操作:git rebase <开发分支名>

这将会将开发分支的更改以线性的方式合并到dev分支上。如果在rebase的过程中出现冲突,你需要解决冲突后执行 git rebase --continue 直到完成整个rebase过程。

4. 提交更改
git push -f
5. 查看是否为线性提交
 git log —graph 
 

也可以用tig工具查看提交历史

注意事项

由于 rebase 会改变提交的 SHA 值,因此应避免在公共分支上使用。