Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rollback to an old commit using revert multiple times

Tags:

git

I want to rollback to a commit using git revert so I can preserve the history. Is there an easier way to do this then to run git revert for every commit hash I want to revert? Is there a quicker way to revert from a specific commit all the way up to another commit hash?

On the man page they state that you can do something like this git revert -n master~5..master~2 but when I try to do that I get this error: fatal: Cannot find 'master~5..master~2'

like image 675
David Avatar asked Jan 17 '11 17:01

David


People also ask

How do I revert multiple commits at once?

To revert multiple commits in the middle of the history, use an interactive rebase. Find the last commit's hash containing all the commits you want to remove. Start an interactive rebase session with git rebase -i <hash>. In the interactive rebase edit screen, remove the commit lines you want to remove.

How do you go back to an older commit?

Go back to the selected commit on your local environmentUse git checkout & the ID (in the same way you would checkout a branch) to go back: $ git checkout <commit-id> . Don't forget the final ' .


2 Answers

git revert should take a single commit, so that error is complaining that you're giving it a list of revisions where it's expecting one. (Update: thanks to Jefromi for pointing out that since 1.7.2, git revert actually can take multiple commits.) I'll suggest three possible courses of action below:

Creating multiple revert commits

I'm not sure if you can do this in one command, but if you know that db0bc is the last good commit (i.e. you want to revert every commit after that) and the history is linear, you could do:

for s in $(git rev-list --reverse db0bc..)
do
    git revert --no-edit $s
done

Going straight back to the old state, but still on one branch

On the other hand, if you just care about the history being there, you could always make the next commit be the state of the source tree back at the last good commit db0bc without introducing revert commits - you'll still have the history that was introduced between then and your new commit, but without lots of revert commits in between. Also this won't have trouble if the history is non-linear:

# Check that "git status" is clean:
git status

# Set the index (staging area) to be as it was at commit db0bc:
git read-tree db0bc

# Create a commit based on that index:
git commit -m "Going back to the state at commit db0bc"

# Your working tree will still be as it was when you started, so
# you'll want to reset that to the new commit:
git reset --hard

Create a new branch for the old commits

If you're the only person working on the project, or you haven't pushed master yet, or you know that resetting your master branch won't cause problems, you could take an alternative tack, and create a new branch at your current position and then reset master back, as described nicely on github's "undoing" page. In short you could do:

# Make sure you're on master:
git checkout master

# Check that "git status" is clean, since later you'll be using "git reset --hard":
git status

# Create a new branch based on your current HEAD:
git branch unwanted-work

# Reset master back to the last good commit:
git reset --hard db0bc

The diagrams on that github page make this nice and clear, I think.

like image 88
Mark Longair Avatar answered Oct 07 '22 16:10

Mark Longair


IMHO the most natural approach is to do (assuming you have a clean working copy):

git reset --hard $lastnicecommit; git merge -s ours @{1}

and then git commit --amend to add some description. (On newer versions of git git-merge already lets you specify a description.)

(@{1} is just referring to the commit your branch pointed to before the reset.)

This makes a fast-forward change and so documents the history completely. Still the changes introduced in the commits since $lastnicecommit don't introduce any changes.

like image 42
Uwe Kleine-König Avatar answered Oct 07 '22 17:10

Uwe Kleine-König