git,确保在保留历史记录的同时移动/重命名文件的方法

时间:2016-02-25 04:41:51

标签: git rename move

我知道有很多"很多"现有的问题看起来很相似,所以让我在问我之前总结一下。

第一个答案,我不同意,因为我之前已经这样做了。第二个问题的答案就是我提出这个问题的原因。即,

我发现我一直在做git mv,但有时它被视为移动/重命名,有时它被视为删除+添加。因此,我想知道如何让它始终移动/重命名?

this one为例,在底部,我们可以看到多个移动/重命名案例,例如easygenapi/tf-varcaser.go → tf-varcaser.go。请注意,此类移动是跨/文件夹之间的移动!即,我做了它!

但是还有许多其他情况git mv被视为删除+添加,显示在完全相同的更改日志中。同样,我一直在做git mv。为什么git表现不同?

在保留历史记录的同时,是否有 sure-fire 方法来移动/重命名git文件?

2 个答案:

答案 0 :(得分:19)

TL;博士;无

更长的版本: 根据我的经验,只要文件未经修改,git就非常擅长检测移动/重命名。 Git使用启发式方法来尝试和定位移动。如果文件过于相似,或者文件在移动过程中被修改过,导致它与原始文件太不相似,可能会被欺骗。

我发现这样做的最好方法是进行多阶段提交,将所有动作分成一个提交,然后再改变另一个提交。例如......

git mv foo.txt bar.txt
git commit

... modify bar.txt ...

git add bar.txt
git commit

它不能保证您的移动被正确检测到,因为当有多个候选者时它仍然会混淆。然而,它对我来说非常有效,并且可以捕获大多数情况。

答案 1 :(得分:12)

Git不会跟踪重命名。期。它也不跟踪添加。或者删除。或差异。或补丁。或移动。或任何形式的改变,真的。

Git是基于快照的。每个提交都记录整个项目的快照。而已。 如何那个快照,Git既不知道也不关心。

差异,补丁,添加,删除,移动,重命名等由各种可视化工具显示,这些工具在使用启发式(这是另一种说法“猜测”)之后推断它们。有时候,他们可能会正确猜出你做了什么,有时他们却没有。然而,这并不重要,因为它只是可视化,它不是历史的任何方式,形状或形式的一部分。

大多数工具使用某种形式的相似性度量,并推断如果两个文件的相似度大于某个阈值,则会发生重命名。在某些工具中,此阈值是可配置的。在某些工具中,甚至算法也是可配置的。 (一个稍微相关的示例:git diff允许您在不同的算法之间进行选择,以推断文件中的差异。)

由于Git不记录更改,因此可以在可视化工具的更高版本中添加新的更改,这些更改可以推断在更新工具之前记录的旧更改的更改,这些新工具甚至可以编写新的更改类型。想象一下,例如,一个了解您正在使用的编程语言的语法和语义的工具。它可以将某个提交可视化,而不是一堆文件,每个文件都有几行更改,但作为一个更改,它重命名子例程并更新每个调用点(即重命名方法重构)。 / p>

重命名实际上是一个很好的例子。例如,git log --follow使用的重命名检测启发式和相似性度量被多次改进。 IIRC,在开始时,根本没有推断重命名,后来增加了这种能力。如果Git记录了更改而不是快照,那么这根本不可能实现。