“git stash”如何处理未跟踪的文件?
“git stash”如何处理未跟踪的文件?,git,git-stash,Git,Git Stash,git如何处理未跟踪的文件 Git官方文档()将Git stash定义为 git-stash - Stash the changes in a dirty working directory away 但对我(git的初学者)来说,什么是 “脏工作目录”的确切定义。没有追踪 包括哪些文件 更准确地说,我注意到 在“脏”工作目录中,我们可以有三种类型的脏状态: 在运行文件之前对文件所做的更改git add(更改在索引中) 运行文件后对文件所做的更改git add(更改不在索引中,但跟踪文件,也称
git如何处理未跟踪的文件
Git官方文档()将Git stash
定义为
git-stash - Stash the changes in a dirty working directory away
但对我(git的初学者)来说,什么是
“脏工作目录”的确切定义。没有追踪
包括哪些文件
更准确地说,我注意到
在“脏”工作目录中,我们可以有三种类型的脏状态:
在运行文件之前对文件所做的更改git add
(更改在索引中)
运行文件后对文件所做的更改git add
(更改不在索引中,但跟踪文件,也称为“要提交的更改”)
对从未运行过的git add
文件所做的更改(该文件未跟踪)
当我们运行git stash
时,#1、#2和#3会发生什么?我认为它们的意思是实际的更改只是git正在跟踪的文件中的更改
在某种程度上,这在git中是有意义的,因为如果您有一个未跟踪的文件,那么它不是一个更改,除非您跟踪它,否则它什么都不是。您甚至可以使用未跟踪的更改在分支之间自由切换
然而,从git的外部来看,这是错误的,因为这是本地存储库中的一个实际更改,但是由于我们讨论的是git特性,因此git中的视图是正确的,尽管它可能看起来有点不直观
这看起来可能是一个意见问题,但由于更改是git中的一个关键字,因此它必须具有单一含义
较长的描述解决了这一问题:
该命令保存本地修改并还原工作目录以匹配头提交
我试图在这里提供我自己的答案
我是新来的git
。但对我来说,描述命令的一行应该修改为
git-stash - Stash away the tracked changes in a dirty working directory
(untracked changes are ignored)
换句话说,git stash
(没有选项-u
)将存储1和2,但不存储3。如果#1和#2发生在同一个文件上,那么#2将优先于#1
使用选项-u
,git stash-u
还可以包括未跟踪的文件。
有关更多详细信息,请参阅本文()
实验
下面的实验显示了git stash
(使用-u
)如何处理
这三个案例(一个基于历史的案例,filet1.txt
)也包括在内
设置四种不同的状态
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Hello" > t1.txt ; git add t1.txt ; git commit -m "Add t1.txt"
[f2 7367b85] Add t1.txt
1 file changed, 1 insertion(+)
create mode 100644 tmp/t1.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Hello in Index" > t1.txt ; git add t1.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Hello in Working Directory (tracked)" > t1.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Bonjour in Working Directory (untracked)" > t2.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git status
On branch f2
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: t1.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: t1.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
t2.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git diff --cached t1.txt
diff --git a/tmp/t1.txt b/tmp/t1.txt
index e965047..a863c48 100644
--- a/tmp/t1.txt
+++ b/tmp/t1.txt
@@ -1 +1 @@
-Hello
+Hello in Index
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git diff t1.txt
diff --git a/tmp/t1.txt b/tmp/t1.txt
index a863c48..a0c6962 100644
--- a/tmp/t1.txt
+++ b/tmp/t1.txt
@@ -1 +1 @@
-Hello in Index
+Hello in Working Directory (tracked)
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ cat t2.txt
Bonjour in Working Directory (untracked)
检查四种状态
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Hello" > t1.txt ; git add t1.txt ; git commit -m "Add t1.txt"
[f2 7367b85] Add t1.txt
1 file changed, 1 insertion(+)
create mode 100644 tmp/t1.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Hello in Index" > t1.txt ; git add t1.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Hello in Working Directory (tracked)" > t1.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ echo "Bonjour in Working Directory (untracked)" > t2.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git status
On branch f2
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: t1.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: t1.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
t2.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git diff --cached t1.txt
diff --git a/tmp/t1.txt b/tmp/t1.txt
index e965047..a863c48 100644
--- a/tmp/t1.txt
+++ b/tmp/t1.txt
@@ -1 +1 @@
-Hello
+Hello in Index
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git diff t1.txt
diff --git a/tmp/t1.txt b/tmp/t1.txt
index a863c48..a0c6962 100644
--- a/tmp/t1.txt
+++ b/tmp/t1.txt
@@ -1 +1 @@
-Hello in Index
+Hello in Working Directory (tracked)
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ cat t2.txt
Bonjour in Working Directory (untracked)
如果您丢失了t2.txt;git stash将无法为您恢复它
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ rm t2.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git stash pop
On branch f2
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: t1.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (6a004ffe723ae18d9d5a314c0f5460622b27e300)
在一对git stash
和git stash pop
操作后,#1
也丢失了。
保留的是#2
。换句话说,工作目录状态在隐藏操作中具有优先权
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ cat t1.txt
Hello in Working Directory (tracked)
git如何处理未跟踪的文件
在Git2.16.x/2.17之前,可能会很糟糕
“git stash--
”错误地吹走了中未跟踪的文件
与已更正的pathspec匹配的目录
参见(2018年1月6日)作者。
帮助人:。
(于2018年1月23日被合并)
隐藏
:不要删除与pathspec匹配的未跟踪文件
(见)
当前使用“git隐藏推送--
”时,未跟踪的文件
与pathspec匹配的将被删除,即使它们不会结束
藏在任何地方
这是因为原始提交在中引入了pathspec功能
git stash push
(“stash:teach'push'(和'create_stash')将
《荣誉路径规范》,2017-02-28,Git v2.13.0-rc0)使用了以下顺序:
git重置和&git ls文件--已修改|
git签出索引(&git-clean)
其目的是模拟“git reset--hard--
”将要实现的功能
可以。
对“git clean
”的调用本应清理
已通过“git reset
”取消老化。
如果pathspec与“git隐藏推送--
”之前未跟踪的任何文件不匹配,这将很好地工作。
但是,如果
匹配在调用“隐藏”命令之前未跟踪的文件,则所有与pathspec匹配的未跟踪文件也会被无意中删除,即使它们不会最终保存在隐藏中,因此会丢失
这种行为从来就不是我们想要的,只是最终也会变成斑点
在贮藏中,应重置为其在头部的状态,之前
未跟踪的文件应单独保存
为实现这一目标:
- 首先匹配索引中的内容和
通过将所有更改添加到索引来工作树
- 询问
diff index
在HEAD
和当前索引之间发生了什么变化,以及
- 然后反向应用该补丁以消除更改,包括删除添加的文件和恢复删除的文件
由于指针的原因,可能会重复。但是我想,如果人们认识到git stash
(不带-u参数)的确切语义,那么另一篇SO文章可能会有所帮助。我的问题更多的是关于官方文件中的一行描述并不是最精确的描述。对于“文档声明X似乎有误导性,Y不是更好吗?”这个问题的答案通常是“是的”(不仅仅是Git)。但这不是真正的编程问题。它可以被重新表述为:“我读了文档并假设了X。然后我运行了命令,但X没有发生。为什么?”然后答案适用于。。。但这也无法修复文档!修复文档的唯一方法是向维护文档的人提交请求。git stash
摘要的另一个误导之处在于,它不仅隐藏工作树修改:它还
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ cat t1.txt
Hello in Working Directory (tracked)
git reset <pathspec> && git ls-files --modified <pathspec> |
git checkout-index && git clean <pathspec>