如何获取从上次合并更改为主文件的文件名?

时间:2016-11-07 21:03:00

标签: git git-diff

A---B---C---D---H     (master)
     \ /   /
      E---F---G   (test)

“X --- Y”表示X和Y之间可以有多次提交

HEAD在G

我想获取已从合并F-> D更改为提交G

的文件名

我使用它,但它返回从E commit

更改的所有文件
git diff --name-only master...HEAD

1 个答案:

答案 0 :(得分:0)

编辑:现在问题不同,让我们像这样重新绘制图表:

A---B---C---D--o--o--...--o--H   <-- master
     \ /   /
      E---F--o--...--o--G        <-- test

也就是说,H^master^是一些&#34;无趣的&#34;提交,我们必须找到H~some-number的号码来命名提交D。例如,如果D--o--o--o--H链中有三个额外的提交,那么它就是master~4。但我们并不想要数数。

提交F很容易找到:它是mastertest合并基础。运行git merge-base master test会吐出提交F的哈希ID。这有效git diff在我们使用master...test时的作用:它找到两个提交的合并基础,即提交F

我们仍然希望将提交F与提交D进行比较。但我们必须找到代表提交D名称。找到D的一种简单方法,但不是那么容易,就是使用图形日志查看器,例如git log --graph --oneline master testgitk master test,并查看图表,寻找提交D。找到后,我们可以剪切并粘贴提交D的原始ID。

但是有一种编程方式可以找到它。请注意,D下一次提交的方向master 1 一旦我们获得了F的ID,我们就可以从master获取整个提交集,但不能从F访问,例如:

git rev-list master ^F    # or, equivalently, F..master

^F从我们的绘图中删除了提交FEBA。由于我们从master开始并向后工作,因此我们也永远不会在G之前和G之前看到提交F,也不会看到任何无趣的提交。所以这给我们留下了这个,我将提交F放在括号中,以便我们可以看到它在哪里:

C---D--o--o--...--o--H   <-- master
[  / ]
[ F  ]

(理想情况下,我们会以灰色或红色或其他方式绘制F,但我无法在StackOverflow帖子中执行此操作。)

使用git rev-list时,我们现在想要的是--ancestry-path选项。 --ancestry-path约束指示git rev-list 丢弃,从输出任何提交,它不是我们所有明确排除的提交的后代。我们明确排除的提交当然是F。因此,这会丢弃提交C,它不是F后代。离开:

    D--o--o--...--o--H

此列表中的第一个提交 - 当然git rev-list 打印首先是D。默认情况下,该列表实际上以反向日期顺序出现,并且由于D最旧的,因此通常会显示 last 。 (我们确实应该在这里添加--topo-order,以保证git rev-list不按日期顺序对提交进行排序,从而将D随机地移动到列表中间,而不是最后。 )

因此,解决方案

以编程方式,我们首先使用F找到提交git merge-base。然后我们使用Dgit rev-list找到提交tail。 (尝试使用--reverse -n 1很诱人,但这不起作用。)所以:

mbase=$(git merge-base test master)
next=$(git rev-list --topo-order --ancestry-path ${mbase}..master | tail -1)

然后我们可以:

git diff $diff_flags $mbase $next

(根据需要将diff_flags设置为--name-only--name-status

另外...

如果没有其他合并到主,可以更轻松地找到D。我们可以简单地使用git rev-list --merges -n 1 master来查找可从master到达的最新合并提交。事实上,当你正在做你在这里做的事情时,通过寻找合并启动是很常见的,然后git diff合并&# 39;合并的父母承诺。以这种方式工作时,只需使用git loggit rev-list--merges来查找合并提交ID,然后使用^2后缀表示法查找前一个合并提交:

merge=$(git rev-list --topo-order --merges -n 1 master)
git diff $diff_flags ${merge}^2 $merge

你已经完成了。

请注意,在这种情况下,我们既不知道也不关心D^2在分支test上;如果我们想知道,我们可以使用:

git merge-base --is-ancestor ${merge}^2 test

查看${merge}^2是否是提交G的祖先。如果我们想要从test专门找到一个合并,我们可以寻找更多的合并(但如果我们这样做,我们可能想要回到--ancestry-path方法)。

1 可以创建一个图表,其中有多个此类提交。在这种情况下,你必须做更多的工作,可能是做手动差异。

以前的回答

让我们从这开始:git diff比较两个提交。 1 三点符号,通常意味着&#34;对称差异&#34;,有一个不同的,特殊的,意思是git diff:它找到两个命名提交的合并基础。根据您的绘图,master(提交D)和HEAD(提交G)的合并基础是提交F,而不是提交E }。然后,diff将该提交与右侧命名的提交进行比较,因此这应该是F vs G

要提交F vs commit D,请将这两个提交命名为。有很多方法可以做到这一点,但看起来master是命名提交的最简单方法D(因为master直接指向它)和test^或{{ 1}}是命名提交test~1的最简单方法(因为F指向提交testG的第一个父级是G)。因此:

F

在这种情况下会这样做。使用git diff test^ master --name-only来获取名称(以及可选的--name-statusMA等状态),就像您一直在做的那样

每当您进行像提交D这样的合并提交时,您可以使用D表示法命名其两个父项。因此,由于^名称提交masterD命名第一个父(即,提交master^1)和C命名第二个父(即,提交{ {1}})。所以:

master^2

还会比较提交F与提交git diff master^2 master

1 或者,一个提交和当前的工作树;或者一个提交和当前索引;或者索引和工作树等。但是,在这种情况下,你要选择哪两个提交进行比较。