2015-03-02 65 views
1

通常情况下,当我做git blame $filename,混帐显示我的各种信息的每一行代码,就像在一个文件分成几个文件之后,git可以跟踪作者和文件重命名吗?

^3333b include/Spec1.php (First Last)  function load($id) { 
^5555b class/Spec.php (Some One)   $id = ... 
^6666b include/Spec1.php (First Last)   $var = ... 

也就是说,

  • 其呈交它,
  • 谁最后更新的路线,
  • 有时甚至是该行所来自的文件名(当执行简单的 单个文件重命名时)。

在我的情况下,我似乎已经打破了这个循环,并且git将我的更改注册为由我进行的单个全局更改。

也就是说,我有一个叫做Spec的大类,其中包含多个产品系列的代码。我将班级中的各种代码重构为几个新班级。当我提交时,git会将这些文件检测为“新文件”。

这意味着我的新文件将以我的名义注册为由我创建的所有新文件,并且其中的行是“全新的”。

从根本上,我失去了:

  • 原作者的每一行 - 尽管我刚刚搬到行从一个文件到另一个不是真的有创作它,Git把它作为新的生产线不管。
  • 用于容纳每行代码的旧文件名 - 当我做git责备时,git现在只将该行看作是存放在创建的新文件中。它丢失了该行被安置在之前的文件名的跟踪。

有没有办法在做这个复杂的提交时不会失去它们?

+0

不确定您的意思是“此时我有什么能够跟踪更改并保留历史记录?”,但如果您拥有大型Spec类,那么您将保留历史记录。你能指定你要找的更多吗? – gravetii 2015-03-02 16:37:58

+0

请参阅更新 - 我正在寻找保留“文件重命名”作为历史的一部分 – Dennis 2015-03-02 17:17:59

+0

我刚才重写了这个问题,添加了“作者” – Dennis 2015-03-02 17:29:53

回答

1

Git总是会动态地重命名和复制检测,在您选择两个不同的提交进行比较时。

使用git blame时,您为每个动态比较选择的两个提交来自父/子关系。 git log -pgit show的情况也是如此。当你运行git diff时,你自己决定要比较哪两个提交(而不是让git通过提交父代码来挑选它们)。在任何情况下,提交最终都会通过git的内部diff引擎运行,要么是显式的git diff补丁输出(git log -p,git show),要么是其更改发现效果(git blame只需要查看子行中的行1234是否不同于在其父母)。

可以指定“相似度阈值”为匹配的文件重命名,这通常是与-M选项,以及是否要启用“找份”如果是这样,是否启用“完成找到更难“:这些通常通过-C(可能重复)或--find-copies-harder完成。 (git blame似乎没有最后一个作为标志,-Mgit blame中也没有查找文件重命名,而是改变了“移动的行”的分配方式。)

在这种情况下,您可能需要设置一个低(ish)-M阈值,并且可能至少指定-C两次。 (二-C选项的意思是“寻找来自其他文件在当前的父/子对复制的代码”而3个-C什么恶意“寻找来自任何承诺复制的代码”。)


你也可以配置diff.renames = true以始终启用默认的-M值;或者也可以打开-Cdiff.renames = copies。这是特定于常规diff; git blame定义其-M-C标志有些不同。

+0

谢谢。我不确定我跟着那个。当我做'git blame -C -C Spec1.php'时,git认为片刻,然后仍然显示每一行由我创作,今天,当每行实际上由其他人创作时,在过去的不同时间。为了比较原始文件中的'git blame Spec.php',显示了几年前各行的各种作者。随着我的重构,我失去了那段历史。 – Dennis 2015-03-02 17:38:06

+0

我知道我需要在提交时做些事情吗? – Dennis 2015-03-02 17:40:15

+0

不是“在提交时”,而是“在你运行git blame时”。您可能需要降低检测阈值以查找移动和复制的代码。缺省情况是检测'-M'的20行块和''-C'的40行。详情请参阅文档。 (我在这里掩饰的一点是''M'和'-C'的确切定义对于'git blame'和'git diff'都是不同的。) – torek 2015-03-02 18:02:28