title: Why do excluded files keep reappearing in my git sparse checkout?
body: <p>I use the <a href="http://gcc.gnu.org/wiki/GitMirror" rel="noreferrer">GCC git mirror</a> and because I only use the C and C++ front ends I use git's sparse checkout feature to exclude the hundreds of files I don't need:</p>
  
  <pre><code>$ git config core.sparseCheckout
  true
  $ cat .git/info/sparse-checkout 
  /*
  !gnattools/
  !libada/
  !libgfortran/
  !libgo/
  !libjava/
  !libobjc/
  !libquadmath/
  !gcc/ada/
  !gcc/fortran/
  !gcc/go/
  !gcc/java/
  !gcc/objc/
  !gcc/objcp/
  !gcc/testsuite/ada/
  !gcc/testsuite/gfortran.dg/
  !gcc/testsuite/gfortran.fortran-torture/
  !gcc/testsuite/gnat.dg/
  !gcc/testsuite/go.dg/
  !gcc/testsuite/go.go-torture/
  !gcc/testsuite/go.test/
  !gcc/testsuite/objc/
  !gcc/testsuite/objc.dg/
  !gcc/testsuite/obj-c++.dg/
  !gcc/testsuite/objc-obj-c++-shared/
  </code></pre>
  
  <p>This works for a while, but then now and then I notice that some of those excluded files have returned, sometimes <em>lots</em> of them:</p>
  
  <pre><code>$ ls gnattools/
  ChangeLog  configure  configure.ac  Makefile.in
  $ ls  gcc/fortran/ | wc -l 
  86
  </code></pre>
  
  <p>I'm not sure exactly when the files reappear, I do a lot of switching to different branches (both remote-tracking and local) and it's a very busy repo so there are new changes to pull frequently.</p>
  
  <p>As a relative newbie to git I don't know how to "reset" my work tree to get rid of those files again.</p>
  
  <p>As an experiment, I tried disabling sparse checkout and pulling, thinking I could enable sparseCheckout again afterwards to update the tree somehow, but that didn't work very well:</p>
  
  <pre><code>$ git config core.sparseCheckout false
  $ git config core.sparseCheckout 
  false
  $ git pull
  remote: Counting objects: 276, done.
  remote: Compressing objects: 100% (115/115), done.
  remote: Total 117 (delta 98), reused 0 (delta 0)
  Receiving objects: 100% (117/117), 64.05 KiB, done.
  Resolving deltas: 100% (98/98), completed with 64 local objects.
  From git://gcc.gnu.org/git/gcc
     7618909..0984ea0  gcc-4_5-branch -&gt; origin/gcc-4_5-branch
     b96fd63..bb95412  gcc-4_6-branch -&gt; origin/gcc-4_6-branch
     d2cdd74..2e8ef12  gcc-4_7-branch -&gt; origin/gcc-4_7-branch
     c62ec2b..fd9cb2c  master     -&gt; origin/master
     2e2713b..29daec8  melt-branch -&gt; origin/melt-branch
     c62ec2b..fd9cb2c  trunk      -&gt; origin/trunk
  Updating c62ec2b..fd9cb2c
  error: Your local changes to the following files would be overwritten by merge:
          gcc/fortran/ChangeLog
          gcc/fortran/iresolve.c
          libgfortran/ChangeLog
          libgfortran/io/intrinsics.c
  Please, commit your changes or stash them before you can merge.
  Aborting
  </code></pre>
  
  <p>So apparently I've got local modifications to files I never asked for and AFAIK have never touched!</p>
  
  <p>But <code>git status</code> doesn't show those changes:</p>
  
  <pre><code>$ git st
  # On branch master
  # Your branch is behind 'origin/master' by 9 commits, and can be fast-forwarded.
  #
  # Untracked files:
  #   (use "git add &lt;file&gt;..." to include in what will be committed)
  #
  #       libstdc++-v3/53270.txt
  #       libstdc++-v3/TODO
  </code></pre>
  
  <p>I've tried <code>git read-tree -m -u HEAD</code> but it doesn't do anything.</p>
  
  <p>So my questions are:</p>
  
  <ul>
  <li>Why do the files reappear?</li>
  <li>How do I make them disappear again?</li>
  <li>How do I prevent them coming back?</li>
  <li><p>Is this possibly related to the fact my <code>.git/info/exclude</code> file contains references to files in the directories supposed to be excluded (i.e. named with <code>!</code>) in the <code>sparse-checkout</code> file? I followed the instructions to <a href="http://gcc.gnu.org/wiki/GitMirror#Commit_on_trunk" rel="noreferrer">ignore the same files that SVN does</a></p>
  
  <p><code>$ git svn show-ignore &gt;&gt; .git/info/exclude</code></p></li>
  </ul>
  
  <p>So my <code>exclude</code> files includes paths such as</p>
  
  <pre><code># /gcc/fortran/
  /gcc/fortran/TAGS
  /gcc/fortran/TAGS.sub
  /gcc/fortran/gfortran.info*
  </code></pre>
  
  <p>Which would be below one of the directories named in the <code>sparse-checkout</code> file:</p>
  
  <pre><code>!gcc/fortran/
  </code></pre>
  
  <p>I've tried to reproduce the problem with a test repo that I clone a few copies of and edit each of them, create/switch/delete branches and merge changes between them, but it never goes wrong in my toy testcases.  The GCC repo is a bit big (over 2GB) and the time between "failures" (on the order of a week or two) too long to expect people to try to reproduce the problem exactly. I <em>haven't</em> experimented with having the same paths in <code>sparse-checkout</code> and <code>exclude</code>, as it only occurred to me today there might be a conflict there.</p>
  
  <p>I asked about this on #git on freenode a few weeks ago and IIRC was basically told "it's probably a bug, noone uses sparse checkout" but I'm hoping for a better answer ;-)</p>
  
  <p><strong>Update:</strong></p>
  
  <p>The most recent time I saw the problem actually happen (i.e. the files weren't there, then appeared after a single command) was doing a pull from the upstream origin:</p>
  
  <pre><code>   bac6f1f..6c760a6  master     -&gt; origin/master
  </code></pre>
  
  <p>and among the changes shown were these renames:</p>
  
  <pre><code> create mode 100644 libgo/go/crypto/x509/root.go
   rename libgo/go/crypto/{tls =&gt; x509}/root_darwin.go (90%)
   rename libgo/go/crypto/{tls =&gt; x509}/root_stub.go (51%)
   rename libgo/go/crypto/{tls =&gt; x509}/root_unix.go (76%)
   create mode 100644 libgo/go/crypto/x509/root_windows.go
  </code></pre>
  
  <p>Before the pull the <code>libgo</code> directory was absent, as desired.  After the pull that dir was present and these files (and no others) were under it:</p>
  
  <pre><code>$ ls libgo/go/crypto/x509/root_&lt;TAB&gt;
  root_darwin.go  root_stub.go    root_unix.go    
  </code></pre>
  
  <p>I don't know if the renamed files lost their <code>skip-worktree</code> bit, how do I check that?</p>
  
  <p>I'm pretty sure the problem doesn't always happen when there are renames, because e.g. the <code>libgfortran/ChangeLog</code> file shown in an example above is not a new file or recently renamed.</p>