在git中列出两个提交哈希之间的所有提交记录

128

我知道这里已经有非常相似的问题,但它们没有解决我的问题。也许有些地方我没有理解清楚。

这是fitnesse的提交历史记录的一部分(https://github.com/unclebob/fitnesse/):

* | | | | | | | | | | | | | | | fa86be8 Avoid possible issue when using CachingPage under heavy memory load.
|/ / / / / / / / / / / / / / /  
* | | | | | | | | | | | | | |   7b4a07a Merge pull request #256 from barredijkstra/fitnesse_issue_250
|\ \ \ \ \ \ \ \ \ \ \ \ \ \ \  
| * | | | | | | | | | | | | | | ecf5891 Fixed test checking for OS specific exception message.
| * | | | | | | | | | | | | | | 082236e Added rendering of cause exceptions. Fix for unclebob/fitnesse#250
* | | | | | | | | | | | | | | |   a92b37f Merge pull request #243 from amolenaar/fix/243-hash-table-rendering

我想要在两个提交哈希之间的提交列表。在这种情况下,我想要 ecf58917b4a07a 之间的提交,并期望结果为:

ecf5891
7b4a07a

到目前为止,我一直在使用git rev-list commit_hash_from_here^..commit_hash_up_to_here命令,并且在线性历史的情况下运行良好。然而,在这种情况下,我得到了更多的提交记录。

我尝试了这个方法,它像预期的那样工作:

git log --since='<date ecf5891>' --until='<date 7b4a07a>'

(我手动搜索了这2个日期)。

一种可能的解决方案是获取这2个日期并执行操作,但我认为应该有更好的方法。

编辑: 7b4a07a 的父提交分别为 ecf5891a92b37f。到目前为止,如果我想从 ecf5891 走到 7b4a07a,那么方案就可以正常工作,但如果我想从 a92b37f 走到 7b4a07a,我希望能够得到:

7b4a07a
ecf5891
082236e
a92b37f

但是我不明白a92b37f

4个回答

95

我认为你正在寻找--ancestry-path,在你的情况下:

git rev-list --ancestry-path 7b4a07a..ecf5891

15
对我来说,“--ancestry-path”是重要的一步。最终,我用以下方式来使用它:git log --oneline --ancestry-path commit1~1..commit2这样可以精确地查看我所拥有的两个提交哈希之间的所有内容。谢谢! - Hoonerbean
6
提交1需要是旧的提交,提交2是新的提交,才能使这些命令起作用。 - Shivendra Agarwal

43

对于Git提交来说,“之间”是一个有点玄乎的概念。

您展示的文本,包括一段图形输出,说明了为什么from^..to会产生超过这两个提交:其中to部分是一个合并提交。

符号A..B实际上只是B ^A的简写。也就是说,“从B开始并向后工作,减去从A开始并向后工作的所有内容”。但是B是一个合并提交,因此“从那里开始并向后工作”需要使用两个父提交

在这里,7b4a07a的第一个父提交是a92b37f(不在您[原始]上面的片段中,但我克隆了链接的repo找到了它)。虽然我们可以用符号表示它,并且我将在下面介绍。 7b4a07a的第二个父提交是您感兴趣的“from”部分,即ecf5891

当您请求:

ecf5891^..7b4a07a

这意味着:

7b4a07a ^ecf5891^

也就是说:

7b4a07a ^082236e

这会让你得到合并的双亲,然后从082236e开始剪裁掉所有东西。你还需要将第一个父级7b4a07a^及其之前的所有内容也都剪裁掉:

git rev-list 7b4a07a ^ecf5891^ ^7b4a07a^
git log --oneline 7b4a07a ^ecf5891^ ^7b4a07a^

总的来说,您需要确定要切断哪些后代线路。

编辑:您可以继续使用A..B符号表示法,但确实需要添加额外的“exclude”。因此,jthill的答案也可以使用,一旦您将帽子移到前面。


关于您的编辑(“如果我想从a92b37f7b4a07a”):我们又回到了“之间”的问题。哪些提交是“之间”的?从a92b37f7b4a07a有一条直线,因为a92b37f是合并提交7b4a07a的两个父提交之一。因此,根据先前的逻辑(“祖先行上的提交”,可能是“包容性的”),这将只是那两个提交之一,或者可能是这两个提交中的两个。但是您说您想要两个提交与a92b37f在任何祖先意义上都没有关系。为什么您想要那两个特定的提交?是什么使082236e“有趣”,而其父提交082236e^“无趣”?


好的,我明白你说“一直回到顶部,但这适用于2个父级”。然后,您要像以前一样切掉额外的父级部分,通过执行^7b4a07a^,即^a92b37f。您如何知道7b4a07a^将成为“另一个”父级,而不是ecf5891?我正在脚本中执行此操作,因此无法手动查找。 - Nico
“啊,这就是问题所在” -《哈姆雷特》。从提交本身来看,没有办法 a priori 知道要切断哪个合并的父级(们)。您需要提供更多背景信息(可能很多)。 - torek
现在我想按照时间顺序列出提交记录,"between" 的概念是:在时间图中查找提交 A 和 B,包括 A 和 B 在内的所有提交。也许这没有多大意义,而且我可能在想 svn 方式。到目前为止,最简单和最丑陋的解决方案是:获取所有提交哈希值,查找 A 并将其添加到列表中,直到我找到 B。无论如何,谢谢你,你帮我澄清了一些问题,并让我思考按时间顺序排列是否是我要寻找的答案。 - Nico
或者,也许这是有意义的,你想要的就是使用--since--until(或者使用相同功能的--min-age--max-age)进行限制。(请注意,这些选项查看的是“提交者”日期而不是“作者”日期,即补丁被提交的时间与编写时间不同。)但是,确实,这就是问题所在,当历史记录是非线性的时,“between”到底意味着什么? - torek
谢谢 @torek。你救了我一天!我一直在苦苦思索如何包含起始提交,使用“^”真的帮了很多。 - Rewanth Tammana

28

首先使用特定方法找到与所需相关的两个提交哈希值,以获取它们之间提交哈希值的列表。

git log --oneline

然后您可以选择有关的两个提交哈希值,并使用相应的命令找到它们之间的提交哈希值

git log <commit hash 1>..<commit hash 2> --oneline | cut -d " " -f 1

你测试过这个答案吗?对我来说它没有产生预期的结果。 - jww
11
我需要执行以下命令:git log --oneline hashone..hashtwo - Andrew
1
有趣的是,“from”提交必须比“to”提交早,否则它将无法正常工作。 - Diego Pino
为什么需要--online选项?有和没有--online选项有什么区别? - user12411795
@user12411795 --oneline 只是一个格式化标志。它会将每个提交的结果打印在一行上,省略一些信息。 - Zorobay

3

添加 ^7b4a07a~ 以排除与合并的第一个父提交相关的所有内容。你只是排除了与其第二个父提交相关的内容。


1
某种程度上的笔误,你需要在前面加上 ^(或者 --not)。 - torek
我应该在哪里添加那部分?完整的行应该是什么样的? - Nico
将其添加到规范的其余部分,只是另一个参数。@torek::-P yow。谢谢。 - jthill
好的,到目前为止它是有效的。然而,在我提供的编辑案例中它不起作用。 - Nico
你已经拥有完成这个任务所需的所有工具。git help revisions 将指导你了解如何指定哪些版本进行操作或不进行操作。需要理解的是命令对提交集合的操作使用“可达性”和“不可达性”说明。现在,你只需要时间和一些实验和探索。 - jthill
潜在的情况是,如果只适用于不强制执行git pull --rebase的数据库,则应添加。 - user12411795

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接