作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想隐藏未跟踪的文件,但我一直传递错误的选项。对我来说,这听起来不错:
git stash save [-a|--all]
git stash save [-u|--include-untracked]
git stash save -a
并尝试
git stash pop
时,对于所有被忽略的文件,我都会收到无数错误:
path/to/file1.ext already exists, no checkout
path/to/file1.ext already exists, no checkout
path/to/file1.ext already exists, no checkout
...
Could not restore untracked files from stash
git reflog
不存储隐藏命令。
最佳答案
TL; DR版本:
您需要清洁目录(用git clean
表示),以便正确应用存储。这意味着运行git clean -f
或什至git clean -fdx
这是一件很丑的事情,因为某些未跟踪或未被跟踪且忽略的文件/目录可能是您要保留的项目,而不是删除完全。 (如果是这样,则应将它们移到工作树之外,而不要git clean
-将其移开。请记住,git clean
删除的文件正是您无法从Git取回的文件!)
若要查看原因,请查看“应用”描述中的步骤3。请注意,没有选项可以跳过存储中未跟踪和/或忽略的文件。
关于隐藏本身的基本事实
当将git stash save
与-u
或-a
一起使用时,隐藏脚本会将其"stash bag"作为三父提交而不是通常的双父提交写入。
用提交图的形式,“存储袋”通常看起来像这样:
o--o--C <-- HEAD (typically, a branch)
|\
i-w <-- stash
o
是任何旧的普通提交节点,
C
也是如此。节点
C
(用于Commit)有一个字母,因此我们可以为其命名:这是“存储袋”的悬挂位置。
C
上的三角形小袋,它包含两个提交:
w
是工作树提交,而
i
是索引提交。 (未显示,因为很难绘制,是
w
的第一个父级是
C
而第二个父级是
i
的事实。)
--untracked
或
--all
时,
w
有第三个父级,因此该图看起来更像这样:
o--o--C <-- HEAD
|\
i-w <-- stash
/
u
stash
是提交
w
,
stash^
是提交
C
(还是
HEAD
),
stash^2
是提交
i
,而
stash^3
是提交
u
,其中包含“未跟踪”甚至“未跟踪和忽略”的文件。 (据我所知,这实际上并不重要,但是我要在这里添加
i
以
C
作为父提交,而
u
是无父母或根提交。似乎没有这样做的特殊原因,只是脚本的工作方式,但它解释了为什么“箭头”(线)与图中的一样。)
save
时的各种选项
-p
,
--patch
-k
,
--keep-index
,
--no-keep-index
-q
,
--quiet
-u
,
--include-untracked
-a
,
--all
-p
完全更改了脚本用于构建存储的算法,并且还打开了
--keep-index
,如果不希望使用
--no-keep-index
则将其关闭。它与
-a
和
-u
不兼容,如果给出任何一个,将出错。
-a
和
-u
之间的最后一个。
C
-u
或
-a
一起,是一个无父母的提交,其中包含(仅)未跟踪的文件或所有(未跟踪和忽略的)文件。
stash
脚本保存您当前的工作树。它使用一个临时索引文件(基本上是一个新的暂存区)来执行此操作。使用
-p
,脚本将
HEAD
提交读出到新的暂存区域中,然后有效地运行
git add -i --patch
,这样该索引就会随着您选择的补丁而结束。如果没有
-p
,它只会将工作目录与隐藏的索引进行比较,以查找更改的文件。2无论哪种情况,它都会从临时索引中写入树对象。该树将成为提交
w
的树。
C
,索引提交以及未跟踪文件的根提交(如果存在)创建最终的存储提交
w
。但是,脚本随后会根据影响您的工作目录的位置执行其他几个步骤,具体取决于您使用的是
-a
,
-u
,
-p
和/或
--keep-index
(并且请记住,
-p
表示
--keep-index
:
-p
和存储之间的差异。从本质上讲,这将使工作目录仅保留未更改的更改(特别是那些不在提交
HEAD
中的更改;此处忽略提交
w
中的所有内容)。
i
时:运行
--no-keep-index
(根本没有任何选项,即
git reset
)。这将清除所有内容的“待提交”状态,而不更改其他任何内容。 (当然,在运行
git reset --mixed
之前使用
git stash save -p
或
git add
进行的任何部分更改都保存在提交
git add -p
中。)
i
:
-p
(如果也指定了
git reset --hard
,请运行
-q
)。这会将工作树设置回
HEAD
提交中的状态。
-a
或
-u
时:运行
git clean --force --quiet -d
(如果
-x
,则使用
-a
;如果
-u
,则不使用)。这将删除所有未跟踪的文件,包括未跟踪的目录;使用
-x
(即在
-a
模式下),它还会删除所有忽略的文件。
-k
/
--keep-index
时:使用
git read-tree --reset -u $i_tree
将隐藏的索引“带回”为也将出现在工作树中的“要提交的更改”。 (自第1步清除工作树以来,
--reset
应该无效。)
apply
时的各种选项
apply
和
pop
。
pop
代码仅运行
apply
,然后,如果
apply
成功,则运行
drop
,因此实际上实际上只有
apply
。 (嗯,还有
branch
,它稍微复杂一些,但最后它也使用
apply
。)
-q
,
--quiet
--index
(不是
--keep-index
!)
show
使用相同的解析代码,此处其他标志传递给
git diff
。)
w
,
i
和
u
表示存储中的各种提交,并使用
C
表示存储袋挂起的提交。
apply
序列是这样的,假设一切顺利(如果某件事很早就失败了,例如,我们处于合并的中间,或者
git apply --cached
失败了,脚本将在此时出错):
--index
:与commit
i
进行diff commit
C
,通过管道传输到
git apply --cached
,保存生成的树,并使用
git reset
取消登台时
u
存在时:将
git read-tree
和
git checkout-index --all
与临时索引一起使用以恢复
u
树
git merge-recursive
将
C
的树(“基础”)与步骤1中写的树(“更新的上游”)和
w
中的树合并(“隐藏的更改”)
git write-tree
,如果索引中存在未合并的条目,则脚本将失败。如果写树有效,则结果为树ID(脚本中的
$c_tree
)。
--index
选项,而且还会检查
$b_tree != $i_tree
(即,
C
的树与
i
的树之间存在差异)和
$c_tree
(即,在步骤1中写出的树与
$i_tree
的树之间存在差异)。
i
的测试很有意义:它正在检查是否有任何要应用的更改。如果没有任何变化(如果
$b_tree != $i_tree
的树与
i
的树匹配),则没有要还原的索引,并且根本不需要
C
。但是,如果
--index
与
$i_tree
匹配,则仅意味着当前索引已包含要通过
$c_tree
恢复的更改。的确,在这种情况下,我们不想
--index
进行这些更改。但我们确实希望他们保持“恢复”状态。 (也许这就是我在下面不太了解的代码的重点。不过,这里似乎更可能有一个小错误。)
git apply
,它也将运行
git apply --cached
编写树,并将其保存在脚本的
git write-tree
变量中。否则,
$unstashed_index_tree
将留空。
$unstashed_index_tree
提交存在于存储中,脚本将坚持将其提取,但是如果其中任何一个文件被覆盖,则
u
将失败。 (请注意,这是通过一个临时索引文件完成的,此文件随后将被删除:步骤3完全不使用常规暂存区。)
git checkout-index --all
提供了要合并的树的“名称”。要运行
$GITHEAD_t
,该脚本提供了四个参数:
git merge-recursive
$b_tree
< cc>
--
。如前所述,这些是基本提交
$c_tree
,开始索引的
$w_tree
和隐藏的工作提交
C
的树。在这些树中,
apply
在环境中查找通过在每个树的原始SHA-1前面加上
w
形成的名称,该脚本不会将任何策略参数传递给
git merge-recursive
,也不允许您选择除以下以外的任何策略
GITHEAD_
。也许应该。)
git merge-recursive
(q.v.),如果
recursive
,则将告诉您索引尚未还原,并以合并冲突状态退出。 (与其他早期出口一样,这防止
git rerere
放下藏匿处。)
--index
,即我们正在做
pop
,并且步骤2中的所有其他测试也都通过了,那么我们需要恢复在步骤2中创建的索引状态。在这种情况下,一个简单的
$unstashed_index_tree
(没有选项)可以解决问题。
--index
中没有东西,脚本将使用
git read-tree $unstashed_index_tree
查找要添加的文件,运行
$unstashed_index_tree
对原始保存的索引进行单树合并,然后使用文件名进行
git diff-index --cached --name-only --diff-filter=A $c_tree
来自早期的
git read-tree --reset $c_tree
。我不太确定为什么要达到这些长度(
git update-index --add
手册页中有一个提示,即避免对修改后的文件造成错误命中,这也许可以解释这一点),但这就是它的作用。
diff-index
(对于
git-read-tree
模式,输出发送到
git status
;不确定为什么在
/dev/null
下运行)。
-q
的几句话
-q
的存储的问题不适用,除非您清除未暂存的文件,甚至可能先忽略文件)。
git stash branch
(例如,
u
)开始。当然,这会导致“分离的HEAD”,因此您需要创建一个新分支,可以将其与检出commit
C
的步骤结合使用:
git checkout -b new_branch stash^
git checkout stash^
,您也可以应用存储,并且它应该工作,因为它将应用于存储袋挂起的相同提交:
git stash apply --index
git stash drop
git stash branch new_branch
C
,如果成功,则应用存储(带有
--index
),然后将其删除。
o-o-C-o-... <-- some_branch
\
I-W <-- new_branch
git checkout -b
和
--index
提交转换为普通的分支提交
i
和
w
。
I
,它直接调用perl脚本进行交互式添加,并为存储设置了特殊的魔术。还有其他一些魔术
W
模式;参见脚本。
git add-interactive --patch=stash --
读取到临时索引中,然后将工作目录与
--patch
进行比较。这意味着,如果您更改了索引中的某些文件
$i_tree
,然后又将其更改回以匹配
HEAD
版本,则存储在存储袋中
f
下的工作树将包含索引版本
HEAD
,
w
的工作树版本。
关于git - 如何从“git stash save --all”中恢复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20586009/
我是一名优秀的程序员,十分优秀!