Stop git from silently clobbering ignorefiles (bug in git?)?

I have found a way that git will not ask you to stash but instead silently delete your files that you believed to be safe in .gitignore.
This is true even if you had the same ignore file since your initial commit.

The problem occurs when you are in a commit that has a said file removed but listed in .gitignore and then you checkout another commit where it existed:

  • What are the difference between Cherry-pick and patch apply?
  • Gradle dependency management with feature branch
  • Switch branch name on SourceTree
  • Move initial commits off master to another branch in Git
  • Howt to tell emacs VC that I want a file to be managed by git not by svn when the file is under both version systems?
  • Git clone failed while unpacking - lack of space - how to recover without a full clone?
  • git init
    mkdir ignored/
    echo stuff > ignored/file
    echo otherstuff > otherfile
    git add -A
    # Opps added my ignored folders files
    # Forgeting to rm --cache
    echo ignored/ > .gitignore ; git add .gitignore
    git commit -m 'accidentally add ignored/file'
    git status
    touch dummyfile; git add dummyfile
    # Remembered to rm --cache
    git rm --cache -rf ignored/file #This file is now vulnerable to clobber
    git commit -m 'add stuff'
    echo somechange >> ignored/file
    
    ## Wait for it..
    git checkout HEAD~
    ## somechange has been silently clobbered!!
    
    # Please paste first paragraph, observe and then past the second.
    # Note both commits have the correct ignore file and are not immune!
    

    (cd to an empty folder before pasting above code into terminal)

    Is there anyway to prevent this silent clobber?

  • How to deal with multiple remotes and branches
  • Treeview for svn commits
  • How does the github website work (architecture)?
  • SVN to Git conversion with renamed trunk
  • Where can I find the patience diff implemented?
  • How to guerilla VC with git while forced to use CVS at work?
  • One Solution collect form web for “Stop git from silently clobbering ignorefiles (bug in git?)?”

    It’s not a bug (or at least, the git developers don’t consider it to be one).

    The contents of .gitignore are not “files that should be ignored” or “path names that should not be touched”; instead, they’re “paths that don’t get automatically added, and are suppressed from being shown as untracked” (which makes .gitignore a poor name).

    Once you’ve committed a file, or even added it to the index, it’s no longer ignored, regardless of whether it is listed in a .gitignore.

    For some files, you can use git update-index --assume-unchanged or (better) git update-index --skip-worktree, but in general, if you’ve accidentally committed a file you should not have, and you want it ignored, you must “rewrite history” to take it entirely out of the repository to get good behavior. That’s not too difficult if you haven’t pushed anything and have few commits that contain the unwanted file, but much harder if you have pushed, or have many such commits.

    See also Git – Difference Between 'assume-unchanged' and 'skip-worktree'.

    [Text below added December 2016]

    Technical details

    For Git, there is a short, simple, and sweet definition of a tracked file: A file is tracked if and only if there is an entry for it in the index.

    The “assume unchanged” and “skip worktree” things are flags you can manually set or clear in the index. They are separate flags and can be set individually, although it’s not clear what it means to set both. The intent of “assume unchanged” is merely to make Git faster, by allowing it to assume that the file is not changed and hence does not need to be updated by git add, while the intent of the “skip worktree” flag is to tell Git “hands off”: don’t just assume it’s unchanged, try hard to keep it unchanged. That’s harder than it may look at first blush; for more about this, see the above linked post.

    In order to set these flags, the file must have an index entry, so it must be tracked.

    If a file is not tracked, it may or may not also be ignored. There are numerous sources for these: not just the top-level .gitignore, which contains a list (one per line) of a variant of Git’s pathspec that is limited to glob matching and negation, but also .gitignore files within each sub-directory within a repository, the file $GIT_DIR/info/exclude if it exists, and the file named by core.excludesFile if that configuration entry exists. To find whether and why a file is ignored, use git check-ignore, available since Git version 1.8.2. The -v option tells you which control file marked the file as ignored.

    Unfortunately, as in the question to which this is an answer, “ignored” has two meanings. While matching an ignore path keeps Git quiet about the file being untracked, it also makes Git feel free to clobber the file.

    Git Baby is a git and github fan, let's start git clone.