如何记录使用旧路径重命名/移动的文件的整个git历史记录?

时间:2019-03-25 13:59:03

标签: git version-control

如果文件A被编辑了一次或多次,然后重命名/移动到B并被编辑为B一次或多次,则使用其发出的git命令新名称/路径...

git log --follow -- B

...显示其整个历史。

但是,当我查看同一项目的旧(已发布/维护)分支时,该文件仍被命名为A,而我想向后移植在master中对其所做的更改,我可能认为是在master ...

上发布以下内容
git log --follow -- A

...将显示所有 更改。但事实并非如此。日志中显示的最新提交是与从AB重命名相对应的更改。对B所做的更改不会显示。

--follow仅将“后退”从较新的名称重命名为较旧的名称,而不是“前进”。

在这一点上,我首先必须确定显示的最新提交是重命名,找到较新的名称,然后再次使用新名称发出git log --follow(如果文件是自维护版本发布以来,已经移动了几次。

如何找到整个历史记录而不必多次手动发出git log --follow

1 个答案:

答案 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

如果您通过将tip1abc移到标记tip2之前的某个位置来构建了“转发”列表,那么您会没事的:该列表中没有分支,因为没有提交包括通向tip1的内容。但是,然后假设有人在 tag:abc | v ...--o--o--*--o--o--o--M--o <-- tip1 \ / o--*--o----o <-- tip2 上添加了 merge ,并进行了另一次提交:

abc

现在,从tip1tip1的路径包括两个 重命名。如果您以git log --follow开头,则必须为B命名合并时选择保留的姓名,无论是C还是git log -- B。因为git log -- CM(以正确的名称为准)确实简化了历史记录,所以Git只会在{后的两条腿中的一条走过{1}}-顶行或底行,具体取决于哪一个具有匹配文件-从abc转发时,您必须选择两个分支中的一个一起工作或进行一些幻想,以便您知道沿 top 检查A-变得-B,同时也检查A-变得- C沿着底部。 (Git没做任何花哨的事情。)