Reading the git rebase
and git merge-base
man documentation:
After working on the topic branch created with git checkout -b
You are correct that $fork_point
will be B3
.
I believe the intent here is to omit B3
as "not your commit".
I think the diagram the Git folks drew here is not so good. Here's how I would redraw and rewrite it without changing it too much (though I'd probably just re-letter each commit anyway).
You begin by cloning (or otherwise updating to) some (origin
) repository whose graph ends in commit B3
, and you create a topic branch and make some commit(s):
...--o---F---B3 <-- origin/master
\
G <-- topic
Over time, with additional git fetch
-es and git commit
s, your commit graph now looks like this:
...--o---F---B3--B2--B1 <-- origin/master
\
G---H---I <-- topic
But, suddenly, after another git fetch
, your own commit graph now looks like this:
o---B1' <-- origin/foo
/
...o---F---B2'-o---o---o---B <-- origin/master
\
B3--G---H---I <-- topic
That is, Git would now think that commit B3 belongs on your topic branch, when in fact, your work begins with commit G
. The people who own the repository named origin
have, in effect, declared that commit B3
is terrible and should be thrown away. (They kept a copy of B2
as B2'
on their master
, and one of B1
as B1'
on their foo
.)
If you simply git rebase
, you will copy original commit B3
to new copy B3'
(while also copying G-H-I
):
o---B1' <-- origin/foo
/
...o---F---B2'-o---o---o---B <-- origin/master
\
B3'-G'--H'--I' <-- topic
but you would instead prefer:
o---B1' <-- origin/foo
/
...o---F---B2'-o---o---o---B <-- origin/master
\
G'--H'--I <-- topic
For git rebase
to do this, you must instruct Git to locate commit B3
. Your reflog for origin/master
has all of F
, B3
, B2
, and B1
in it (under at least one reflog entry, including in this case origin/master@{1}
), while your own topic
has F
and B3
, but not B2
nor B1
, in it as well. Therefore --fork-point
chooses B3
as the newest (tip-most) shared commit, rather than F
.
The key sentence / idea in here is that the upstream repository writers intended to discard commit B3
entirely.
(How you are supposed to know this for certain is a bit of a mystery. It may not be obvious that B2'
and B1'
are copies, if the rebasing required, e.g., discarding a file that should never have been committed—and was in B1
, which is why B1
was also discarded. The fact that this file is now omitted in B2'
and B3'
makes them not-patch-equivalent, hence not obviously copies.)
(Note that your own master
also still points to B3
!)