Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to 'soft revert' an old commit?

Tags:

git

git-revert

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.

like image 653
Michael Avatar asked Jun 14 '16 21:06

Michael


People also ask

How do I undo changes after last commit?

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.

Can you revert specific 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.


3 Answers

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.

like image 174
Yaroslav Melnichuk Avatar answered Oct 30 '22 07:10

Yaroslav Melnichuk


This command usually works for me: git revert --no-commit <commit>

like image 5
Berni Avatar answered Oct 30 '22 07:10

Berni


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 adds are in effect now. If you use git reset --mixed, none of those git adds are in effect now.

For experts only

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.

like image 3
torek Avatar answered Oct 30 '22 09:10

torek