title: How to git reset --hard a subdirectory
body: <blockquote>
  <p><strong>UPDATE²</strong>: With Git 2.23 (August 2019), there's a new command <code>git restore</code> that does this, see the <a href="https://stackoverflow.com/a/15404733/946850">accepted answer</a>.</p>
  </blockquote>
  <blockquote>
  <p><strong>UPDATE</strong>: This will work more intuitively as of Git 1.8.3, see <a href="https://stackoverflow.com/a/16589534/946850">my own answer</a>.</p>
  </blockquote>
  <p>Imagine the following use case: I want to get rid of all changes in a specific subdirectory of my Git working tree, leaving all other subdirectories intact.</p>
  <ul>
  <li><p>I can do <code>git checkout .</code> , but <a href="https://stackoverflow.com/questions/15251638/git-checkout-adds-directories-excluded-by-sparse-checkout">git checkout . adds directories excluded by sparse checkout</a></p>
  </li>
  <li><p>There is <code>git reset --hard</code>, but it won't let me do it for a subdirectory:</p>
  <pre><code>  &gt; git reset --hard .
    fatal: Cannot do hard reset with paths.
  </code></pre>
  <p>Again: <a href="https://stackoverflow.com/questions/11200839/why-git-cant-do-hard-soft-resets-by-path">Why git can&#39;t do hard/soft resets by path?</a></p>
  </li>
  <li><p>I can reverse-patch the current state using <code>git diff subdir | patch -p1 -R</code>, but this is a rather weird way of doing this.</p>
  </li>
  </ul>
  <p>What is the proper Git command for this operation?</p>
  <p>The script below illustrates the problem. Insert the proper command below the <code>How to make files</code> comment -- the current command will restore the file <code>a/c/ac</code> which is supposed to be excluded by the sparse checkout. Note that I <em>do not</em> want to explicitly restore <code>a/a</code> and <code>a/b</code>, I only &quot;know&quot; <code>a</code> and want to restore everything below. <strong>EDIT</strong>: And I also don't &quot;know&quot; <code>b</code>, or which other directories reside on the same level as <code>a</code>.</p>
  <pre><code>#!/bin/sh
  
  rm -rf repo; git init repo; cd repo
  for f in a b; do
    for g in a b c; do
      mkdir -p $f/$g
      touch $f/$g/$f$g
      git add $f/$g
      git commit -m &quot;added $f/$g&quot;
    done
  done
  git config core.sparsecheckout true
  echo a/a &gt; .git/info/sparse-checkout
  echo a/b &gt;&gt; .git/info/sparse-checkout
  echo b/a &gt;&gt; .git/info/sparse-checkout
  git read-tree -m -u HEAD
  echo &quot;After read-tree:&quot;
  find * -type f
  
  rm a/a/aa
  rm a/b/ab
  echo &gt;&gt; b/a/ba
  echo &quot;After modifying:&quot;
  find * -type f
  git status
  
  # How to make files a/* reappear without changing b and without recreating a/c?
  git checkout -- a
  
  echo &quot;After checkout:&quot;
  git status
  find * -type f
  </code></pre>