执行git stash时丢失跟踪文件--include-untracked

问题描述 投票:0回答:1

[当我执行git status时,既有跟踪的文件也有无跟踪的文件。一天早上,我刚刚了解到git stash --include-untracked将存储未跟踪的文件。当时对我有用。因此,我认为git stash --include-untracked将同时保存跟踪文件和未跟踪文件的更改。但是当我git stash apply时,仅剩下未跟踪文件的更改。跟踪文件的更改丢失。

git git-stash git-untracked
1个回答
0
投票

这里有些可疑,但可能不是藏匿处本身

git stash --include-untracked,可以简写为git stash -u,使提交为隐藏。

前两个与通常的两个相同:一个用于保存您在运行git stash时索引中的内容,另一个用于保存工作树中的内容(但仅用于跟踪文件) 。换句话说,保存索引的i提交保存git write-tree的结果,w提交保存git add -u && git write-tree的结果(等效)(尽管隐藏代码很难做到这一点,或者在过去的shell脚本隐藏中做了)。

这就是您运行git stash 没有 --all--include-untracked所具有的全部存储:它将具有i(索引状态)和w(工作树)的两个提交状态),两者都将当前提交C作为其第一父级。提交w具有i作为其第二父级:

...--o--o--C   <-- HEAD
           |\
           i-w   <-- stash

如果您do添加-u-a,则会得到提交存储:提交w获取第三个父级,我们可以将其称为u,包含未跟踪的文件。该第三个父级没有自己的父级(是一个孤儿/根提交),因此图形现在为:

...--o--o--C   <-- HEAD
           |\
           i-w   <-- stash
            /
           u

有关此新提交的有趣的事情,以及它在工作树中的作用是:*提交u包含only未跟踪的文件。**

[请记住,提交是所有(跟踪的)文件的完整快照。提交u是通过(在临时索引中)<< [discarding所有tracked文件进行的,而不是跟踪某些或所有untracked文件。此步骤仅添加未跟踪但未被忽略的文件(git stash -u),或添加all文件(git stash -a)。然后,Git写入提交u,使用git write-tree将临时索引变成要放入提交u的树,以便提交u包含only所选文件。

现在这些选定文件在提交u中,git stash

从工作树中删除它们。实际上,它过去只是使用适当的选项运行git clean。新的C语言编码的git stash仍然可以做到这一点(但是,人们可能希望,它的bug更少;请参见下文)。这类似于对i和/或w中的文件执行的操作:它有效地执行git reset --hard,以便工作树的跟踪文件与HEAD提交匹配。 (也就是说,除非您使用--keep-index,否则它会重置文件以使其与i提交相匹配。)此时的git reset

untracked

文件没有影响,这些文件是不在git reset的范围内,并且对当前分支没有影响,因为重置是故意将其保留在HEAD上。

但是在提交u中隐藏了一些未跟踪的文件,然后git stash然后从工作树中

删除

这些文件。稍后(也许也立即),这一点非常重要。

注意:

在将git stash push与pathspecs结合使用时存在一个错误,可能会影响所有内容,但尤其会影响使用-u-a制成的隐藏变量,其中某些版本的Git删除too许多文件。也就是说,您可能仅git stash个文件子集,但是Git会git reset --hardgit clean all文件,或者文件太多。 (我相信这些问题已在今天修复,但是总的来说,我根本不建议使用git stash,尤其是不要使用奇特的pathspec变体。删除实际上未被隐藏的未跟踪文件特别令人讨厌,并且[一些版本的Git可以做到!)
您描述了apply-时间问题,但也许不是通常的问题

您在这里说的是:

我以为git stash --include-untracked将同时保存跟踪和未跟踪文件的更改。

与往常一样,Git不会保存

更改

,而是保存快照
但是当我'git stash apply'时,只剩下未跟踪文件的更改。跟踪文件的更改丢失。

应用普通(没有未跟踪的文件)存储是通过两种方式之一完成的,具体取决于您是否使用--index标志。不带--index的变体更容易解释,因为它实际上只是[[0]提交]。 (带有i标志的变量首先在差异上使用--index,如果失败,则建议您尝试不使用git apply --index。如果您[[want

--index的效果,这是一个糟糕的建议您应该忽略它。但是,对于此答案,我们将完全忽略--index选项。)

注意:这不是--index标志,而是--keep-index标志。 --index标志仅在creating

隐藏时适用。当

apping隐藏时,--keep-index标志适用。要应用--index提交,Git直接运行w。这不是您作为用户应该执行的操作,当git merge-recursive执行此操作时,这也不是那么明智,但这就是它的功能。效果与运行git stash非常相似,不同之处在于,如果索引和/或工作树中的更改尚未提交,则可能无法以任何自动化方式返回此状态。但是,如果从“干净”索引和工作树开始,即git merge表示git status,则此合并操作与常规nothing to commit, working tree cleangit merge几乎完全相同,很多种方法。 (请注意,至少在默认情况下,git cherry-pickgit merge require

都应保持干净。)合并操作运行时将

merge base

设置为提交git cherry-pick的父项,

current或w提交是照常的当前提交,而另一个或--ours提交则是提交--theirs即,假设您的提交图现在看起来像这样:w

这样您就可以提交 o--o--A--B <-- branch (HEAD) / ...--o--o--C |\ i-w <-- stash / u 。应用隐藏的合并操作执行三向合并,其中B作为合并基础,C作为w提交,当前提交/工作树作为--theirs提交。 Git分别比较--oursC来查看

we

的变化,以及B vs C来查看
they
的变化,并结合两组差异。

这是向w的合并的运行方式,提供 Git首先可以取消隐藏提交B。这时的常见问题是Git cant

取消隐藏u

请记住,提交u完全(且仅)包含您进行隐藏时出现的untracked文件,然后使用u(和适当的选项)删除了Git。 这些文件必须仍在工作树中缺少。

如果没有这些文件,则git clean将无法从git stash apply中提取文件,并且将无法继续。

由于未跟踪的文件已被取消跟踪,因此很难知道它们是否已更改但是当我'git stash apply'时,只剩下未跟踪文件的更改。跟踪文件的更改丢失。

您谈论的是未跟踪文件中的

更改

当然,Git不会存储更改,因此您无法以这种方式找到它们。而且,如果文件未跟踪,它们现在也不在索引中。因此:您怎么知道它们已经

更改?

,您需要将它们与之进行比较的其他文件集。

提取提交u的步骤应该是全部或没有:它应该提取所有u文件,否则不提取。如果确实提取了所有u文件,则u应该继续尝试合并,就好像git stash apply一样(除了Cherry-pick也写入索引),在存储中提交git cherry-pick -n。这将使您在工作树中剩下w -vs- u合并的[[和

提取的w文件。[如果C -vs-work-tree与C -vs- C之间存在冲突,则应该在工作树中显示冲突标记,并且应该像往常一样将索引扩展为冲突的合并。

如果您可以为您的问题制作一个复制器,那么这里可能会提供大量的清晰度。

© www.soinside.com 2019 - 2024. All rights reserved.