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'
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.
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 ' .
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:
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
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
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.
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.
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