我在git之外重命名了一些文件并对其进行了大量修改。当我跑步的时候
git diff-index -M --name-status HEAD
我看到只有4个文件被重命名/移动,而它应该更多。
我知道我可以使用hg mv --after
在Mercurial中记录事后移动。我找不到git中的等价物。有吗?
答案 0 :(得分:4)
作为Dietrich Epp already answered,你不仅没有必要,你实际上不能。我从评论中看到你仍在努力解决这个问题。它可能有助于“回放”一些并谈论通用版本控制系统(VCS)理论。
Mercurial与许多(大多数?)其他VCS一样,具有强大的文件标识概念。这就是您必须使用hg mv
的原因,如果您忘记这样做,请使用hg mv --after
:Mercurial知道某些路径的文件首先在某些提交 C n中引入 ,从那时起,通过记录任何重命名操作来跟踪该文件的身份。
其他VCS通过其他机制执行相同的操作,例如将路径名映射到对象标识符(类似Unix的“inode number”或ClearCase“OID”)。该文件的历史记录以某种方式附加到此对象ID。虽然Mercurial不使用数字OID / inode-number,但是通过记录重命名(以及副本和删除)来跟踪文件通过清单的技巧会产生相同的结果。
Git抛弃了整个概念。莱纳斯宣称你不需要它,因此他根本就不会这样做。在任何提交中,没有任何文件具有超出其存在或缺乏的任何标识。提交 C 0 中的文件foo
与提交 C n 中的文件foo
完全无关(其中 n ≠0)...除非,事后,你(或Git)决定它应相关。 (见下面的旁注。)
git diff
命令决定两个不同提交中的两个文件是否相关,如果它们具有相同的名称和/或相似。否则他们是无关的。根据您传递给git diff
的选项,它会在您运行git diff
时动态决定 。因此,如果您使用不同选项运行git diff
两次,则会得到不同的答案。文件f1
和f2
可能相关(重命名或复制)或相关(f1
已删除,f2
已创建)。
如果你对VCSes非常熟悉,你会立即想要反对:这不会干扰增量压缩吗?答案是肯定的,确实如此,但是Git没有em>做 delta压缩。
<等等(等等,什么?!?)好吧,让我们调整一下。 Git不进行增量压缩尚未。
在存储库中的“松散对象”级别,Git根本不进行增量压缩。它只是将文件内容减少为单个哈希值,并声明散列到相同值的所有文件都是相同的文件。内容的哈希是内容的标识(名称)。因此,如果提交 C 0 中的f1
与提交 C n <中的f2
相同,则内容相同/ sub> ,然后 content 只存储一次,作为其哈希命名的对象(即使 n = 0 !)。
稍后,Git制作“打包文件”而做做delta压缩,但是它通过选择其认为在分组时可以进行delta压缩的其他对象来实现。在这个对象选择中有大量的头发和魔法,Git实际上偷看了文件名来做到这一点,但至少 ,它只是在整个存储库中挥动魔杖在所有历史记录中,并说“啊,如果我从提交blah
和内部树对象9999999
增量压缩文件1234567
并在链中一起提交abcdef2
,我会变得很好结果,所以我会这样做!“
这样做的一个结果是,在Git中,文件实际上没有历史记录。由于没有真正的文件标识概念,您有提交历史记录但没有文件历史记录。但是,Git会通过将每个提交与一些先前的提交进行区分,并且有时将两个具有不同路径名的文件声明为相关来合成历史记录。例如,使用git log --follow
可以做到这一点。但是一般来说这很难做,git log --follow
做得相对较差:你可以通过一系列提交跟踪一个路径名,一次一个提交,并尝试发现重命名。该代码仅在从较新的提交转换为较旧的提交时有效,因此您不能git log --follow --reverse where/did/this/get/renamed/to
。也就是说,如果你知道是一个带有一些路径名的文件,并且想知道它是否仍然存在,那么Git并不擅长讲述。 (基本上,您需要git log --raw
在原始名称上搜索R
状态。如果您找到这样的状态,则可能需要重复使用新名称,直到找到每个重命名从“我认识的文件”到“一个看起来像内容的文件今天有关”。)
答案 1 :(得分:3)
摘要:不要担心。只需正常提交文件,因为这确实是您唯一的选择。
这里是Git如何查看从X到Y的重命名。
Commit #1:
- File named "X" with contents "Hello, world!"
Commit #2:
- File named "Y" with contents "Hello, world!"
请注意,如果您重命名该文件或者您创建了具有相同内容的新文件,Git实际上并不关心。对于Git,没有任何区别。
Git不记录存储库中的移动,并且没有每个文件的历史记录。 Git仅将历史记录为整个存储库的快照图。只需正常使用git add
和git commit
,您在此处执行的任何操作都不会产生任何影响。如果您使用git mv
,则与git rm
和git add
相同。
当您使用git status
或git log
时,如果添加的文件与已删除的文件足够相似,则会显示删除和添加内容。 Git不使用存储库中的任何额外信息。如果您更改了移动的文件,它将显示为单独的添加和删除。 Git通过将新文件的内容与已删除文件的内容进行比较来完成此操作。当您在数据已经提交之后请求差异时,会发生这种情况。
默认相似度阈值为50%。如果要查看相似度低于50%的文件之间的重命名,请将较低的百分比传递给git diff-index
。例如,要跟踪重命名,即使75%的文件发生更改,请使用以下命令:
git diff-index -M25%