0%

git的cherry-pick的使用

对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求。一种情况是,你需要另一个分支的所有代码变动,那么就采用合并(git merge 或 git rebase),另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用(git cherry-pick) 。

所以 cherry-pick 是 摘取特定 commit 到 自己的分支上 (樱桃采摘)。

1. 使用

1
2
3
4
5
6
7
8
9
10
11
12
# 应用单个提交
git cherry-pick <commit-hash>

# 应用多个提交
git cherry-pick <commit1> <commit2> <commit3>

# 应用提交范围(不包含 start-commit)
git cherry-pick <start-commit>..<end-commit>

# 应用提交范围(包含 start-commit)
git cherry-pick <start-commit>^..<end-commit>

1.1 现象

上面命令就会将指定的提交commitHash,应用于当前分支。这会在当前分支产生一个新的提交,当然它们的哈希值会不一样。

  • A分支log (add 1 和 add 2)
1
2
3
* cf976d8 - (HEAD -> master, origin/master, origin/HEAD) add 2 (2 minutes ago) <liuwei>
* 07444e6 - add 1 (2 minutes ago) <liuwei>
* 73a2b7f - (cherry) rm citycode (4 minutes ago) <liuwei>
  • B分支操作 (add 1)
1
git cherry-pick 07444e6
  • 然后再看B分支log: (选中了特定的 commit 到我的分支)
1
2
* d38ece4 - (HEAD -> cherry) add 1 (11 seconds ago) <liuwei>
* 73a2b7f - rm citycode (5 minutes ago) <liuwei>

1.2 其他选项

1
2
3
# 编辑提交信息
git cherry-pick -e <commit-hash>
git cherry-pick --edit <commit-hash>

1.3 代码冲突

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 执行 cherry-pick(可能出现冲突)
git cherry-pick abc1234

# 2. 查看冲突文件
git status

# 3. 手动解决冲突
# 编辑冲突文件,删除冲突标记

# 4. 添加解决后的文件
git add <resolved-files>

# 5. 继续 cherry-pick
git cherry-pick --continue

# 或者放弃 cherry-pick
git cherry-pick --abort

2. 停止使用cherry-pick

cherry-pick 可能产生比冲突更严重的问题:该有冲突却没有冲突。

1

如上图,apple 代表这个功能是上线状态,berry 代表这个功能是下线状态。

然后我们发现了一些 bug,需要将该功能紧急下线,我们:

  • 在 feature 分支上下线该功能(F2):apple -> berry
  • 然后将该操作 cherry-pick 到 master(M2),现在 master 上该功能也下线了
  • 然后我们在 feature 分支上进行了 bug 修复,最终解决了 bug,我们在 feature 分支上将该功能上线(F3):berry -> apple
  • 然后我们决定将 featuter 的 bug 修复 merge 到 master
  • merge 顺利完成,没有冲突。但是:这行代码仍然是berry,下线状态

原因分析:

M3(berry) 和 F3(apple) 的最近公共祖先是 A(apple),因此 git 认为 feature 分支并未修改 apple 的值,master 分支的berry是最新的修改。

结果合并后 master 分支上这行代码还是 berry,我们的功能在 master 上还是下线状态。

2.1 经验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ❌ 不要在公共分支直接 cherry-pick
git checkout main
git cherry-pick feature-commit
git push origin main # 危险!

# ❌ 不要 cherry-pick 大量提交而不测试
git cherry-pick commit1 commit2 commit3 commit4 commit5
# 应该逐个或小批量处理

# ❌ 不要忽略冲突
git cherry-pick abc1234
# 出现冲突后不要强制解决
git add .
git cherry-pick --continue # 确保理解冲突原因

2.2 替代方案

  • 交互式 Rebase (推荐)
  • Format-patch + Apply

3. 参考资料

可以加首页作者微信,咨询相关问题!