使用git rebase 的工作场景
git 相较于svn/perforce等版本管理工具, git 分支的灵活性成为一个巨大的优势. 带来的麻烦在于假设团队没有采用rebase合并方式进行提交时, 当每个成员开发各自的功能拉一个开发分支再合并到主干时, 主干的提交记录就会变成一团乱麻.
采用非rebase 方式合并会出现什么问题?
假设我们有一个主分支 main 和一个功能分支 feature:
-
初始状态:
A---B---C (main) \ D---E (feature) -
开发进行:
main分支上有提交A,B,C。feature分支从B分叉,并有提交D,E。
-
合并
feature到main:- 使用
git merge feature合并分支。
- 使用
-
合并结果:
A---B---C---M (main) \ / D---E (feature)
造成合并记录非线性原因如下:
- 合并提交
M:M是合并提交,包含main和feature的更改。 - 分叉历史:
D和E的开发历史与C并行存在。 - 图形结构:历史不是简单的一条线,而是图形结构。
这种非线形的合并让回退变得非常的麻烦, 开发过程中就出现过策划团队提交错误想要回退到之前的某个版本, 结果因为git merge 提交并不是线性的,所以无法直接回退到某个版本,最后只好手动修改通过重新提交的方法复原版本.
所以在开发分支的历史记录存在必要性意义不大的前提下, 保持主干记录的线性提交一方面保持了线性提交记录的整洁, 另一方面也为后续版本回退提供了方便.
git rebase 合并提交方式能让提交记录保持干净的线性提交历史记录.
git rebase 原理
git rebase 的原理是将一个分支上的提交“重新应用”到另一个分支的基础上,从而创建一个线性的提交历史。
工作流程
-
找到共同祖先:
- Git 找出当前分支与目标分支的共同祖先。
-
提取当前分支的提交:
- 从共同祖先开始,提取当前分支的每个提交,保存为补丁。
-
应用补丁:
- 逐个将这些补丁应用到目标分支最新的提交上。
-
重写历史:
- 生成新的提交,相当于当前分支的提交历史被“移动”到目标分支之上。
这样所有提交看起来像是在目标分支之后顺序提交的,使得历史记录更加易读.
如何用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 值,因此应避免在公共分支上使用。