From: Jeff King <peff@peff.net>
To: Robert Buck <buck.robert.j@gmail.com>
Cc: "git@vger.kernel.org List" <git@vger.kernel.org>
Subject: Re: got myself into trouble; now what? - how to revert once you've pushed
Date: Wed, 2 Mar 2011 08:37:20 -0500 [thread overview]
Message-ID: <20110302133720.GA26989@sigill.intra.peff.net> (raw)
In-Reply-To: <AANLkTi==_zmSy4j-JwyCuYouV-J3shSObJe2y942PjCn@mail.gmail.com>
On Wed, Mar 02, 2011 at 08:10:38AM -0500, Robert Buck wrote:
> > If you can accept that history will be rewritten (which is a problem if
> > people have built on top of your bogus merge), then what you want is:
> >
> > git checkout master
> > git reset --hard $SHA1_OF_MERGE^
> >
> > and then re-push.
>
> That does not work; the central server rejects the commit. Now there
> are two other commits after mine, and the problem is getting worse.
Yeah, you would need "git push -f" to force push the rewrite of history.
But if people are building on top, then you would be removing their
history.
It's also possible that your server is configured to disallow pushing
history rewrites entirely, in which case all of the advice below will be
useless to you.
> Does anyone have a detailed guide of how to obliterate a range of
> commits and replay subsequent history on top of that?
You can do what you want with rebase. But note that this is also
rewriting history, so people building on top of what you rewrite will be
inconvenienced. If you are working a small-ish team where you can tell
everybody "stop what you're doing, let me fix this, and then we'll
proceed with working on top of my new history", then you can do
something like this.
Your history presumably looks something like this:
T1--T2--T3
/ \
...A--B--C--D--E--M--N1--N2 <-- master
where A..E are commits on master, T1..T3 are commits on the topic branch
that accidentally got merged, M is the merge commit, and N1..N2 are
commits built on top. Presumably your master points at N2. Obviously the
numbers of commits I just made up, but you should be able to identify
the sha1 id of the merge commit, "M".
Though the reflogs will provide a safety net for reversing the changes
we're about to make, it may be simpler to experiment on a new branch,
just in case we screw things up. Then when we have it looking good, we
can put our changes onto the master and topic branches.
So the first thing I would do is:
git checkout -b new-master master
to make a new branch and check it out. We can also give a name to the
bogus merge commit to make it easier to refer to:
git tag M <commit sha1 of M>
So now we want to go back to "E", and replay N1 and N2 on top of that.
Because M was a merge of topic to master, we know that E is the first
parent of M, which we can refer to as "M^1". So we can use rebase like:
git rebase --onto M^1 M
which will take all commits between the merge and the current branch tip
(which should be N1 and N2), and replay them on top of the commit just
prior to the merge. Check the result in "git log" or "gitk", or checking
it out, or whatever makes sense to you. If you're happy, you can force
it into master with:
git branch -f master new-master
I think you also said you ended up merging the bogus merge back onto the
topic branch. To undo that, probably you want to just move the topic
branch back to T3, where it was just prior to the merge. T3 is the
second parent of the merge, so you can use "M^2".
git branch -f new-topic M^2
and then check that new-topic looks good, and install it with:
git branch -f topic new-topic
Now you can push it all upstream with:
git push -f origin master topic
Everybody else on your team will then want to fetch the new history and
reset their branch pointers to match:
git fetch origin
git branch -f master origin/master
git branch -f topic origin/topic
Note that this will _throw away_ any work they had done that was not in
the rewritten history. If they had more commits that weren't pushed,
they will need to do a rebase. I think "git pull --rebase" will do what
they want, but I've never actually used it myself.
I hope that helps. Let me know if you try it and run into complications,
or if some of my assumptions don't match your situation.
-Peff
next prev parent reply other threads:[~2011-03-02 13:37 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-01 19:37 got myself into trouble; now what? - how to revert once you've pushed Robert Buck
2011-03-01 19:50 ` Jeff King
2011-03-02 13:10 ` Robert Buck
2011-03-02 13:37 ` Jeff King [this message]
2011-03-02 15:52 ` Jon Seymour
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110302133720.GA26989@sigill.intra.peff.net \
--to=peff@peff.net \
--cc=buck.robert.j@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).