如果文件A
被编辑了一次或多次,则重命名/移动到B
并编辑一次或多次B
,使用其新名称/路径发出以下git命令...
git log --follow -- B
......展示了它的整个历史。
但是,当我正在查看同一个项目的旧(已发布/维护)分支时,该文件仍然名为A
,并且我想在master
中对其进行后退更改,我可能会认为在master
上发布以下内容。 。
git log --follow -- A
......会告诉我所有的变化。但事实并非如此。日志中显示的最新提交是对应于从A
到B
的重命名的更改。未显示对B
所做的更改。
即--follow
只跟随从较新的名称“向后”重命名为旧名称,而不是“转发”。
此时,我必须首先确定显示的最新提交是重命名,找到更新的名称,然后再次使用新名称发出git log --follow
(如果文件移动了几次,可能会重复几次,因为保持释放。
如何在不必多次手动发布git log --follow
的情况下找到整个历史记录?
不幸的是,git log
本身严格地向后工作,就像Git一样。 Git确实无法正常工作,因为Git存储的内容是向后的:每个提交都会记住其父提交的哈希ID,但由于所有提交在创建时都会及时冻结,因此无法记住其子项的哈希ID,后来创建。
什么git log
(和它的大姐姐/主力管道命令git rev-list
)可以做的一次反向遍历,找出哪些提交在其他提交之前,然后反向打印。 git log --reverse
命令执行此操作。但是,重命名检测仅在向后(对于Git向前)遍历期间发生,并且不能楔入后面的向前(向Git向后)打印输出。
它不是内置于Git中,但您可以使用git rev-list
进行反转,保存结果,然后在每个提交对上运行git diff --name-status
时进行自己的前进行走,寻找重命名操作。请注意,这仍然有点棘手,因为现在分支真正分支和合并真正合并Git的内部向后遍历,合并分支,而分支合并。 :-)也就是说,假设我们有:
tag:abc
|
v
...--o--o--*--o--o--o <-- tip1
\
o--*--o----o <-- tip2
你想从标签abc
开始,它位于左侧,并且“向前工作”。 Git想要从tip1
开始,沿着顶线向右移动,或者tip2
,向右边的提交开始。
标记为*
的提交将您的文件A
重命名为一些新名称。在顶部的一个新名称是B
,在底部的一个名称是C
。
如果你在tip2
开始Git,你必须寻找C
。 Git注意到在*
重命名,从那时起,向左,寻找A
。如果你在tip1
开始Git,你必须以同样的方式寻找B
。
如果你通过从tip1
倒退到标记abc
之前的某个点来建立一个“前锋”列表,你会没事的:因为没有包含导致tip2
的提交,所以在该列表中没有分支。但是后来假设有人向tip1
添加了一个合并,并且另一个提交:
tag:abc
|
v
...--o--o--*--o--o--o--M--o <-- tip1
\ /
o--*--o----o <-- tip2
现在从abc
到tip1
的路径包括重命名。如果你从tip1
开始,你必须给git log --follow
这个合并的人选择保留的名称,无论是B
还是C
。因为git log -- B
或git log -- C
(无论哪个是正确的名称)进行历史简化,Git只会走M
后面两条腿中的一条 - 无论是顶行还是底行,具体取决于哪一个具有匹配文件 - 以及当你向前工作时从abc
你必须选择两个分支中的一个来工作,或做一些奇特的事情,以便你知道检查A
-become-B
沿着顶部,同时还检查A
-become-C
沿底部。 (Git没有做任何花哨的事情。)