Git拉取失败:(技巧)您的本地更改将被合并覆盖



Git Pull失败:您的本地更改将被合并覆盖。提交、隐藏或还原它们以继续。当我单击链接查看这些文件时,我会看到一个名为Environment.config的文件。令人惊讶的是,我的.gitignore文件中有它和Run.config,比如。。

# General Config files, both originally tracked(but modified for only this project)
Run.config
Environment.config 

首先,我不知道为什么只有Environment.config被指出正在更改,尽管这两个文件都已为我的本地项目更改并输入到.gitignore文件中。

第二,我运行这个命令来删除被跟踪的文件。

git update-index --assume-unchanged <file>

我可以把我的本地更改发送到远程。但经过一些开发,当我尝试提交,然后从远程拉取时,我就陷入了这种"Git拉取失败"的情况。

当我通过"git status"或IntelliJ工具的本地更改视图检查本地更改时,我没有发现任何更改。为什么要报告此幻影文件更改?

这并不"棘手",这很正常。

文件位于.gitignore中并且没有被跟踪,这就是问题所在。这意味着您没有提交此版本的文件。因此,它是工作树中未提交的文件。但repo中也有一个早期版本的同一文件,这是您提交时的早期版本。因此,一个简单的pull会覆盖工作树版本,git会阻止您。git正确地告诉你完成这个拉动的选择是什么。倾听并服从;选择一个:

  • 使索引中的版本与工作树中的版本匹配,这称为提交

  • 使工作树中的版本与索引中的版本匹配,这称为revert,或者您可以使用restore

  • 将工作树中的版本移到一边,这称为隐藏

长期解决方案是git rm --cached此文件以从索引中删除旧版本,并提交和推送。现在,下次拉时它不会出现在远程的提交中,因此不会有冲突。

其次,我运行这个命令来删除被跟踪的文件。

git update-index --assume-unchanged <file>

这不会使文件不被跟踪。

记住,被跟踪文件的定义是存在于Git索引中的文件。根据定义,未跟踪文件是指存在于工作树中但不存在于Git索引中的文件。

使用CCD_ 2将索引中的文件标记为"0";假定不变";。(类似的--skip-worktree将文件的同一索引副本标记为"跳过工作树"。)在这两种情况下,文件仍在Git的索引中。

根据定义,Git索引中的文件是被跟踪的。。。因此这些文件被跟踪。

当我通过"git status"检查本地更改时。。。

git status命令通过运行两个单独的比较来工作。

  • 第一个将当前提交与Git索引中的内容进行比较。我们可以暂时忽略这个比较,但如果它发现任何差异,它会打印文件的名称,首先说有的更改准备提交

  • 第二个比较将Git索引中的每个文件与工作树中的相同文件进行比较。如果它们不同,Git会打印文件名,首先表示有更改未提交

在Git索引中的文件副本上设置两个标志中的任何一个,只需告诉git status不要查看工作树副本。也就是说,git status应该只是假设文件是不变的。毕竟,这就是为什么第一个标志被命名为";假定不变";。

(第二个标志只是用于稀疏签出代码的一个微小变体。第一个标志——假设不变的标志——用于慢速系统。从技术上讲,使用任何一个标志都是对这两种内部机制的滥用。)

因为文件在Git的索引中,所以它被跟踪。只是git status对此闭口不言。但git checkout和其他几个Git命令无论如何都会检查它。在这种特殊情况下,git pull调用git merge的方式使得git merge希望覆盖工作树副本,同时替换这两个文件中每个文件的索引副本。Git绕过这两个标志,注意到这两个文件的工作树副本与当前的索引副本不同,并正确地告诉您,如果命令要完成,将销毁未保存的工作树数据1

如果您不希望未保存的工作树数据被销毁,则您的工作是将它们保存到某个位置。由于Git看到它们被跟踪,它建议你提交它们,即使你真正想要的是将它们从工作树中移出,这样当Git破坏你的工作树文件时,它就不会破坏这些文件。

如果你不关心这两个文件中的数据,你可以自己删除它们。如果你确实关心数据,不要删除它们,也不要让Git破坏它们——现在还没有!将它们保存在的某个地方,在Git销毁这些副本后,您可以将它们取回然后让Git销毁它们,也许可以清除假设不变的标志,这样你就可以看到你在做什么。

注意:一旦你让Git通过将其他提交的副本提取到你的工作树中来销毁这些副本,你就可以通过将保存的副本复制到适当的位置来销毁Gitput你的工作目录树中的副本。然后,如果您愿意,您可以再次设置"假定未更改"标志。


1记住,所有工作树数据——您的文件的所有都不在Git中。它们的内容不是一直安全存储的。

Git提交的文件安全地存储在.git文件夹中的大型Git数据库中的Git提交中。这些提交是只读的:在所有时间内都被冻结,或者至少在提交本身继续存在的时间内被冻结。

提交包含快照。每次提交都有一个完整的所有文件的副本——好吧,在运行git commit时,你告诉Git跟踪的所有文件(因此在Git的索引中)。这些文件是一种特殊的仅限Git的格式,并且是重复数据消除的,因此同一个README.md文件有数百万(或数百,或其他)副本的事实并不令人担忧:实际上只有一个副本。

当您git checkout某个提交时,Git会提取这些冻结的文件——这些文件的格式仅为Git;你电脑上没有其他程序可以使用它们——将它们转换成普通的日常文件。这些日常文件就是您的,您可以在工作树中随意处理。但有一个奇怪的中间步骤:Git首先将2文件复制到Git的索引中,为下一次提交做好准备。

索引也被称为暂存区,它的存在是您必须始终使用git add的原因。假设您签出的提交中有一个冻结格式的README.md文件。该冻结文件也进入了Git的索引,然后Git将索引副本恢复为正常文件。这就是您在工作树中看到的README.md:普通文件。但是,如果您已经更改了,现在您需要让Git将新的README.md复制回Git的索引/暂存区域。git update-index --assume-unchangedpath0就是这样做的:它替换索引中的现有副本,或者根据需要将一个全新的文件放入索引中。

Git放在Git索引中的文件副本只保存了一半,所以它们也是临时的。但只要它们是直接从提交中出来的,那也没关系,因为提交会永远保存它们。

2从技术上讲,索引没有文件的完整副本。相反,它有文件的名称——一个完整的路径名称,包含正斜杠(即使在Windows Git上也使用正斜杠)——以及它的模式,100644表示不可执行文件,100755表示可执行文件——然后是Gitblob哈希ID。内部Git blob对象是Git存储(和消除重复)文件内容的方式。还有一些字段可以让Git快速运行,还有一些标志。但是,除非您开始转储原始索引内容,例如使用git ls-files --stage,或者使用git update-index更新它们,否则您不需要知道这一点。即使在使用假设不变的标志时,您仍然不需要真的需要知道这一点:您只需要知道Git从Git的索引而不是从您的工作树中进行提交。

最新更新