列表合并提交,其中一次祖先触及某个文件

时间:2017-02-08 08:03:52

标签: git git-log

我想仅列出合并提交,通过该提交,给定文件实际上将其作为当前分支。举个例子:

-A--B----C-------D--E------F----G--------H---
  \   \---P--Q--/    \---X--Y--/        /
   \-----------------------------M-----/

让我们说P和Y是修改abc.txt的唯一提交。在这种情况下,如何让git log仅列出D和G?请注意,D和G实际上并没有直接触及abc.txt:它们只是具有触及abc.txt的祖先的合并提交。

我试过了:

git log --merges -m --name-only --follow abc.txt

不幸的是,这也包括H,因为H曾经触及(通过Y)abc.txt的祖先(G)。

(注意:Firebug UI提出了一个不同的问题:它询问哪个合并提交(不是他们的祖先,但合并提交本身)实际上触及了abc.txt。)

1 个答案:

答案 0 :(得分:1)

你不能,至少不能直接。 (我认为 - 这是基于--simplify-merges显然没有做你想要的事实。通常看起来它会做你想要的。注意你需要--simplify-merges --merges此处;您将在“第一”步骤中的--simplify-merges中使用--merges但不使用git rev-list。)

  

请注意,D和G实际上并没有直接触及abc.txt:它们只是具有触及abc.txt的祖先的合并提交。

嗯,是的,不是。像Git中的任何提交一样,合并提交有一个树和一些父。提交D和G,合并,至少有两个父提交。每个父母也有一棵树,所以我们可以差异(或者有Git diff)D ^ 1(即C)vs D,和D ^ 2(即Q)vs D.其中一个 - 第一个,如果我让两个父母正确订购 - 将显示对abc.txt的更改。我们可以以相同的方式将G ^ 1和G ^ 2中的每一个与G相区分并获得相同的效果。但我想我们都知道你的意思:我们以这种方式发现的变化因某些早期提交而存在

但对于H来说也是如此!差异H ^ 2(又名M)与H显示对同一文件的更改。这种变化是通过G引起的,就像G通过Y引起的变化一样。那么问题就变成了:我们为什么要算G,但不算H?

认为我们应该计算G的原因而不是H这里的原因是 - “带来”变化的祖先 - 即Y-具有“下游”提交,即G,这是一个合并,我们想声称“吸收”变化。

(根据同样的逻辑,如果M也改变了abc.txt,那么我们希望将H包括在我们的集合中。)

如果这种推理是正确的,那么这就建议了一种找到你关心的合并的算法:

  • 首先,查找文件以任何方式更改的所有合并。这将选择D,G和H中的所有内容。
  • 其次,对于每个这样的合并,找到它的父母(至少有两个)。如果abc.txt的合并提交版本与两个父版本不同,请将合并标记为集合中的“肯定包含”:我们从“双方”引入了更改和/或这是一个“邪恶的合并”(它引入了在父叉中没有做出的改变)。但是,如果没有,请将合并标记为“可能可移除”。
  • 最后,以“最父母 - y”的顺序遍历所有“可能可移动”的合并(在任何孩子之前做所有父母:你将自然地从适当的git rev-list --topo-order --reverse中获得第一步,或者您可以按其他顺序获取列表,然后反向工作)。任何标记为“绝对保留”的提交;标记为“可能保留,可能是可移动的,取决于父级#N”的任何提交都将保留,除非它具有与父级相同的相同 abc.txt的父级合并-in-那个方向;并且任何标记为“可能保留,可能是可移动的”的内容都会被删除,如果它具有保持父方向的方向具有相同的abc.txt

    (我不确定如何为章鱼合并修改这个,所以我会考虑给你。)