Another option is git rebase -i
. It's more involved than git revert
, but you have more options also.
Let's say you have a git repo that only contains a README file:
$ cat README
This is line alpha.
Line Beta.
Line Gamma.
Then you delete line beta and commit your change:
(make changes)
$ git commit -am 'removed beta'
Now you add some more lines, committing along the way:
(make changes)
$git commit -am 'added delta'
(make changes)
$git commit -am 'added epsilon'
Now our README file and git log look like this:
$ cat README
This is line alpha.
Line Gamma.
Line Delta.
Line Epsilon.
$ git log --pretty=oneline
56ae2db58905607270434045b2a7218237d3716e added epsilon
058ec4b92fb279370f6e5b81c4aebb6250f93c6b added delta
19801b380956b60f36b4922796ea86935a75e569 removed beta
bc9057cebf05352eb5596eaf753708a14de589d2 initial commit
Now we decide that we shouldn't have removed the beta line. git rebase
to the rescue! Whenever I do any rebasing I like to use a temporary branch, since I'm changing the history.
$ git checkout -b fixingthings
Now we want to rebase everything that's happened since our initial commit. Looking at the log, that's commit bc9057c...
.
$ git rebase -i bc9057c
Now you'll see this in your editor:
pick 19801b3 removed beta
pick 058ec4b added delta
pick 56ae2db added epsilon
# Rebase bc9057c..56ae2db onto bc9057c
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
The comments at the bottom are helpful. Just delete the line with the commit you want to get rid of, save and quit and git will take care of the rest. Now your README looks like this:
$ cat README
This is line alpha.
Line Beta.
Line Gamma.
Line Delta.
Line Epsilon.
It's like magic!
If you like, you can merge back into your master branch now and delete your temporary branch.
$ git checkout master
Switched to branch "master"
$ git merge fixingthings
Auto-merging README
Merge made by recursive.
$ git branch -d fixed
Deleted branch fixingthings (was 1247141).
What git rebase
does is consider each commit as a patch and replays them in order (or not, as you tell it). That means you can have merge conflicts. If this happens to you, rebase will pause and have you resolve the conflicts. There are lots of tutorials about what to do in that situation. This one looked good to me.