git - 如何将代码重构为新文件并保留 git 历史记录?

标签 git refactoring

所以我想将大文件的一部分提取到一个新文件中并保留 git 历史记录,这样我就可以运行 git blame并像重构之前一样查看更改。

最佳答案

在 Git 中,历史就是提交。没有文件历史记录。这与大多数其他版本控制系统不同:那些跟踪“文件身份”的其他 VCS 需要您通知他们新文件 path/to/new.ext源自 path/to/existing.ext以便他们可以将新文件的历史记录与旧文件的历史记录相关联。类似地,他们需要您通知他们有关文件重命名的信息——尽管某些(例如 ClearCase)可以通过简单地充当工作树的文件系统来自动检测重命名。 Git 不需要任何这些,因为它不能那样工作。 1

相反,在 Git 中,当你比较一次提交时——称之为 a —对于另一个( 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命令有些不同(并且 ab 提交只是每个提交的自动父子提交),但它仍然有 -C选项。它的 -C工作方式略有不同:一个 -C查找从提交之间修改的文件中复制的行 ab .使用 -C两次查找从提交 a 中的任何文件复制的此类行,和三个 -C标志,它将“更难找到副本”:它将查看每个提交中的每个文件以查找复制的代码。

因此,在大多数情况下,您可以只使用一个 -C在您的 git blame .您应该使用 -C -C如果复制的代码来自未修改的文件。使用三个 -C s 如果您认为某些代码在很多次之前被删除,然后又复活了,并且您想找到原始来源。请注意 git blame-C选项打开 git blame-M选项,它检测移动的代码(因此与 git diff-M 选项大不相同——文件重命名检测,总是启用的 git log --follow ,3)。

1这是 Git 优于其他 VCS 的一个很好的优势,因为 Git 可以检测人类忘记的情况,还可以在比较“相距甚远”的修订时检测重命名。这对 Git 来说是一个可怕的劣势,因为即使人类不会忘记,它也必须检测案例,从而错过重命名。这对 Git 来说是一个很大的优势,因为 future 更智能的算法会以更好的方式使用现有数据。简而言之,对于为什么它更好和为什么它更糟存在争论,但最终它只是不同的。

2对于git diff ,您可以使用其 -B 有条件地拆分这些自动配对的“同名意味着相同的文件”配对。选项。这对 git blame 来说是不可用的,但对它来说是不必要的。 ,这不是在做这种配对。

3由--follow启用的代码在 git log是一个可怕的黑客,基本上只适用于 git blame 要求的一种情况.不要尝试使用 --follow逆序 git log .

关于git - 如何将代码重构为新文件并保留 git 历史记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40466194/

相关文章:

git - 关于如何在 git 中处理未完成的用户故事分支的建议

windows - 无法从 Windows 连接到我的 git 存储库到 linux

javascript - 通过算法将冗余代码优化为循环

eclipse - 如何使用 Eclipse 重构工具并通过 Subclipse 与 SVN 保持同步?

java - 重构自动检测文件的编码

Git:为什么文件删除不同步?

git - 是否可以在 bash 的 PS1 中预先评估一个值?

git - 为什么 git clone 不设置远程跟踪分支?

wpf - 重构 WPF MVVM 以提高可测试性

language-agnostic - 设计现在是重构的一个子集吗?