Search code examples
git

How do I reset the working tree without moving HEAD?


Given a git branch with some commits on it (C is the most recent commit):

A -> B -> C

How do I reset my workspace so that all the files are in the state they were at commit B, but HEAD is still at C?

I've looked at git-reset, but none of the options seem to help. The man page suggests that all the different modes will move HEAD:

--soft
   Does not touch the index file or the working tree at all 
   (but resets the head to <commit>, just like all modes do).

I've tried git reset HEAD~ but that moves HEAD.


Solution

  • git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>...

    git checkout with <paths> or --patch is used to restore modified or deleted paths to their original contents from the index or replace paths with the contents from a named <tree-ish> (most often a commit-ish).

    So you need to run this at root of your repository (works fine for any sub-tree or file(s) too):

    git checkout HEAD~ -- .
    

    This will result in git applying changes necessary to revert files to HEAD~ state not counting file removals, the changes will be in the index. Add --no-overlay flag to allow removal of files added since HEAD~:

    git checkout --no-overlay HEAD~ -- .
    

    From man git-checkout (git v2.44.0):

    --overlay, --no-overlay
    In the default overlay mode, git checkout never removes files from the index or the working tree. When specifying --no-overlay, files that appear in the index and working tree, but not in <tree-ish> are removed, to make them match <tree-ish> exactly.