“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
    )如何处理 这三个案例(一个基于历史的案例,file
    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)
    $ 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>