Reputation: 1
I want to remove a commit from a git repository. Not the last one, thus a git reset
won't work.
I have this: A->B->C->D->...
And now I want to have only
A->B->D->...
Thus, I want to change the past on a way as if C
never had been existed.
How can I do that?
The possible inconsistencies with the remote repositories are a non-issue (I have full control over them). It is not a problem if the commit ids change, too.
Upvotes: 2
Views: 194
Reputation: 488463
If you have a simple, linear set of changes to copy to new commits, use git rebase -i
as in Alejandro C.'s answer. If not, do not mix git rebase -i
with git rebase -p
: it really won't work well.
Instead, first, use git replace
to construct an alternative history: make a replacement for the commit that comes after the one(s) you want removed, where the replacement's parent is the next-earlier commit you want Git to "see" when it uses replacements (which it does by default). Then, once you have the desired history, run an otherwise-no-operation git filter-branch
to copy the commits. The copied commits will, like the rest of Git, use the "pretend history" from the replacement, so they will in fact have that as their real history, and when git filter-branch
makes the branch names point to the newly copied branch tips, the replacement history will now be the actual history.
(Then, as with any git filter-branch
operation, you must clean away the refs/original/
references. It's also wise to all of this in a temporary spare repository in case you goof it up. :-) )
Upvotes: 1
Reputation: 3801
Use git rebase -i B
then squash the commit that you don't want (but whose changes you want to keep; delete it if you don't want the changes) (where B is the ref of the parent of the commit you want to delete).
You'll get something like the following
pick B Good commit
squash C Commit message I don't want, but whose changes I do want
pick D Good commit
# Rebase B..D onto B
#
# 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
Upvotes: 2