[当我执行git status
时,既有跟踪的文件也有无跟踪的文件。一天早上,我刚刚了解到git stash --include-untracked
将存储未跟踪的文件。当时对我有用。因此,我认为git stash --include-untracked
将同时保存跟踪文件和未跟踪文件的更改。但是当我git stash apply
时,仅剩下未跟踪文件的更改。跟踪文件的更改丢失。
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
从工作树中删除它们。实际上,它过去只是使用适当的选项运行 untrackedgit clean
。新的C语言编码的git stash
仍然可以做到这一点(但是,人们可能希望,它的bug更少;请参见下文)。这类似于对i
和/或w
中的文件执行的操作:它有效地执行git reset --hard
,以便工作树的跟踪文件与HEAD
提交匹配。 (也就是说,除非您使用--keep-index
,否则它会重置文件以使其与i
提交相匹配。)此时的git reset
对git reset
的范围内,并且对当前分支没有影响,因为重置是故意将其保留在HEAD
上。
u
中隐藏了一些未跟踪的文件,然后git stash
然后从工作树中删除
这些文件。稍后(也许也立即),这一点非常重要。注意:
在将git stash push
与pathspecs结合使用时存在一个错误,可能会影响所有内容,但尤其会影响使用-u
或-a
制成的隐藏变量,其中某些版本的Git删除too许多文件。也就是说,您可能仅git stash
个文件子集,但是Git会git reset --hard
或git 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 clean
或git merge
几乎完全相同,很多种方法。 (请注意,至少在默认情况下,git cherry-pick
和git 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分别比较--ours
与C
来查看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
之间存在冲突,则应该在工作树中显示冲突标记,并且应该像往常一样将索引扩展为冲突的合并。如果您可以为您的问题制作一个复制器,那么这里可能会提供大量的清晰度。