多合并场景下Git日志查询异常问题排查
为什么git log v0.2..HEAD会带出一堆旧提交?
默认情况下,git log A..B的规则是:所有能从B(当前HEAD)追到,但从A(v0.2)追不到的提交都会显示。
在你的GitFlow流程里,肯定存在这种情况:某个功能分支(比如feat01)在v0.2打标签之前就从主分支分出去了,之后等到v0.2发布完才合并回master。这时候,feat01上的所有旧提交,因为分叉点早于v0.2,所以从v0.2根本追不到它们,但合并到master之后,从当前HEAD又能追到,自然就被默认的git log列出来了——这就是你看到“大量之前合并的提交”的原因。
为什么--ancestry-path更接近预期,但感觉有缺失?
git log --ancestry-path v0.2..HEAD会严格筛选:只有既在HEAD的祖先链里,又属于v0.2后代链的提交才会显示。简单说,它只留v0.2之后新产生的提交,以及合并提交本身——但那些分叉在v0.2之前的功能分支上的旧提交,会被直接过滤掉,只有合并到master的那个合并节点会保留。
你说“会缺少部分合并提交(不过所有合并提交都存在)”应该是表述上的小误差,实际是合并提交都在,但合并进来的旧分支提交被剔除了,这完全是--ancestry-path的设计逻辑。
为啥简单测试复现不了?
因为你测试时创建的功能分支,大概率都是在v0.2之后才从主分支分出去的,这些分支的提交本身就是v0.2的后代,所以默认的git log只会显示你预期的内容。但实际工作中你有“旧分支在新标签之后才合并”的操作,这才导致了和测试场景的差异。
要拿到精准结果该用什么命令?
如果你的需求是只看v0.2之后master主线上的提交(包括合并提交,不带合并进来的旧分支内容),直接加--first-parent参数就行:
git log --first-parent --oneline v0.2..HEAD
这个参数会让Git只沿着主分支的第一个父提交回溯,说白了就是只追踪master本身的历史,完全忽略合并进来的分支的提交细节,正好匹配你想要的结果。
内容的提问来源于stack exchange,提问作者ochurlaud

