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
答案 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
很容易找到:它是master
和test
的合并基础。运行git merge-base master test
会吐出提交F
的哈希ID。这有效git diff
在我们使用master...test
时的作用:它找到两个提交的合并基础,即提交F
。
我们仍然希望将提交F
与提交D
进行比较。但我们必须找到代表提交D
的名称。找到D
的一种简单方法,但不是那么容易,就是使用图形日志查看器,例如git log --graph --oneline master test
或gitk master test
,并查看图表,寻找提交D
。找到后,我们可以剪切并粘贴提交D
的原始ID。
但是有一种编程方式可以找到它。请注意,D
是下一次提交的方向master
。 1 一旦我们获得了F
的ID,我们就可以从master
获取整个提交集,但不能从F
访问,例如:
git rev-list master ^F # or, equivalently, F..master
^F
从我们的绘图中删除了提交F
,E
,B
和A
。由于我们从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
。然后我们使用D
和git 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 log
或git 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
指向提交test
而G
的第一个父级是G
)。因此:
F
在这种情况下会这样做。使用git diff test^ master
或--name-only
来获取名称(以及可选的--name-status
或M
或A
等状态),就像您一直在做的那样
每当您进行像提交D
这样的合并提交时,您可以使用D
表示法命名其两个父项。因此,由于^
名称提交master
,D
命名第一个父(即,提交master^1
)和C
命名第二个父(即,提交{ {1}})。所以:
master^2
还会比较提交F
与提交git diff master^2 master
。
1 或者,一个提交和当前的工作树;或者一个提交和当前索引;或者索引和工作树等。但是,在这种情况下,你要选择哪两个提交进行比较。