【问题标题】:Getting Git to Acknowledge Previously Moved Files让 Git 确认先前移动的文件
【发布时间】:2010-11-28 16:20:28
【问题描述】:

我不假思索地手动移动了一堆文件,并且找不到让 git 识别这些文件只是被移动而不是实际上不同的文件的方法。除了删除旧的并添加新的(从而丢失历史记录)或使用 git-mv 重做所有更改之外,还有其他方法吗?

【问题讨论】:

标签: git


【解决方案1】:

要让 git 删除已删除或已移动的文件,只需输入

git add -u

【讨论】:

  • +1:谢谢,这正是缺少的。当git status 不了解移动或重命名时,git add -u 会修复它。
  • 你能解释一下这是做什么的吗?
  • @OlivierBlanvillain: 'git add -u' 暂存 git 正在跟踪的所有文件,并且在工作目录中也发生了更改。请注意,如果您将文件移动到 Git 未跟踪的目录,“add -u”将不会检测到移动。如果您稍后将目标目录添加到 Git 并重新执行“添加 -u”,Git 将正确执行此操作。
  • 请注意,如果您有其他不想暂存的文件,则应指定文件名。
【解决方案2】:

我认为它已经这样做了。现在,我可能是错的,但我读过 git 根据文件内容而不是根据文件系统中的位置或增量/差异来跟踪文件。在堆栈中,我认为它显示它好像文件被删除然后重新添加,但我想我已经尝试过一次并且它仍然保持历史记录,由于上述 git 跟踪事物的方式。

仍然有助于有人验证我是否正确。抱歉,如果我误解了您的问题。

【讨论】:

  • 这是正确的。移动文件(分别在旧文件和新文件上使用“git rm”和“git add”)和使用“git mv”之间应该没有区别。 Michael:如果问题是您在“git log FILE”中没有看到移动前的历史记录,请尝试使用“git log --follow FILE”。
  • 对我不起作用。 Git 看到该文件被删除并添加了一个新文件。不知道我做错了什么。可能是 bitbucket 问题,因为看起来 Git 在我提交时检测到文件被重命名。
  • 这完全取决于移动文件后文件的不同程度,这很愚蠢。如果您将 dummy.class 重命名为 clean_refactor.clas,您将很可能通过至少重命名类名来更改文件的内容。这些改动会让 git 没有意识到 dummy.class 和 clean_refactor.class 属于同一个历史 :(
  • @JorgeIsraelPeña 只是重命名文件不会有问题。但通常你在一些重构过程中重命名一个文件,而与重构相关的代码中的更改会使 git 感到困惑。
  • @JorgeIsraelPeña 是的,我知道。因此我的咆哮 :) 在 svn 中,文件的历史不会丢失,包括它的重构。我将能够在日志中看到类 B 曾经被命名为 A,并被重构为 B。
【解决方案3】:

git 不跟踪单个文件的历史记录,也不专门处理移动和复制,即没有特殊的元数据表明发生了移动或复制。相反,每个 git 提交都是工作树的完整快照。

如果您想查看git log 中的移动,您可以提供-M 以及列出哪些文件已更改的选项,例如

git log --summary -M

git 将查看提交历史记录中的相邻树并推断是否有任何文件被每次提交移动。

要查找副本以及重命名,您可以使用 -C 选项,您可以提供两次以使 git 更难查找可能的副本源,但会牺牲一些性能。

git log --summary -M -C -C

注意,由于 git 不存储文件历史记录(仅提交历史记录),即使您对文件进行了 git rmgit mv,您也不会丢失任何历史记录。对路径的所有更改仍将被记录并在 git log 中可见。

【讨论】:

  • 您还可以在.git/config(存储库配置)或~/.gitconfig(用户配置)中将diff.renames 配置变量设置为true。有关详细信息,请参阅 git-config 手册页。
【解决方案4】:

为了更好地理解为什么 Git 会进行 重命名检测 而不是(更常见的)显式重命名跟踪,以及 git log 路径限制 的工作原理,您可以阅读 @ 987654321@ Git 维护者 Junio C Hamano 的博文(以及其中的参考资料)。

【讨论】:

    【解决方案5】:

    您可以将新文件移动/重命名为 git 之外的旧名称和路径,然后使用 git mv 进行移动;例如在 bash 中:

    mv $NEW $OLD && git mv $OLD $NEW
    

    它有点麻烦1,尤其是如果你必须手工操作的话。但它的优点是它保留了其他更改,例如更改命名空间或类名未暂存,以便您可以检查它们并且仅在您打算这样做时暂存它们。


    1我希望找到更好的替代方案,并在找到时更新我的​​答案。

    示例: 我将一堆文件从oldDir 移动到newDir,然后热情地开始进行其他一些更改。现在我想检查进行了哪些其他修改。使用 会导致以下结果(在一行上):

    git status --short |
    gawk '/^\?\?/ && match($0, /newDir\/(*.\.cs)/, a) {print "newDir/" a[1] " " "oldDir/" a[1]}' |
    xargs -n 2 bash -c 'mv $0 $1; git mv $1 $0'
    

    现在git status 将重命名显示为“要提交的更改”以及“未暂存的更改”下的文本修改

    【讨论】:

    • 我可能只有一个旧的 git,但如果文件更改太多,那么它会将 $OLD 标记为已删除,并将 $NEW 标记为已创建。任何编辑都应该在“git mv”之前提交。
    【解决方案6】:

    发生在我身上,当我移动和编辑文件时,它不再将其识别为移动文件而是一个新文件,所以我丢失了历史记录。

    我所做的是创建 2 个单独的提交,一个是在我移动文件时,另一个是在编辑文件。这样我就保留了历史记录。

    【讨论】:

      猜你喜欢
      • 2012-02-09
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多