My recommendation (or, "what I would do if I were Mr Orange") is, start with git fetch
. Now I'll have this in my repo, which is what Mr Blond had after his rebase and just before he ran "git push -f".
M1 - M2 - M3
\ \
\ \
A1 - A2 A1' - A2'
The one important difference is, I'll have my local label A
pointing to rev A2, and the remote label remotes/origin/A
pointing to A2' (Mr Blond had it the other way around, local label A
pointing to A2' and remotes/origin/A
pointing to A2).
If I've been working on my copy of the branch named "A" I'll have this instead:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2'
(with my local label pointing to A3 rather than A2; or A4 or A5, etc, depending on how many changes I have applied.) Now all I have to do is rebase my A3 (and A4 if needed, etc) onto A2'. One obvious direct way:
$ git branch -a
master
* A
remotes/origin/master
remotes/origin/A
$ git branch new_A remotes/origin/A
$ git rebase -i new_A
and then drop revs A1 and A2 entirely, since the modified ones are in new_A as A1' and A2'. Or:
$ git checkout -b new_A remotes/origin/A
$ git format-patch -k --stdout A3..A | git am -3 -k
(the git am -3 -k
method is described in the git-format-patch
manual page).
These do require figuring out what I have that Mr Blond didn't before he did his rebase
, i.e., identifying A1, A2, A3, etc.
If the second approach is successful I end up with:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' - A3'
where my branch name new_A
points to A3' (my existing A
branch still points to the old A3). If I use the first approach and it succeeds, I end up with the same thing, it's just that my existing branch name A
will now point to A3' (and I have no name for the old branch with A1-A2-A3, even though it's still in my repo; finding it requires going through reflogs or similar).
(If my A3 needs modification to become A3', both the interactive rebase and the "git am" method will require work by me, of course.)
Of course it's also possible to just git merge
(as in the answer by Gary Fixler), but that will create a merge commit ("M" with no number, below) and keep revs A1 and A2 visible, giving:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' -- M
\_______________/
If you want to preserve the original A1 and A2, this is a good thing; if you want to get rid of them, it's a bad thing. So "what to do" depends on "what you want the result to be".
Edit to add: I like the format-patch method better as it leaves my old A branch name around while I make sure everything is good. Assuming it all works and is good, here's the last few steps:
$ git branch -m A old_A
$ git branch -m new_A A
and then, if old_A can be abandoned entirely:
$ git branch -D old_A
or, equivalently, start with the branch delete, then rename new_A to A.
(Edit: see also git rebase --onto
documentation, for the goal of rebasing A3, etc., onto the new_A branch.)