2010-08-19 141 views
17

我很了解Git如何支持文件移动:因为它使用文件哈希,所以“添加”文件很容易被检测为与“移除”文件相同。Git在重构过程中如何跟踪历史记录?

我的问题是关于重构:考虑到Java中,包声明变化,使文件内容将不会是相同的。在这种情况下,Git如何确定“已添加”文件与“已删除”文件共享历史记录?假设我只做了很小的修改或类似的非确定性解决方案,它是否检查“最相似的内容”?

+0

等一下......这 “阿帕奇Maven的” 书只是在我面前有一个作者的名字怪异的熟悉... – VonC 2010-08-19 08:49:21

+0

吧,我是这个家伙:D – 2010-08-19 10:25:19

+0

我知道了!我仍然试图从“C'est pas sorcier”中谈论一个疯狂的弗雷德在最近的JUG谈到maven3迁移的情景......好时光;)欢迎来到SO。 – VonC 2010-08-19 10:31:51

回答

20

Git FAQ提到的,它会检测基于启发式类似的内容。

Git必须与很多不同的工作流程进行互操作,例如一些更改可能来自补丁,其中重命名信息可能不可用。依靠明确的重命名跟踪,无法合并两棵完全相同的树,除了一个做了补丁(创建/删除),还有一个树使用了其他启发式。

第二个说明中,跟踪重命名实际上只是跟踪树中内容移动方式的特殊情况。在某些情况下,您可能有兴趣查询函数何时添加或移动到不同的文件。通过仅依赖于在需要时重新创建此信息的能力,Git旨在提供一种更灵活的方式来跟踪树的变化。

但是,这并不意味着Git有对重命名的支持。
在GIT中的DIFF机械具有用于自动地检测重命名的支持,这是由“-M”开关导通以对git-diff-*家庭命令。
git-log(1)和git-whatchanged(1)使用重命名检测机制,因此例如'git log -M'将给出具有重命名信息的提交历史记录。
Git还支持跨重命名的有限合并形式。
两个工具用于分配怪,git-blame(1)git-annotate(1)都使用自动重命名检测码来跟踪重命名。


git log为您提供有关启发式一些细节:

-B[<n>][/<m>] 

歇完全重写转变为对删除和创建。这有两个目的:

  • 它影响的方式,相当于一个文件的完全重写不是与发生在文本上匹配的背景下,极少数线路混在一起了一系列的缺失和插入的变化,但是作为旧的一切删除操作,随后插入一切新内容,并且数字m控制-B选项的这一方面(默认为60%)。
    -B/70%指定为与原始小于30%应保持在结果为GIT中认为这是一个总重写(即否则所得到的贴剂将与上下文行混合在一起的一系列缺失和插入的)。

  • 与-M一起使用时,完全重写的文件也被认为是重命名的来源(通常-M只考虑消失的文件作为重命名的来源),而数字n控制着这个方面-B选项(默认为50%)
    -B20%指定添加和删除相对于文件大小的20%或更多的更改有资格作为重命名到另一个文件的可能来源。

-M[<n>] 

如果生成的diff,检测并报告重命名为每个提交。对于在遍历历史记录时跨越重命名的文件,请参阅--follow
如果指定了n,则它是相似度索引(即与文件大小相比的添加/删除量)的阈值。
例如,-M90%表示如果超过90%的文件没有变化,git应该考虑删除/添加对是重命名


其他参考:

+0

好的,但是用简单的语言对原始情况有一个简单的答案吗?如果我通过将Java类移动到不同的包目录来重构Java类,以便(例如)100行中的单行已被修改,表示Java包,则_default_日志和责备是否会识别移动/重命名?我还会在GitHub/BitBucket上看到正确的指责吗?换句话说,如果我执行这个(非常非常非常常见的)活动,那么这些事情是否会与所有事情的默认设置“一起工作”? – 2015-09-05 23:07:44

+0

@GarretWilson是的,它会在本地(你可以调用'git log --follow'(如http://stackoverflow.com/q/2314652/6309)或'git blame -C'。尽管(GitHub:http://stackoverflow.com/a/5647721/6309)(或BitBucket:https://bitbucket.org/site/master/issues/589/file- history-should-follow-copies-and) – VonC 2015-09-05 23:13:29

+0

感谢您对链接的快速澄清!我将扣留我对Git的评论,这似乎我没有选择,只能使用... :) – 2015-09-05 23:35:00

相关问题