为什么文件的移动会导致其所有行被删除然后添加?

Tud*_*ari 1 git atlassian-sourcetree

我尝试将文件移动到子文件夹中,并且 git 看到它刚刚被“重命名”......但也看到它的整个内容被删除然后添加。

由于某种原因,对于某些文件,我可以移动它们而不会丢失所有行的实际/正确/原始git blame。但对于有些人,我不能。

我在Windows上并使用SourceTree。看起来也许这不是 git 的错,而是 SourceTree 的错?

我在另一台计算机上尝试过,也使用 Windows 10 和 SourceTree,一切正常。我可以在任何地方移动所有东西,而不会触发更改、影响 git 指责等。

有什么建议吗?我想使用 CLI 提交文件移动将是首选,但我使用 SourceTree 来避免这种情况。:\

在此输入图像描述 无论如何,如果没有其他解决方案,您能否推荐一个快速命令来轻松安全地提交整个文件夹及其子文件夹的移动?

提前致谢!

mat*_*att 5

这里有两件事需要理解。

\n

首先,Git 对“发生了什么变化”一无所知。Git 完全通过提交进行传输。提交不是更改或差异;而是提交。它是项目整个状态的快照。因此,如果您进行一次提交,然后移动一个文件并添加所有内容并再次提交,您所拥有的只是一个包含文件 A(但不包含文件 B)的提交和另一个包含文件 B(但不包含文件 A)的提交。换句话说,Git 对于“发生了什么”是完全中立的;这是人类喜欢思考的事情,但这与 Git 无关。Git 只知道事物有一种状态,然后又有另一种状态。正如《李尔王》所说:“看看这张照片和这张照片。”

\n

但其次,Git 还试图通过提供有关更改的信息来善待人类,尽管它实际上对此事一无所知。当你要求差异时,无论是通过还是其他方式,Git 都会尝试做人类会做的事情:它查看第一个提交并查看第二个提交,并尝试“发现差异”他们。它得出的结论不会以任何方式被纳入存储库;存储库只包含提交。这些关于差异的结论是短暂的\xe2\x80\x94 Git现在正在尝试找出这些提交的差异,纯粹是为了向您展示差异。git showgit loggit diff

\n

(此规则的例外是 Git 执行合并时发生的情况。合并是 Git 计算差异并实际使用它生成全新提交的情况。使用合并逻辑的所有命令 \xe2\x80\x94 git merge, git cherry-pick, git rebase\xe2\x80\x94 以此方式操作。)

\n
\n

现在,基础知识已经讲完,我们来谈谈 Git 如何向(人类)显示两次提交之间的差异。如果您进行提交,然后移动一个文件并添加所有内容并提交,就 Git 而言,唯一发生的事情就是一个文件消失(被删除)而另一个文件出现(被创建)。可以说,这就是它的后备立场:“这是我的故事,我会坚持下去。” 你必须承认,这是对所发生事件的一个很好的底层描述。

\n

但 Git 实际上听说过文件重命名的概念,并且它知道当它显示差异或历史记录时,了解文件重命名可能会很有用。因此,当一个文件消失而另一个文件出现时,Git 还会比较这些文件,并尝试确定它们在内容方面是否实际上是“相同”文件。如果您在提交之间所做的只是移动一个文件,而不执行任何其他操作,Git 很可能会得出该文件已重命名的结论。这很好,因为如果您要求跟踪git log文件的历史记录(即git log --follow),Git 可以将移动之前的历史记录和移动之后的历史记录显示为单个历史记录。(记住,Git 对历史一无所知这纯粹是一种显示帮助您(人类)提供方便的

\n

但是 \xe2\x80\x94 这就是我的观点 \xe2\x80\x94 就目前而言。Git 只是一台机器,“非常非常有可能”只不过是它所说的那样。Git 是否真的看到两次提交之间的特定差异(涉及文件重命名)是一个冒险的事情。Git 的行为方式存在不确定性。事实上,你可以尝试影响Git 对此的思考方式;请参阅 的-B-M选项git log,您可以在其中说明两个文件需要有多相似才能被视为同一文件。

\n

而且,你并不是直接使用 Git;而是直接使用 Git。您正在使用 GUI。因此,您依赖 GUI 来完成您无法控制的两件事:GUI对 Git所说的内容,以及 GUI 如何显示Git 对 GUI 所说的内容。这些事情也是不确定的。

\n

因此,由于存在所有这些不确定性,Git 如何理解历史的不确定性以及使用 GUI 添加的额外不确定性,有时 GUI 将文件重命名为纯粹的“一个文件”也就不足为奇了。消失了,另一个文件出现了”\xe2\x80\x94,因为这毕竟是事情的根本真相。

\n