bounty将在6天后过期。回答此问题可获得+50的声望奖励。Tudvari正在寻找来自知名来源的答案。
我试着将一个文件移到一个子文件夹中,git发现它只是被“重命名”了...但也发现它的整个内容都被删除了,然后又添加了。
由于某些原因,我可以移动一些文件,而不会丢失它们所有行的实际/正确/原始git blame
。
我在Windows上使用SourceTree。看起来可能不是git的错,而是SourceTree的错?
我在我的另一台电脑上尝试过,也使用Windows 10和SourceTree,一切都在那里工作。我可以在任何地方移动所有东西,而不会触发更改,影响git的指责等。
有什么建议吗?我想应该使用CLI提交文件移动,但我使用SourceTree来避免这种情况。:
x1c 0d1x无论如何,如果没有其他的解决方案,你能推荐一个快速命令来轻松安全地提交整个文件夹及其子文件夹的移动吗?
提前感谢!
2条答案
按热度按时间bjp0bcyl1#
这里有两件事需要了解。
首先,Git对“改变了什么”一无所知。Git完全通过提交来交易。提交不是一个改变或差异;它是项目整个状态的快照。因此,如果你提交了一个文件,然后移动了一个文件,添加了所有内容,然后再次提交,那么你所拥有的就只是一个包含文件A(但不包含文件B)的提交和另一个包含文件B(但不包含文件A)的提交。换句话说,Git对于“发生了什么”是完全中立的;这是 * 人类 * 喜欢思考的事情,但这与Git无关。Git只知道事物有一种状态,然后又有另一种状态。正如李尔王所说,“看看这张照片和这张照片。”
第二,Git也会对人类“友好”,提供“信息”,告诉人类发生了什么变化,尽管它实际上并不知道这件事。当你请求diff时,无论是通过
git show
、git log
还是git diff
,Git都会尝试做人类会做的事情:它会查看第一次提交和第二次提交,并试图“找出它们之间的区别”。这个仓库除了提交之外什么都没有。这些关于不同之处的结论是 * 短暂的 * - Git正在 * 立刻 * 尝试找出这些提交有什么不同,纯粹是为了向你展示不同之处。(The这个规则的一个例外是当Git执行合并时,合并是指Git计算一个diff,并实际上 * 使用 * 它来生成一个全新的提交。所有使用合并逻辑的命令-
git merge
,git cherry-pick
,git rebase
-都是这样操作的。现在,我们来看看Git如何向人类 you 显示两次提交之间的差异。如果你提交了一个文件,然后移动一个文件,添加所有内容并提交,对Git来说,唯一发生的事情就是一个文件消失了(被删除),另一个文件出现了(被创建)。也就是说,它的后备位置:“这是我的故事,我坚持它。”你必须承认,这是一个很好的岩石底部描述发生了什么。
但是Git实际上听说过文件重命名的概念,它知道当它显示diff或历史记录时,知道文件重命名可能是有用的。因此,当一个文件消失而另一个出现时,Git也会比较这些文件,并试图判断它们是否在 * 内容 * 方面实际上是“相同的”文件。如果你在两次提交之间所做的只是移动一个文件,Git很可能会得出文件被重命名的结论。这很好,因为如果你要求做一个
git log
,你可以追溯一个文件的历史(即git log --follow
),Git就可以把移动前的历史和移动后的历史作为一个历史来显示。(记住,Git对历史一无所知;这纯粹是一个 * 显示 * 方便,以帮助你,人类。)但这也是我的观点。Git只是一台机器,“非常非常有可能”并不比它说的多。Git * 是否 * 会 * 实际上将两次提交之间的特定差异视为涉及文件重命名是一种冒险。* 这里有不确定性 * 关于Git将如何行为。事实上,你可以尝试 * 影响 * Git对此的思考方式;请参阅
git log
的-B
和-M
选项,您可以在其中说明两个文件需要多么相似才能被视为同一个文件。而且,你 * 没有 * 直接使用Git;您使用的是GUI。因此,您需要依赖GUI来完成两件您无法控制的事情:GUI对Git说了什么,GUI如何显示Git对GUI说了什么。2这些事情也是不确定的。
因此,在所有这些不确定性的情况下,包括Git如何理解历史记录的不确定性,以及使用GUI所增加的额外不确定性,如果有时GUI显示文件重命名为纯粹的“一个文件消失,另一个文件出现”也就不足为奇了--因为这毕竟是最基本的事实。
xqnpmsa82#
Git使用一种称为“基于内容的寻址”的技术来确定文件是否被修改,这意味着它会查看文件的实际内容,而不是文件的名称或位置,来确定文件是否被修改。
避免这个问题的一个方法是使用命令来移动文件,而不是使用文件系统来移动文件。这将告诉Git跟踪文件的移动,这样你就不会丢失文件的历史记录。
例如,若要将名为的档案从目前目录移至名为的子目录,您可以使用下列命令:
这将移动文件并更新Git存储库以跟踪移动。
或者,如果您想要移动整个目录及其所有内容,您可以搭配使用选项,以递归方式移动目录。例如,若要将名为的目录及其所有内容移至名为的子目录,您可以使用下列命令:
这将移动目录及其所有内容,并更新Git存储库以跟踪移动。
我希望这对你有帮助!如果你有任何其他问题,请告诉我。
更新日期:
另一个选择是在Git配置中使用core.symlinks设置。此设置允许Git在Windows上正确处理符号链接,这有助于解决文件移动相关的问题。
//启用设置的命令:
git config --global core.symlinks true
//禁用设置的命令:
git config --global core.symlinks false