以前 有人 问过有关在 Git 中重命名文件的问题,但我无法解决我的具体问题。
我已经移动和编辑了多个文件(我没有使用git mv
- 不幸的是现在为时已晚)。现在我想要它,所以当我的同事从我的存储库中提取,对这些相同的文件进行了自己的编辑(不移动它们)时,它成功地将我的更改与他在文件的新位置中的更改合并。要成功合并,Git 显然需要知道这些是相同的文件。
Git 是否足够聪明,可以自己解决这个问题?似乎很难相信。如果是这样,我如何确定 Git 会拾取特定的文件移动 - 即使内容已更改?
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
并不意味着文件会被重命名,它仍然会使用 diff 算法:
% 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
默认情况下,只要文件在两次提交之间被删除,git 就会检查重命名——不需要手动告诉它。如果您确实移动了一个文件(使用 git mv,而不是手动删除它并再次添加它)它会忽略提示。出于性能原因,启发式算法不会一直运行——如果您将一个文件移开,然后添加一个具有原始名称的新文件,则可能无法检测到该移动。
请注意,从逻辑上讲,git 仅存储每个修订版中存在的树:它不存储有关修订版之间所做更改的任何跟踪信息。
如果您想查看检测到的内容,可以使用-M
( --find-renames
) 开关git diff
来显示重命名。此开关还打开启发式,如果您有一个不会触发它们的提交,这很有用。
这种基于启发式的方法是保持提交小且独立的一个很好的理由(如果您需要另一个),因为这使 git 的工作更容易。
git diff
没有发现我重命名了文件并更改了它们的内容。我的场景是我有文件 A、B、C,并插入了一个新的 B,所以旧的 B 现在是 C,旧的 C 现在是 D。git diff
告诉我 B 和 C 现在完全不同了!
我使用的解决方案既繁琐又手动,但确实完成了工作。
git mv
将文件重新命名为新名称。B 到 C,C 到 D。