So my history looks like this:
o---o---o---o master
\
o---o---o A
\
o B
So, to explain:
A
which was started from master
B
(with only 1 commit) which was started from A
What I want is this:
o---o---o---o master
\
o---o---o A
\
o B
What I did was:
1).
git checkout A
git rebase master
This resulted in a lot of conflicts which, after some significant time spent fixing, the following history emerged:
o---o---o---o master
\
o---o---o A
Which is exactly what I wanted.
(I don't know where B
is right now)
2).
After this I did a lot of squashes and changed the order of commits on A
, to make the history look like I want.
3).
Now, what I also want to do is:
git checkout B
git rebase A
However this doesn't seem to work and I don't know why. If I do git log
I see the commits which were there before I did step 1.
Also, I get the same huge number of conflicts which I already solved at step 1. I spent significant time doing it, don't want to do it again.
This example suggested to use --onto
, which I did:
git checkout B
git rebase --onto A
But this deletes the commit on B
entirely and makes A
and B
point to the same commit i.e. the last one on A
.
My question is: How can I effectively rebase B off A so that it looks like B started from A ? (which was actually true in the beginning).
My best guess is that I'm using --onto
wrong. Or that I should use something else (like cherry-pick
).
Short answer to How can I effectively rebase B off A so that it looks like B started from A? Assuming you want to move exactly one commit:
git rebase --onto A B~ B
If you want to move more then one commit use:
git rebase --onto A old_A B
The rest of the answer.
Your branch of B is still around (you can check it out), but its parent is still the exact commit object that A
was before.
to see a graphical representation of this I use:
git log --graph --decorate --all
to see all branches and where they are with respect to each other.
What you originally had:
o---o---o---o master
\
o---o---o A
\
o B
What you have now:
o---o---o-----------o master
\ \
o---o---o(B~) o---o---o A
\
o B
In terms of using --onto
, you need to have a starting point and an ending point.
use:
git rebase --onto [target] [rebasing stops] [rebasing head]
git rebase --onto A B~ B
And what you get:
o---o---o----------o master
\ \
o---o---o o---o---o A
(old_A) \
o B
[branch_name]~
indicates the parent commit of the branch.
The B~
is the branch that you do not want to change. (It happens to be the old A
)
Alternatively, if B was the only commit that had A as a parent, (i.e., B is the end of a chain of commits that branch off master) you could do
git checkout B
git rebase master
git checkout B~ # this is the commit before B (the A commit)
git branch -d A # remove the old A branch (it was rebased, and so is now invalid
git branch A # recreate the A branch on the commit that is based on the original A