如果文件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
?
答案 0 :(得分:2)
不幸的是,git log
本身像Git一样严格地向后退 。 Git实际上不能向前工作,因为Git存储的是是向后的:每个提交都记住其父提交的哈希ID,但是由于所有提交在创建时就被冻结了,因此他们无法记住哈希他们的孩子的ID,稍后创建。
git log
(及其类似的大姐姐/主力管道命令git rev-list
) 可以做一次反向遍历,从而确定哪些提交先于其他提交提交,然后 print 反向。 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
上添加了 merge ,并进行了另一次提交:
abc
现在,从tip1
到tip1
的路径包括两个 重命名。如果您以git log --follow
开头,则必须为B
命名合并时选择保留的姓名,无论是C
还是git log -- B
。因为git log -- C
或M
(以正确的名称为准)确实简化了历史记录,所以Git只会在{后的两条腿中的一条走过{1}}-顶行或底行,具体取决于哪一个具有匹配文件-从abc
转发时,您必须选择两个分支中的一个一起工作或进行一些幻想,以便您知道沿 top 检查A
-变得-B
,同时也检查A
-变得- C
沿着底部。 (Git没做任何花哨的事情。)