让 Git 跟踪重命名和编辑后的文件

16

有关在Git中重命名文件的问题之前已经被问到过但我无法解决我的特定问题。

我已经移动并编辑了多个文件(我没有使用git mv - 不幸的是现在为时已晚)。现在我想让我的同事从我的存储库中拉取,而他对这些相同文件进行了自己的编辑(未将它们移动)。为了成功合并,Git显然需要知道这些是相同的文件。

Git是否足够聪明,能够自己解决这个问题?这似乎很难相信。如果是这样的话,我如何确保特定的文件移动会被Git捕捉到 - 即使内容发生了更改?


2
这就是 git mv 的目的。 - ezod
好的,但是我该如何告诉 Git 文件已经被移动了呢?我在 Visual Studio 中移动了文件,现在我想确保 Git 知道这一点。我尝试过 git mv --cached,但那个命令不存在。当我尝试使用 git mv 时,会出现“fatal: bad source, source=...”的错误提示。 - Robin Winslow
如果您尚未提交,您可以将文件移到其原始路径,然后将它们 git mv 到新路径。 - ezod
好的,我可以做到,但这很烦人,因为我必须重新创建整个目录结构。Git没有一个相当于--cached的选项似乎有些愚蠢。 - Robin Winslow
5
Git确实足够聪明,能够自行处理这个问题。无论您是否使用git mv命令,重命名实际上只是在存储库中添加和删除文件。 - Edward Thomson
3个回答

21

Git实际上并不会跟踪重命名文件的操作,它使用差异启发式算法来检测您是否将一个文件重命名为另一个文件。也就是说,如果您使用git mv命令重命名文件,然后完全替换了其中的内容,这个操作不会被认为是重命名,因此您不需要再次使用git mv命令来检测重命名。

例如:

% mv d.txt e.txt
% git rm d.txt
rm 'd.txt'
% git add e.txt
% git commit -m"rename without git mv"
[master f70ae76] rename without git mv
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename d.txt => e.txt (100%)
% git diff --summary --find-renames HEAD~1 HEAD
 rename d.txt => e.txt (100%)

同样地,git mv并不意味着文件将被重命名,它仍然会使用差异算法:
% git mv e.txt f.txt
% echo "Completely replacing f.txt" > f.txt
% git add f.txt
% git commit -m"git mv doesn't help here"
[master 068d19c] git mv doesn't help here
 2 files changed, 1 insertion(+), 14 deletions(-)
 delete mode 100644 e.txt
 create mode 100644 f.txt
% git diff --summary --find-renames HEAD~1 HEAD
 delete mode 100644 e.txt
 create mode 100644 f.txt

8
默认情况下,git会在文件在提交之间被删除时检查重命名,不需要手动告诉它。如果您确实移动了一个文件(使用git mv而不是手动删除并再次添加),它会忽略提示。由于性能原因,启发式算法不会一直运行 - 如果您将文件移到另一个位置,然后使用原始名称添加一个新文件,则可能无法检测到移动。
请注意,从逻辑上讲,git仅存储每个修订版中存在的树:它不会存储有关修订版之间所做更改的任何跟踪信息。
如果您想查看检测到的内容,可以使用“-M”(“--find-renames”)开关切换到“git diff”以显示重命名。此开关还打开了启发式算法,如果您有一个不触发它们的提交,则非常有用。
这种基于启发式算法的方法是保持提交小而自包含的好理由(如果您需要另一个)。因为这样可以使git的工作更加容易。

2

git diff 没有检测到我重命名了文件并更改了它们的内容。我的情况是这样的:我有文件 A、B、C,然后插入了一个新的 B,所以旧的 B 现在是 C,旧的 C 现在是 D。 git diff 告诉我 B 和 C 现在完全不同!

我使用的解决方案很繁琐而且需要手动操作,但确实完成了工作。

  1. 尽力将文件重命名。例如,B 重命名为 Bnew,C 重命名为 B,D 重命名为 C。
  2. 进行 diff,检查是否有错误。
  3. 提交更改。
  4. 使用 git mv 将文件重新命名回其新名称。B 重命名为 C,C 重命名为 D。
  5. 提交更改。
  6. 进行其他重命名,将它们提交为新文件。例如,Bnew 重命名为 B。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接