Git 进阶:rebase、cherry-pick 与冲突的艺术

团队协作久了,难免会遇到一些 Git 进阶场景:把几个零散 commit 合并成一个、把某个分支的特定提交挪过来、处理纠缠不清的冲突。这篇梳理几个高频操作。

rebase:整理提交历史的利器

rebase 是最容易让人害怕的命令,但理解了原理其实很简单 —— 它就是把你的提交"挪"到另一个分支的末尾。

1
2
3
# 把 feature 分支挪到 main 最新
git checkout feature
git rebase main

交互式 rebase 合并提交

更常用的是交互式 rebase 来整理历史:

1
git rebase -i HEAD~3

打开编辑器后会看到:

pick a1b2c3d 修复登录bug
pick d4e5f6g 添加日志
pick 7h8i9j0 再次修复登录bug

把后两个的 pick 改成 squash(或 s),它们就会被合并到前一个提交里。提交信息也可以一并整理。

心法:rebase 会改变 commit hash,所以已经 push 到公共分支的提交不要 rebase,否则同事会想打你。

cherry-pick:精准搬运

有时候你只想要另一个分支的某几个提交,不想要整个分支。这时候用 cherry-pick

1
2
git cherry-pick a1b2c3d      # 搬一个
git cherry-pick a1b2c3d..f6g7h8i9   # 搬一段(不含起点)

适合的场景:hotfix 在主分支修了,需要同步回开发分支;或者某功能在错误分支提交了,要挪到正确分支。

冲突解决

冲突本质上是 Git 不知道你想保留哪些内容,需要你介入。几个建议:

  1. 用 merge 工具:配置 mergetool,比手动编辑强百倍
  2. 小步提交:每次改动小一点,冲突概率和解决难度都低
  3. 先拉再推git pull --rebase 减少无意义的 merge commit

冲突标记长这样:

<<<<<<< HEAD
我这边的内容
=======
对方那边的内容
>>>>>>> feature-xxx

保留需要的部分,删掉标记,git add 后继续即可。

一个高效工作流

我现在常用的工作流是:feature 分支开发期间随便提交,准备合并前用 rebase -i 整理成几个有意义的提交,然后 rebase 到最新主分支,最后合并。这样主分支历史始终干净。

1
2
3
git rebase -i main        # 整理我的提交
git rebase main           # 同步主分支
git checkout main && git merge --ff-only feature  # 快进合并

写在最后

Git 是工具不是信仰,理解原理比死记命令重要。把这些进阶操作用熟了,日常协作会顺畅很多。