[尝试进行交互式变基时,git说:
error: The following untracked working tree files would be overwritten by checkout:
# some files here
Please move or remove them before you switch branches.
Aborting
error: could not detach HEAD
有问题的文件集似乎会有所不同,具体取决于我为(e)dit标记的提交。它们都是被跟踪的文件,它们已经沿着分支中的提交进行了修改,然后最终在后续提交中被删除。
为什么git这样做?我该如何解决?
谢谢!
Git抱怨,因为文件未跟踪。
我知道你说过:
[[the]文件被跟踪
但不是:您还说过:
它们在以后的提交中最终被删除。
在发生故障时,文件已从索引中删除,但未从工作树中删除。这就是untracked file:的定义,它是工作树中的文件,但不在索引中。
特别是这个:
error: could not detach HEAD
告诉您(或者,无论如何,告诉我)在您现在签出的提示提交中,当您输入命令时,文件当前未被跟踪:
git rebase -i <start-point>
但是这里由git checkout
该提交,但是在签出该提交时,它将用跟踪的文件覆盖未跟踪的文件。
如果最后一点给您带来record-scratch / WTF噪音😀,请放心:这确实令人困惑。Git中的索引是至关重要的小野兽,通常无法正确解释。要理解它,您必须意识到Git始终具有您正在使用/正在使用的每个文件的 three 您下一次提交的文件git checkout
中的提交的out。然后,Git将索引副本以特殊的Git格式复制到您的work-tree中,这是Git放置所有快照文件供您查看和使用的地方。一旦Git复制了这些内容,大部分就完成了。您对工作树副本进行了更改,然后运行git add
告诉Git:将工作树副本复制回索引副本中/上方的索引副本中。 (再次,请参见脚注1。)这样做的原因有些复杂,但是如果您愿意,可以这样考虑:
提交中的副本是只读的,一直冻结。为了节省大量空间,Git将它们保留为仅Git可以使用的特殊的仅Git压缩格式。这对于存档很有意义,但是对于完成[[work
则毫无用处,因此Git必须将文件扩展为正常格式。那是
git add
来替换批发的索引副本:Git将其放入索引中已准备好提交的冻干format中(但仍可以在其中替换) 。git add
将工作树文件复制到该名称下的索引中。要完全删除它,请使用git rm file
。运行git commit
时,Git打包
索引中的所有文件
以创建新提交的快照。索引中的任何内容(无论索引中具有什么形式)都将进入新提交。 Git根本不使用您的工作树。这就是为什么您必须一直重新git-add
文件的原因:Git不在查看工作树副本。2如果工作树文件存在并且索引副本为gone,则该文件为untracked。但是,如果文件位于某个更早的
commit
中,并且您签出了该提交,则来自较早提交的副本将被back into索引,然后再次跟踪该文件。而且,当来自较早提交的副本进入索引时,Git也会覆盖工作树中的副本-除非这样做会浪费它,因为它没有保存在任何地方,在这种情况下,Git表示这样做。 >((如果被跟踪,Git会知道它是否安全地保存在提交中。如果是,则Git可以覆盖它。)因此,现在该怎么办了:如果数据很重要,请将文件移到其他位置。做你的基础。完成后,文件将为[[gone,因为最后一次提交将其删除。现在,您可以将文件移回,并且不会再次跟踪它们。先前具有文件的提交现在仍具有文件;如果您的基准将这些提交复制到新的和改进的提交中,则这些新的和改进的提交仍然具有文件。关键概念:
文件是tracked
还是untracked取决于索引中是否有副本。索引副本大部分是不可见的,3
却非常重要! 索引是一个临时区域。它主要包含您要进行的next提交;当您git checkout
提交时,Git必须从提交中填写。因此,某些文件的跟踪/未跟踪状态可能会突然改变。当Git填充索引from提交时,它将在索引中创建一个文件(如果需要)[删除文件(如果不在您要移动的提交中),并且在那时,它将删除文件从
工作树也是如此。1从技术上讲,索引包含要提交的每个文件的blob对象的reference。就像索引一样,blob对象始终被冻结,并且提交引用了该对象。当您git add
一个文件时,Git会压缩和散列内容,如果已经有一个包含该数据的Blob,则Git可以重新使用现有的Blob。否则,Git会创建一个新的,并且该blob的哈希将进入索引。有时,这会创建一个永远不会使用的blob,因为您在其中写入了一个版本,然后意识到其中存在错误,然后在其中写入了另一个版本。那没关系:Git一直在自行创建垃圾对象。 Git有一个2如果使用git commit -a
,则会创建一个second但临时索引,git add
-s将所有文件都移到该临时索引,并从该临时索引提交。如果一切正常,则临时索引将成为新索引;如果失败,Git只会删除临时索引,然后一切都会恢复到运行git commit -a
之前的状态。 TL; DR是Git仍从索引提交。只是第二个额外索引而已。
3 git status
命令
compares
索引与HEAD
提交的比较,并告诉您什么是[[different。因此,如果文件“丢失”,您会看到一个删除内容,为stage for commit。然后,它分别将索引与工作树进行比较,并告诉您什么是[[different。因此,如果文件在索引中但在工作树中丢失,您将看到一个删除,其删除内容为未暂存以提交。如果文件存在于HEAD
中,但在索引中gone,然后在工作树中为back,您会看到分阶段删除and未跟踪的文件,两者名称相同。
提交历史,其中修改了文件foo.txt
,然后将其删除;此刻,在您跟踪的文件旁边,您的磁盘上还有一个未跟踪的foo.txt
版本。