Does git “dirty” mean files not staged, or not committed? (glossary conflict)

前端 未结 3 1962
情书的邮戳
情书的邮戳 2020-12-31 03:49

https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html#def_dirty A working tree is said to be \"dirty\" if it contains modifications which have not been committed

相关标签:
3条回答
  • 2020-12-31 04:04

    From torek's answer:

    What git status tells you is both the answer to:

    • "what, if anything, is staged for commit" and
    • "what, if anything, is different between the work-tree and the index".

    Note that only the working tree is involved with git status, not the "working directory".

    Git 2.9.1+ (Q3 2016) will make that clearer.
    See commit 2a0e6cd (09 Jun 2016) by Lars Vogel (vogella).
    (Merged by Junio C Hamano -- gitster -- in commit a010d61, 27 Jun 2016)

    Use "working tree" instead of "working directory" for git status

    Working directory can be easily confused with the current directory.
    In one of my patches I already updated the usage of working directory with working tree for the man page but I noticed that git status also uses this incorrect term.

    0 讨论(0)
  • 2020-12-31 04:15

    According to the official Git documentation, in the section on Stashing, a dirty state is defined as ... the dirty state of your working directory — that is, your modified tracked files and staged changes. From this definition, files staged for commit are dirty as well. This means that the kernel.org article is correct, while the gitguys.com article is pretty much wrong. You should probably point this out to them.

    0 讨论(0)
  • 2020-12-31 04:28

    They're actually both reasonable claims. I think the "best answer" is that both are wrong, although the former (the kernel.org version) is probably closer.

    Consider:

    $ mkdir /tmp/repo && cd /tmp/repo
    $ git init
    Initialized empty Git repository in /tmp/repo/.git/
    $ echo contents > file
    $ git add file
    $ git commit -m initial
    [master (root-commit) e1731a6] initial
     1 file changed, 1 insertion(+)
     create mode 100644 file
    

    We now have a repository with one commit containing one file.

    $ echo second line >> file; git add file; echo contents > file
    

    At this point, the index has file with two lines in it. But the work-tree version of file has just the one line in it, and matches what's in the repository.

    Is file dirty? Well, git status --short says that it is, twice (two Ms). Both git diff and git diff --cached show changes (so yes, it's "dirty"), but git diff HEAD says there's no change, and if we git add it again and try git status:

    $ git status --short
    MM file
    $ git diff HEAD
    $ git add file
    $ git status
    # On branch master
    nothing to commit, working directory clean
    

    Let's put that odd change back and do one more thing. This time let's use the long form of git status so that it gives us more information:

    $ echo second line >> file; git add file; echo contents > file
    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #   modified:   file
    #
    # 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:   file
    #
    

    It says we can use git reset (which is the same as git reset --mixed) with HEAD and the file name to un-stage; surely that will make the working directory dirty? :-)

    $ git reset HEAD file
    $ git status
    # On branch master
    nothing to commit, working directory clean
    

    No, in fact, it makes the working directory clean again! This follows from the (lack of) output of git diff HEAD: "un-staging" the change that adds the second line makes the index refer to the HEAD version, and the working-directory version is the same as the HEAD version, so un-staging the "changes to be committed" causes there to be nothing to commit and no working-directory changes.

    The "right" definition is, I think, that your tree is "clean" if there are no changes to commit and no changes between "tree staged for commit" (contents of index) and "work directory". However, it's reasonable to ask separately whether the index is clean (i.e., there is nothing staged for commit) and/or the work-tree is clean (unchanged) with respect to fill-in-the-blank, where the blank can be filled in with "the staging area" or "the HEAD commit".

    What git status tells you is both the answer to "what, if anything, is staged for commit" and "what, if anything, is different between the work-tree and the index". You have to use git diff HEAD (you may want to add --name-only or similar) to see what, if anything, is different between the work-tree and the HEAD commit unless (as is often the case) the index matches the HEAD commit.

    0 讨论(0)
提交回复
热议问题