开发中经常遇到这种情况:要发版了,得确认功能分支是不是都合并到主分支了;或者线上出了bug,紧急修复后还得检查是否同步到了其他分支。
大多数人第一反应是用git log或git diff,但这俩命令在复杂的提交历史面前经常"翻车",特别是遇到cherry-pick操作时,输出的信息能把人绕晕。
今天就来聊聊怎么优雅地比较分支差异,从简单需求开始,一步步搞定各种复杂场景。

先从简单的开始

假设我们要找:在master分支里有,但在phase2分支里没有的,提交信息包含"270851"的所有提交。
这种需求很常见,用Git的范围选择功能就能搞定:
git log phase2..master --grep="270851" --oneline
解释一下:
phase2..master:显示从master能追溯到,但从phase2追溯不到的提交--grep="270851":筛选提交信息包含这个字符串的记录--oneline:简洁输出,只显示哈希值和标题
这样就能工作了,但如果想看更详细的信息,比如提交人和时间:
git log phase2..master --grep="270851" --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:"%h - %an, %ad : %s"
通过--pretty=format可以自定义输出格式,想显示什么就显示什么。
实际工作中要比较远程分支
团队开发时,我们真正关心的是远程仓库的分支状态,不是本地的。直接比较本地分支可能因为没及时更新而出错。
正确的做法是先同步远程信息:
# 先拉取最新的远程信息(不会改动本地代码)
git fetch origin
git fetch很安全,只更新远程分支的指针,不会动你的工作区。
然后比较远程分支:
git log origin/phase2..origin/master --grep="270851" --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:"%h - %an, %ad : %s"
就是把分支名前面加个origin/,这样比较的就是远程仓库的真实情况了。
最坑的问题:cherry-pick导致的"幽灵提交"

运行上面的命令后,你可能会遇到一个很诡异的现象:明明两个分支都有的提交,为什么还是被显示出来了?
这就是Git里最经典的坑之一,罪魁祸首通常是cherry-pick。
原因很简单:Git是通过Commit ID(SHA-1哈希值)来识别提交的。当你把一个提交从A分支cherry-pick到B分支时,Git实际上在B分支创建了一个全新的提交。虽然代码改动、作者、提交信息都一样,但Commit ID完全不同!
所以git log origin/phase2..origin/master会认为master上这个新创建的提交是phase2没有的,就错误地显示出来了。
解决办法:Git提供了专门的参数来处理这种情况:
git log origin/phase2...origin/master --cherry-pick --right-only --grep="270851"
注意几个关键变化:
...(三个点):显示两个分支的"对称差",就是A有B没有,或者B有A没有的提交--cherry-pick:这是关键!当Git发现两个分支有代码改动完全一样的提交时(一个是另一个cherry-pick的结果),就会把这对提交"抵消"掉--right-only:因为对称差会显示两边的差异,我们只要右边分支(master)的
更多实用技巧
掌握了核心原理,就可以组合出各种实用命令了。
按作者筛选:
git log origin/phase2...origin/master --cherry-pick --right-only --author="张三"
排除合并提交(这些通常是噪音):
git log origin/phase2...origin/master --cherry-pick --right-only --author="张三" --no-merges
合并提交往往不是我们关心的代码变更,用--no-merges可以过滤掉,让输出更清爽。
我的常用命令模板
经过这么多年的踩坑,我总结出了一个万能模板:
git log <分支A>...<分支B> \
--cherry-pick \
--right-only \
--author="<作者名>" \
--grep="<关键词>" \
--no-merges \
--date=format:'%Y-%m-%d %H:%M:%S' \
--pretty=format:"%h - %an, %ad : %s"
根据需要删减参数就行了。比如:
# 找master比phase2多的所有提交(排除合并提交)
git log origin/phase2...origin/master --cherry-pick --right-only --no-merges
# 找特定作者的提交
git log origin/phase2...origin/master --cherry-pick --right-only --author="李四" --no-merges
小结
Git分支比较看起来简单,但实际用起来坑不少。特别是cherry-pick这种操作,经常让人摸不着头脑。
记住几个要点:
- 比较远程分支前先
git fetch - 遇到cherry-pick用
--cherry-pick参数 - 用
--no-merges过滤掉合并提交的噪音 - 灵活组合
--author、--grep等筛选条件
掌握了这些技巧,以后再也不用为分支比较头疼了。
8907

被折叠的 条评论
为什么被折叠?



