因此,我想将大文件的一部分提取到新文件并保留 git 历史记录,这样我就能够git blame像重构之前一样运行并查看更改。
在 Git 中,历史记录就是提交。没有文件历史记录。这与大多数其他版本控制系统不同:那些跟踪“文件身份”的其他 VCS需要您通知他们新文件的path/to/new.ext来源path/to/existing.ext,以便他们可以将新文件的历史记录与旧文件的历史记录相关联。同样,他们需要您通知他们有关文件重命名的信息\xe2\x80\x94,尽管有些(例如 ClearCase)可以通过简单地充当工作树的文件系统来自动检测重命名。Git 不需要任何这些,因为它不是那样工作的。1
相反,在 Git 中,当您将一个提交\xe2\x80\x94(称为a\xe2\x80\x94)与另一个提交 ( b) 进行比较时,Git 会尝试(在比较时动态地)发现a/path/to/name某个文件是否与另一个文件“相同” b/some/other/path/to/anothername。比较的程度以及判断它们是相同文件还是不同文件的算法取决于Git命令。该git diff命令首先查看实际路径名:如果它们相同,则文件相同,2否则它们可能不同。“可能”部分是重命名检测的用武之地(如果您已启用它)。常规程序git diff还具有-C和--find-copies-harder来启用“文件复制自”检测。使用-C两次(或--find-copies-harder)设置查找从提交中的任何文件复制的新文件a(这被认为太昂贵而无法自动执行;通常,只有那些被视为“修改”的文件才会被视为复制源候选人)。
该git blame命令有些不同(并且a和b提交只是自动成为每个提交的父子项),但它仍然有一个-C选项。它的-C工作方式有点不同:-C查找从提交和之间修改的文件复制的行。使用两次查找从commit 中的任何文件复制的此类行,并且使用三个标志,它将“更难找到副本”:它将查看每个提交中的每个文件以查找复制的代码。ab-Ca-C
因此,对于大多数用途,您只需-C在git blame. -C -C如果复制的代码来自未修改的文件,则应该使用。-C如果您认为某些代码在许多转之前被删除,然后又复活,并且您想要找到原始来源,请使用三个s。请注意,git blame\'s-C选项打开git blame\'s-M选项,该选项检测移动的代码(因此与git diff\'s-M选项\xe2\x80\x94 文件重命名检测完全不同,la git log --follow, 3始终启用)。
1与其他 VCS 相比,这是 Git 的一个很好的优势,因为 Git 可以检测人类忘记的情况,并且还可以在比较“相距较远”的修订时检测重命名。这对于 Git 来说是一个可怕的缺点,因为即使人类不会忘记,它也必须检测案例,因此会错过重命名。这对 Git 来说是一个很大的优势,因为未来更智能的算法会以更好的方式使用现有数据。简而言之,对于为什么它更好和为什么它更差存在争议,但最终它只是不同。
\n\n2对于git diff,您可以使用其选项有条件地分解这些自动配对的“相同名称意味着相同文件”配对-B。这对于 不可用,但也不必要,因为git blame它不进行这种配对。
3--follow in启用的代码git log是一种可怕的黑客行为,基本上只适用于git blame. 不要尝试--follow逆序使用git log使用。