`git stash`如何处理未跟踪的文件?

时间:2017-09-22 14:06:33

标签: git git-stash

git stash如何处理未跟踪的文件?

Git官方文档(link)将git-stash定义为

git-stash - Stash the changes in a dirty working directory away

但对我来说(git的初学者),它的含义并不是很明显 “脏工作目录”的确切定义。没有跟踪 包含文件?

更确切地说,我注意到了 在“脏”工作目录中,我们可以有三种类型的脏状态:

  1. 在文件运行之前对文件所做的更改git add(更改在索引中)
  2. 文件运行后对文件进行的更改git add(更改不在索引中,但跟踪文件又称“要提交的更改”)
  3. git add从未运行过的文件所做的更改(文件未跟踪)
  4. 当我们运行git stash时,#1,#2和#3会发生什么?

3 个答案:

答案 0 :(得分:1)

我认为他们的意思是实际的更改只是git正在跟踪的文件中的更改。

以一种在git中出现的方式,因为如果你有一个未跟踪的文件,那么它不是一个改变,直到你跟踪它是没有的。您甚至可以使用未跟踪的更改自由切换分支之间的分支。

从git的外部然而这是错误的,因为它是本地存储库中的实际更改,但由于我们正在讨论git功能,因此git中的视图是正确的,即使它看起来有点非didatic。

这可能看起来像是一个意见问题,但由于更改是git中的关键字,因此它必须具有单一含义。

较长的描述解决了它:

  

该命令将您的本地修改保存起来,并恢复工作目录以匹配 HEAD 提交。

答案 1 :(得分:0)

我想在这里提供自己的答案。

我是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。

使用选项-ugit stash -u还可以包含未跟踪的文件。 有关详细信息,请参阅此SO文章(link)。

<强>实验

以下实验说明了git stash-u)如何处理 还包括三种情况(基于案例,历史中的文件t1.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)
$ git stash
Saved working directory and index state WIP on f2: 7367b85 Add t1.txt

MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git status
On branch f2
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        t2.txt

nothing added to commit but untracked files present (use "git add" to track)

请注意,git stash

未处理t2.txt
MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ git stash show
 tmp/t1.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

如果你输了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)

索引与已跟踪(未提交的更改)

顺便说一下,还要注意发生在

状态的事情
#1 "Hello in Index" (of t1.txt in index before `git stash`)
#2 "Hello in Working Directory (tracked)" (of t1.txt in worktree before `git stash`)
经过一对#1git stash操作后,

git stash pop也丢失了。 保留的是#2。换句话说,工作目录状态在存储操作中优先。

MINGW64 ~/proj/tmp/sandbox/tmp (f2)
$ cat t1.txt
Hello in Working Directory (tracked)

答案 2 :(得分:0)

  

git stash如何处理未跟踪的文件?

在Git 2.16.x / 2.17之前,可能很糟糕! &#34; git stash -- <pathspec>&#34;错误地将未经跟踪的文件吹走了 与pathspec匹配的目录,已经更正。

commit bba067dThomas Gummerer (tgummerer)(2018年1月6日) 帮助:Junio C Hamano (gitster)
(由Junio C Hamano -- gitster --合并于commit 087d1a8,2018年1月23日)

  

stash:不要删除与pathspec匹配的未跟踪文件

Git Glossary pathspec

  

目前{&#39; git stash push -- <pathspec>&#39;使用,未跟踪的文件   匹配pathspec的将被删除,即使它们没有结束   藏在任何地方。

     

这是因为原始提交引入了pathspec功能   git stash pushdf6bba0(&#34; stash:teach&#39; push&#39;(和&#39; create_stash&#39;)   荣誉pathspec&#34;,2017-02-28,Git v2.13.0-rc0))使用了以下序列:

git reset <pathspec> && git ls-files --modified <pathspec> | 
  git checkout-index && git clean <pathspec>
  

目的是模仿&#39; git reset --hard -- <pathspec>&#39;将   这样做。
  致电&#39; git clean&#39;应该清理那些文件   没有被&#39; git reset&#39;   如果在几个未跟踪的文件之前匹配任何文件,那么这将正常工作。git stash push -- <pathspec>&#39;。
  但是,如果<pathspec>与未调整的文件匹配,则会在调用&#39; stash&#39;之前命令,所有与pathspec匹配的未跟踪文件也会被无意中删除,即使它们不会在藏匿处结束,因此也会丢失

     

这种行为绝不是预期的,只有blob也会结束   之前,存储区应该重置为HEAD中的状态   未跟踪的文件应该保持不变。

     

实现这一目标:

     
      
  • 首先匹配索引中的内容以及中的内容   通过向索引添加所有更改来工作树,
  •   
  • 询问diff-index HEAD与当前索引之间的变化,以及
  •   
  • 然后反向应用该补丁以消除更改,包括删除添加的文件和复制已删除的文件。
  •