Git日志:从特定合并中排除提交

Git日志:从特定合并中排除提交,git,git-log,Git,Git Log,我正在尝试解决如何在两个标记之间打印git日志,排除在一个特定合并提交中合并的所有提交 比如说。如果我的提交日志如下所示: TAGA TAGB | C---F---H---K Q---T---V | v / \ / \ v A---B---D---G---J---L---M---O---

我正在尝试解决如何在两个标记之间打印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
git log --oneline --no-merges TAGB ^TAGA
我希望a排除在merge commitL时引入主干的所有提交。(在这个例子中,我想排除C,F,H,K

目前我的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
git log --oneline --no-merges TAGB ^TAGA
这将列出两个标记之间的所有提交(注意,我不包括合并提交本身,这就是为什么J、L、U&W不存在的原因):

有人知道排除C、F、H和K的方法吗?i、 e:

A,B,D,E,G,I,M,N,O,P,Q,R,S,T,V,X
任何帮助都将不胜感激。

请尝试
--第一位家长

git log --oneline --no-merges --first-parent TAGB ^TAGA
文件

--第一个父级在看到合并提交时仅跟随第一个父级提交。此选项可以在查看时提供更好的概览 特定主题分支的演变,因为合并到一个主题中 分支机构往往只是随时调整以适应更新的上游 此选项允许您忽略单个提交 通过这样的合并而被带入你的历史。不能与 --对分


没有廉价的、一体化的Git表达式方法可以做到这一点。图形遍历代码要么只跟在第一个父级之后(如中所示),要么跟在合并的所有父级之后。因此,排除性的
^K
(或
^L^2
或其他命名commit
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
之间的合并基,那么你就可以用
git merge base
和这两个名字找到它的ID。)在本例中,我们并不真正需要
--无合并
,但在更复杂的示例中,我们可能需要它和/或
--第一个父级
。(编辑以添加注释:当然,我们永远不需要
--没有合并
:这是一个排除列表,合并已被排除。)

现在我们需要“在tempfile1中找到的所有哈希值,不包括tempfile2中的任何哈希值”,执行此操作的Unix工具集命令是
comm
。(Linux变体要求对输入进行排序并实际检查这一点,因此您需要
--nocheck order
来解决这一问题。
comm
使用的底层算法只需要将文件的行按相同的顺序排序即可。或者,您可以对两个文件进行排序:
sort-o$tempfile1$t例如,empfile1
。但这既昂贵又不必要。)

comm
实用程序读取file1和file2,这两个文件应按词汇排序, 并生成三个文本列作为输出:仅file1中的行;线 仅在文件2中;和两个文件中的行

我们需要“仅文件1中的行”,即丢弃文件2中出现的行。这将是“文本栏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
获得的修订版

我们现在只需要一个小小的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。根据需要想象一下。)

嗨,Vimsha,是的,我知道--first parent选项,但是,我只希望排除一个特定的合并。不是每次合并。