2. Git Rebase
简单粗暴地说,git rebase
会把你的整个特性分支移动到主分支的最新提交之上。它会为原特性分支的每个提交创建全新的提交。
让我们通过实际操作理解 rebase 的工作原理:
git clone https://github.com/yourusername/yourrepo.git
git branch testBranch1
git branch testBranch2
在 testBranch1
分支创建新文件并提交:
git add .
git commit -m "feat: 添加新功能模块"
git push --set-upstream origin testBranch1
git log
执行后输出如下(示意图):
commit 3a4b5c6d (HEAD -> testBranch1, origin/testBranch1)
Author: Your Name <youremail@example.com>
Date: Mon May 16 10:00:00 2022 +0800
feat: 添加新功能模块
现在尝试将此分支 rebase 到 main
分支:
git rebase main
由于 main
分支没有新提交,输出如下:
Current branch testBranch1 is up to date.
接下来将特性分支合并到主分支:
git checkout main
git merge testBranch1
git push
git log
输出显示特性分支的提交 ID 保持不变(类似快进合并):
commit 3a4b5c6d (HEAD -> main, origin/main, origin/testBranch1, testBranch1)
Author: Your Name <youremail@example.com>
Date: Mon May 16 10:00:00 2022 +0800
feat: 添加新功能模块
现在处理 testBranch2
分支(它缺少 testBranch1
的提交):
git checkout testBranch2
git add .
git commit -m "fix: 修复登录问题"
git push --set-upstream origin testBranch2
git log
输出:
commit 7e8f9a0b (HEAD -> testBranch2, origin/testBranch2)
Author: Your Name <youremail@example.com>
Date: Mon May 16 11:00:00 2022 +0800
fix: 修复登录问题
执行 rebase 操作:
git rebase main
由于 main
已有新提交,输出变为:
Successfully rebased and updated refs/heads/testBranch2.
现在合并到主分支,注意rebase 前后提交 ID 会改变:
git checkout main
git merge testBranch2
git push
git log
输出显示新提交 ID:
commit c1d2e3f4 (HEAD -> main, origin/main)
Author: Your Name <youremail@example.com>
Date: Mon May 16 11:00:00 2022 +0800
fix: 修复登录问题
查看线性提交历史:
git log --graph --oneline
输出(示意图):
* c1d2e3f4 (HEAD -> main, origin/main) fix: 修复登录问题
* 3a4b5c6d feat: 添加新功能模块
* 1a2b3c4d (origin/main) init: 初始提交
3. Git Merge
git merge
会找到两个分支的共同基提交,然后将两个分支的提交序列应用到基提交上完成合并。
创建新仓库和特性分支:
git clone https://github.com/yourusername/yourrepo.git
git branch testBranch1
git branch testBranch2
在 testBranch1
创建文件并提交:
git add .
git commit -m "feat: 添加用户管理"
git push --set-upstream origin testBranch1
git log
输出:
commit 5f6g7h8i (HEAD -> testBranch1, origin/testBranch1)
Author: Your Name <youremail@example.com>
Date: Mon May 16 12:00:00 2022 +0800
feat: 添加用户管理
合并到主分支:
git checkout main
git merge testBranch1
git push
git log
输出(HEAD 指向 main):
commit 5f6g7h8i (HEAD -> main, origin/main, origin/testBranch1, testBranch1)
Author: Your Name <youremail@example.com>
Date: Mon May 16 12:00:00 2022 +0800
feat: 添加用户管理
现在处理 testBranch2
(主分支已有新提交):
git checkout testBranch2
git add .
git commit -m "docs: 更新API文档"
git push --set-upstream origin testBranch2
git log
输出:
commit 9j0k1l2m (HEAD -> testBranch2, origin/testBranch2)
Author: Your Name <youremail@example.com>
Date: Mon May 16 13:00:00 2022 +0800
docs: 更新API文档
合并到主分支:
git checkout main
git merge testBranch2
git log
输出显示新增合并提交:
commit n3o4p5q6 (HEAD -> main, origin/main)
Merge: 5f6g7h8i 9j0k1l2m
Author: Your Name <youremail@example.com>
Date: Mon May 16 13:30:00 2022 +0800
Merge branch 'testBranch2'
commit 9j0k1l2m (origin/testBranch2, testBranch2)
Author: Your Name <youremail@example.com>
Date: Mon May 16 13:00:00 2022 +0800
docs: 更新API文档
commit 5f6g7h8i
Author: Your Name <youremail@example.com>
Date: Mon May 16 12:00:00 2022 +0800
feat: 添加用户管理
查看分支图:
git log --graph --oneline
输出(示意图):
* n3o4p5q6 (HEAD -> main, origin/main) Merge branch 'testBranch2'
|\
| * 9j0k1l2m (testBranch2, origin/testBranch2) docs: 更新API文档
* | 5f6g7h8i feat: 添加用户管理
|/
* 1a2b3c4d init: 初始提交
4. 使用场景对比
选择 rebase 还是 merge 取决于具体需求:
- 需要线性历史时:使用 rebase(适合个人分支或特性开发)
- 多人协作时:谨慎使用 rebase,特别是已推送到公共仓库的提交
- 保留完整合并信息时:使用 merge(适合团队协作和代码审查)
⚠️ 踩坑警告:对公共仓库的已推送提交执行 rebase 会导致提交 ID 改变,可能造成其他开发者的分支与你的分支产生分歧,引发合并冲突。
5. 总结
本文深入对比了 Git 中两个核心分支整合操作:
- Rebase:重写提交历史,创建线性提交链
- Merge:保留真实提交历史,生成合并提交
作为有经验的开发者,理解这两种操作的本质差异能帮你:
- 根据项目需求选择合适的分支策略
- 避免团队协作中的历史污染问题
- 更高效地管理代码变更流程
记住:没有绝对的好坏,只有场景的适配。在私有分支大胆 rebase,在公共分支谨慎 merge。