我试图找出如何在两个标记之间打印出一个git日志,排除在一个特定合并提交中合并的所有提交。
例如。如果我的提交日志看起来像这样:
TAGA TAGB
| C---F---H---K Q---T---V |
v / \ / \ v
A---B---D---G---J---L---M---O---R---U---W---X
\ / \ /
E---I N---P---S
我希望在merge-commit L 中排除引入主干的所有提交。 (所以在这个例子中,我想排除 C,F,H,K )。
目前我的git行看起来像这样:
git log --oneline --no-merges TAGB ^TAGA
将列出两个标签之间的所有提交(注意,我不包括合并 - 提交本身,这就是J,L,U和W不存在的原因。):
A,B,C,D,E,F,G,H,I,K,M,N,O,P,Q,R,S,T,V,X
有没有人知道如何排除C,F,H& K?即:
A,B,D,E,G,I,M,N,O,P,Q,R,S,T,V,X
任何帮助都将不胜感激。
答案 0 :(得分:1)
没有廉价的,一体化的Git表达方式来做到这一点。图形行走代码仅在--first-parent
之后(如在Vimsha's answer中)或遵循合并的所有父项。因此,排除^K
(或^L^2
或其他名称提交K
的方法)具有修剪所有提交的副作用{{1} },而不仅仅是K
序列。
我们仍然可以获得我们想要的列表,它只需要更多的工作。首先,生成有趣的哈希的完整列表:
C--F--H--K
(请注意tempfile1=$(mktemp)
git rev-list --no-merges TAGB ^TAGA > $tempfile1
和git log
几乎是相同的命令,并且是从同一个源构建的;它们之间的主要区别是git rev-list
只打印完整的哈希ID) 。接下来,生成要排除的哈希的完整列表:
rev-list
(您如何找到tempfile2=$(mktemp)
git rev-list --no-merges K ^B > $tempfile2
?我想知道,您是如何找到B
的?{但是一旦您找到了K
K
},并且知道它是L^2
,B
是L^
和L^2
之间的合并基础,因此您可以使用git merge-base
找到其ID这两个名字。)在这个例子中我们并不需要--no-merges
,但在更复杂的例子中,我们可能也想要它和/或--first-parent
。 (编辑以添加注释:当然我们从不需要--no-merges
:这是排除列表,并且合并已被排除。)
现在我们想要“在tempfile 1中找到所有哈希值,不包括tempfile2中的任何哈希值”,执行此操作的Unix工具集命令是comm
。 (Linux变体要求对输入进行排序,并实际检查,以便您需要--nocheck-order
来解决这个问题。comm
使用的基础算法只需要文件“行将在相同的顺序中,这将是这种情况。或者,您可以对两个文件进行排序:例如sort -o $tempfile1 $tempfile1
。但这很昂贵且不必要。”
comm
实用程序读取file1和file2,它们应按词法排序, 并生成三个文本列作为输出:仅在file1中的行;线 仅在file2中;和两个文件中的行。
我们需要“仅在file1中的行”,即丢弃出现在file2中的行。这将是“文本第1列”,这似乎需要更多的后期处理,但幸运的是:
-1
禁止打印第1列。
-2
禁止打印第2列。
-3
禁止打印第3列。
所以我们压制第2列和第3列:
comm -23 $tempfile1 $tempfile2
这会在标准输出上生成我们希望git log
显示的完整SHA-1列表。
最后一步是将此输出挂钩到git log --oneline
,这很容易:
git log --oneline --stdin --no-walk
--no-walk
阻止git log
(或git rev-list
)完全执行提交图,这是我们想要的,因为我们正在为它提供每个提交访问的完整列表。我们从--stdin
获得的修订版中的comm
个Feed。
我们现在需要的是一个小的shell包装来清理临时文件:
#! /bin/sh -e
# note the -e option -- this avoids the need for a lot of || exit
# clauses (to handle any early failures)
tempfile1=$(mktemp)
trap "rm -f $tempfile1" 0 1 2 3 15
tempfile2=$(mktemp)
trap "rm -f $tempfile1 $tempfile2" 0 1 2 3 15
git rev-list --no-merges TAGB ^TAGA > $tempfile1
git rev-list --no-merges K ^B > $tempfile2
comm -23 $tempfile1 $tempfile2 | git log --oneline --stdin --no-walk
(当然,这都是未经测试的,并且它省略了您想要查找的地方,或者作为参数获取您希望单侧排除的两个标记和合并提交L
,以及侧面编号,1或2.根据需要加入这个。)
答案 1 :(得分:0)
尝试--first-parent
git log --oneline --no-merges --first-parent TAGB ^TAGA
文档here
- first-parent在看到合并提交时仅跟随第一个父提交。查看时,此选项可以提供更好的概述 特定主题分支的演变,因为合并到主题中 分支往往只是关于从时间上调整到更新的上游 时间,此选项允许您忽略各个提交 通过这样的合并带来了你的历史。不能合并 --bisect。