Is there a way to revert an old commit without changing the files in the working directory? I made a commit a while back, but the code that I committed wasn't ready and I want those changes to stay in my working directory as uncommitted changes so that I can continue working on them now. I looked into the revert command but that changes the working directory. I was thinking about checkout the old revision, resetting the head 1 and stashing the changes, but I already have the changes. I just want it to be as if I never made that one commit way back then, but I want the changes to the files to stay.
Try Git checkout --<file> to discard uncommitted changes to a file. Git reset --hard is for when you want to discard all uncommitted changes. Use Git reset --hard <commit id> to point the repo to a previous commit.
You can revert a specific commit to remove its changes from your branch. When you revert to a previous commit, the revert is also a commit. The original commit also remains in the repository's history.
You can do something like
git revert hash_of_your_commit
git reset HEAD^
After that you come with unstaged changes of your reverted commit.
This command usually works for me:
git revert --no-commit <commit>
The short answer is "no".
The longer answer: git revert
—like all merge-oriented operations, including git cherry-pick
, git rebase
, and of course git merge
itself—modifies a modifiable work-tree, using an index. You can commit or stash your current work, or get a second work-tree (with another clone, or using git worktree
if you have Git version 2.5 or later).
You can use git revert -n
, which allows the work-tree to be dirty, but I would not really advise that here.
The way I would handle this is to make a commit now:
$ git add ...
$ git commit -m 'temporary commit, do not push'
Then, do the desired revert as a regular commit:
$ git revert <hash>
Then use git rebase -i
to swap the order of the new revert commit and the temporary commit:
$ git rebase -i HEAD~2 # and edit the two "pick" lines
then use git reset --soft HEAD^
(or HEAD~1
, same thing) or git reset --mixed HEAD^
to un-commit the temporary commit. At this point you are in the same state (mostly) as you were before you made the temporary commit.
The (mostly) has to do with the index state: if you use git reset --soft
, all those git add
s are in effect now. If you use git reset --mixed
, none of those git add
s are in effect now.
If, before you start any of this, you already have some carefully staged state—for instance, from git add -p
—that you want to preserve, this requires doing two commits, and git stash
before the revert, with git stash apply --index
afterward, is simpler. This is because git stash
actually makes two commits, and git stash apply --index
extracts and applies those two commits, separately, to the index and work-tree. (Then git stash drop
the stash if all has gone well.)
Depending on how comfortable you are with git stash
, you can even replace the whole sequence above with git stash && git revert <hash> && git stash pop
to do it as a one-liner. Add --index
to recover separate index state. (Note that if you typo --index
and your Git version is not modern enough to detect the mistake, this will mash together the two separate commits and drop the stash. This is why I like to use git stash apply
instead of git stash pop
here.)
If anything goes wrong during this process, you will need to know exactly what happened, and what to do about it, hence the "for experts only" header above this part.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With