Git 日志:排除来自特定合并的提交
Git log: excluding commits from a specific merge
我正在尝试找出如何在两个标签之间打印 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
而且我想要排除在合并提交时引入主干的所有提交 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
如有任何帮助,我们将不胜感激。
尝试--first-parent
git log --oneline --no-merges --first-parent TAGB ^TAGA
文档here
--first-parent Follow only the first parent commit upon seeing a merge commit. This option can give a better overview when viewing the
evolution of a particular topic branch, because merges into a topic
branch tend to be only about adjusting to updated upstream from time
to time, and this option allows you to ignore the individual commits
brought in to your history by such a merge. Cannot be combined with
--bisect.
没有便宜的、一体化的 Git 表达方式来做到这一点。图遍历代码要么仅遵循 --first-parent
(如 ),要么遵循合并的所有父项。因此,排除性^K
(或^L^2
或其他命名提交K
的方式)具有修剪所有提交的副作用K
,而不仅仅是 C--F--H--K
序列。
我们仍然可以获得我们想要的列表,只是需要更多的工作。首先,生成有趣哈希的完整列表:
tempfile1=$(mktemp)
git rev-list --no-merges TAGB ^TAGA > $tempfile1
(请注意 git log
和 git rev-list
几乎是相同的命令,并且是从相同的来源构建的;它们之间的主要区别在于 rev-list
只是打印完整的哈希ID)。接下来,生成要排除的完整哈希列表:
tempfile2=$(mktemp)
git rev-list --no-merges K ^B > $tempfile2
(你是怎么找到 B
的?好吧,我想知道,你一开始是怎么找到 K
的?——但是一旦你 有了 找到 K
,并且知道它是 L^2
,B
是 L^
和 L^2
之间的合并基础,所以你可以找到它的 ID git merge-base
和那两个名字。)在这个例子中我们真的不需要 --no-merges
但在更复杂的例子中我们可能也需要它 and/or --first-parent
。 (编辑以添加注释:当然我们永远不需要 --no-merges
:这是一个排除列表,合并已被排除。)
现在我们需要 "all hashes found in tempfile 1, excluding any hashes that are in tempfile2",执行此操作的 Unix 工具集命令是 comm
。 (Linux 变体要求对输入进行排序,实际上 检查 ,因此你需要 --nocheck-order
来打败它。[=35 的底层算法=] 使用只需要文件的行按 相同的 顺序,情况就是如此。或者,您可以对两个文件进行排序:例如 sort -o $tempfile1 $tempfile1
。但是既昂贵又不必要。)
The comm
utility reads file1 and file2, which should be sorted lexically,
and produces three text columns as output: lines only in file1; lines
only in file2; and lines in both files.
我们需要 "lines only in file1",即丢弃出现在 file2 中的行。那将是 "text column 1",这似乎需要更多的 post 处理,但幸运的是:
-1
Suppress printing of column 1.
-2
Suppress printing of column 2.
-3
Suppress printing of column 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
.
获得的修订
我们现在只需要一点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。根据需要考虑一下。)
我正在尝试找出如何在两个标签之间打印 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
而且我想要排除在合并提交时引入主干的所有提交 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
如有任何帮助,我们将不胜感激。
尝试--first-parent
git log --oneline --no-merges --first-parent TAGB ^TAGA
文档here
--first-parent Follow only the first parent commit upon seeing a merge commit. This option can give a better overview when viewing the evolution of a particular topic branch, because merges into a topic branch tend to be only about adjusting to updated upstream from time to time, and this option allows you to ignore the individual commits brought in to your history by such a merge. Cannot be combined with --bisect.
没有便宜的、一体化的 Git 表达方式来做到这一点。图遍历代码要么仅遵循 --first-parent
(如 ^K
(或^L^2
或其他命名提交K
的方式)具有修剪所有提交的副作用K
,而不仅仅是 C--F--H--K
序列。
我们仍然可以获得我们想要的列表,只是需要更多的工作。首先,生成有趣哈希的完整列表:
tempfile1=$(mktemp)
git rev-list --no-merges TAGB ^TAGA > $tempfile1
(请注意 git log
和 git rev-list
几乎是相同的命令,并且是从相同的来源构建的;它们之间的主要区别在于 rev-list
只是打印完整的哈希ID)。接下来,生成要排除的完整哈希列表:
tempfile2=$(mktemp)
git rev-list --no-merges K ^B > $tempfile2
(你是怎么找到 B
的?好吧,我想知道,你一开始是怎么找到 K
的?——但是一旦你 有了 找到 K
,并且知道它是 L^2
,B
是 L^
和 L^2
之间的合并基础,所以你可以找到它的 ID git merge-base
和那两个名字。)在这个例子中我们真的不需要 --no-merges
但在更复杂的例子中我们可能也需要它 and/or --first-parent
。 (编辑以添加注释:当然我们永远不需要 --no-merges
:这是一个排除列表,合并已被排除。)
现在我们需要 "all hashes found in tempfile 1, excluding any hashes that are in tempfile2",执行此操作的 Unix 工具集命令是 comm
。 (Linux 变体要求对输入进行排序,实际上 检查 ,因此你需要 --nocheck-order
来打败它。[=35 的底层算法=] 使用只需要文件的行按 相同的 顺序,情况就是如此。或者,您可以对两个文件进行排序:例如 sort -o $tempfile1 $tempfile1
。但是既昂贵又不必要。)
The
comm
utility reads file1 and file2, which should be sorted lexically, and produces three text columns as output: lines only in file1; lines only in file2; and lines in both files.
我们需要 "lines only in file1",即丢弃出现在 file2 中的行。那将是 "text column 1",这似乎需要更多的 post 处理,但幸运的是:
-1
Suppress printing of column 1.
-2
Suppress printing of column 2.
-3
Suppress printing of column 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
.
我们现在只需要一点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。根据需要考虑一下。)