Reverting specific commits from git
There are two cases here:
When you have already pushed your git tree to somewhere and you don't want to change the history. In this case you will need a new commit expressing the changes you made in reverting the previous commits. You should use @mamapitufo's answer.
If you have never pushed the branch that the changes are on, and you can change the history. In this case you can completely remove the unwanted commits. This will neaten the history and means that you don't push a wrong turning to your co-workers or the public.
In the second case you should do git rebase -i
. Find a commit which comes before any of the history you want to change. This might be the hash of the commit, or the name of the branch or tag. For example, you could do
git rebase -i 23def8231
or if you started from the branch origin/dev_branch
and did the work which includes the bits to remove on your branch called dev_branch
, you could do
git rebase -i origin/dev_branch
Now, you will be sent into an editor window where you can see a list of all the commits which you are rebasing. This might be vim
- if you don't usually edit in the terminal it could be set as the default. You will probably need a quick start guide to vim and an open mind if that's the case.
Now, the easiest thing to do is to remove commits. You do this by deleting the line, or adding a #
which indicates a comment to the start of the line. (There are already some comments in the file, to explain things to you. Ignoring these or deleting them has no effect.)
When you are finished, save the file and exit the editor. The rebase happens like this: git goes back to the commit you named. It goes through the list you saved and replays each commit in that list. Then it makes the result of that process the new version of the branch you were originally on.
Important things to remember:
- If you get lost or delete too many lines, you can cancel the rebase by deleting every commit line in the file, and saving. The rebase process will end with nothing changed at all.
- It's possible to create conflicts. For example if you remove a commit which edits a file, and leave in a later commit which edits the same place. The later commit will now not apply correctly and you will have to edit by hand or in a merge tool to get the version you want.
You can also do lots of other manipulation in git rebase -i
. For example changing the order of commits, squashing several together into one, adding extra changes between commits, or changing the messages. It is very useful. The classic use case is cleaning up your local branch before you push it back to somewhere where other people will look at your changes.
You can use git revert
with the --no-commit
option. In your example:
$ git revert --no-commit b49eb8e 1d8b062
# Files that were modified in those 2 commits will be changed in your working directory
# If any of those 2 commits had changed the file 'a' then you could discard the revert for it:
$ git checkout a
$ git commit -a -m "Revert commits b49eb8e and 1d8b062"
--no-commit
option will not do auto commit, it allows you to edit and add your own commit message
Note that with unlike git reset
with git revert
all the reverted commits will still be there in the commit history