Reputation: 2920
I have some commits in my repository like:
A - Added Feature A
B - Removed Feature B
C - Redesigned Feature C
D - Added Feature D
E - Added Feature D
Where E is the most recent commit I made. Now I want to get rid of the changes I made with feature C but I want to keep the changes added with D and E.
Upvotes: 39
Views: 35312
Reputation: 836
By far the best solution is to use git revert. This will make a new commit that undoes the changes in a specific SHA. This is a very safe way to remove a commit, and can be easily merge with other or remote branches.
git revert <insert bad commit hash here>
Upvotes: 2
Reputation: 19146
If you use TortoiseGit in Windows, you can right-click on the Git folder then click TortoiseGit > Show log
. You can view all of the commits done before and then check the commit you'd want to revert to.
Click on the commit and you can see the changed files below. Click right on the files to be reverted and then click revert to parent revision
.
Upvotes: 0
Reputation: 5201
git reabse -i HEAD~3
you will have the list of your 3 last commit messages
C - Redesigned Feature C
D - Added Feature D
E - Added Feature D
you just insert x git reset HEAD^ before the commit you want to undo, you want to undo commit C, so it will be like this
C - Redesigned Feature C
x git reset HEAD^
D - Added Feature D
E - Added Feature D
exit rebase console, you will see that your commit is no more in the log and their files are staged.
Upvotes: -1
Reputation: 46921
If you only want to "get rid of the changes" (as specified in your question body) as opposed to actually "removing a commit" (as specified in the title), an easy option is adding a new commit, doing exactly the opposite of what the earlier commit did.
It's not foolproof and it can result in conflicts due to changes done since, but it doesn't alter history, allows you to document the reversal and its reasons, and plays well with other working copies.
git revert
is the tool used to make such evil twins of a set of commits.
Upvotes: 14
Reputation: 40690
If you only have changes locally, you're probably best off following a rebasing answer. If you've published the changes anywhere then you don't want to rebase because that will change history, meaning that everyone else will also have to rebase or you'll get your offending commit merged back in again.
If other people have your commits, the cleanest thing to do is to revert the offending change, not to excise it altogether. Use git revert COMMIT_ID
to create a new commit that undoes the changes you applied in COMMIT_ID
.
Upvotes: 1
Reputation: 2434
Interactive rebase is your friend!
As others have said:
$ git rebase -i HEAD~5
...where -i
is the interactive flag, and HEAD~5
means include the last 5 commits in the interactive rebase.
When you get editor up as a result of issuing the above, take a look at the comment in the opened file:
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
The key bit for you is If you remove a line here THAT COMMIT WILL BE LOST.
So, delete the lines that reference the commits you want to be rid of, save and close, and git will handle the rest (you may have to fix some conflicts depending on the nature of the commit and the revert you're trying to delete).
It's important to note that if you have already pushed your code and others have pulled it, the above will not work as the commits will find their way back in there the next time someone who has your branch checked out does a push. The interactive rebase deletes the commits to the extent that there is no record of them, so the other clones do not know they have been deleted. Next time they push, they'll try and re-instate them as the local clones "see" that the origin does not have the objects (commits) that you have deleted.
Upvotes: 62
Reputation: 5201
to do that, follow these steps:
git rebase -i HEAD~3
then move commit C to be the first at the bottom, you will have
D - Added Feature D
E - Added Feature D
C - Redesigned Feature C
you save and exit, then
git reset HEAD^
this will undo commit C.
Upvotes: 2
Reputation: 6854
this is called rebasing: you want the -i
switch.
read: https://www.atlassian.com/git/tutorial/rewriting-git-history#!rebase-i
for a similar question/answer see: https://stackoverflow.com/a/2938393/2536029
Upvotes: 1