Re: [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:45:21
Possibly related (same subject, not in this thread)
- 2016-06-15 · [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase · Thomas Rast <hidden>
- 2016-06-15 · Re: [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase · Marcus Griep <hidden>
Thomas Rast [off-list ref] writes:
+RECOVERING FROM UPSTREAM REBASE +------------------------------- + +This section briefly explains the problems that arise from rebasing or +rewriting published branches, and shows how to recover.
The largest issue of "The problem" is that the person who rebases causes this problem to others, _forcing_ his downstream to recover. This intro needs to make it clear the distinction between the person who rebases, who suffers is forced to recover as the consequence.
+ o---o---o---o---o master + \ + o---o---o---o---o subsystem + \ + *---*---* topic ... +If 'subsystem' is rebased against master, the following happens: ... + o---o---o---o---o master + | \ + | o'--o'--o'--o'--o' subsystem + \ + o---o---o---o---o---*---*---* topic
Make the original upstream a bit longer in the "after" picture, explaining
that "your upstream subsystem rebased on top of its own upstream after it
gets updated", so that the part that are unchanged in two pictures are not
drawn differently like you did above.
In other words, draw it like this. It is much easier to see what's
changed and what's unchanged, if the part that hasn't changed stayed
unchanged in the picture:
o---o---o---o---o master
\
o---o---o---o---o subsystem
\
*---*---* topic
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic
+Note that while we have marked your own commits with a '*', there is +nothing that distinguishes them from the commits that previously were +on 'subsystem'. Luckily, 'git-rebase' knows to skip commits that are +textually the same as commits in the upstream. So if you say +(assuming you're on 'topic')
There is no luck involved in "git rebase" knowing how to do this -- this
is by design.
But more importantly, at this point, there is a break in the flow of
thought in this section. Step back and read what you wrote, pretending as
if you are reading the section for the first time, and notice:
* The readers were shown how the topology before and after the
subsystem's rebase looked like;
* The readers haven't been told what you are trying teach them now. Yes,
I know that you are going to tell them how to transplant their own
commits on top of updated subsystem, but they don't know that yet;
* Some of the readers may not even understand why it is a bad idea to
keep building on top of the old subsystem without rebasing on top of
the rebased subsystem at this point.
Only when the readers know that the objective is to transplant these three
top commits, they would start appreciating the difficulty (i.e. you cannot
tell the commits apart by looking at the topology alone) of rebase the
reader has to do, and the smart (i.e. if you are lucky, the rebase your
upstream did may have been a simple one) git-rebase uses to help them.
It would suffice to insert something like this before "Note that...".
To continue working from here, you need to transplant your own
commits (marked as '*') on top of the "subsystem", which is now
rebased.
But see footnote below.
+This becomes a ripple effect to anyone downstream of the first rebase: +anyone downstream from 'topic' now needs to rebase too, and so on.
This calls for a stronger wording than "needs to", perhaps "forced to".
+Things get more complicated if your upstream used `git rebase +--interactive` (or `commit --amend` or `reset --hard HEAD^`).
I do not think this section is absolutely necessary. The upstream may have done a simple rebase, which may have conflicted with the changes in its own upstream.
+To fix this, you have to manually transplant your own part of the +history to the new branch head. Looking at `git log`, you should be +able to determine that three commits on 'topic' are yours. Again +assuming you are already on 'topic', you can do +------------ + git rebase --onto subsystem HEAD~3 +------------ +to put things right.
HEAD~3 would _work_, but it often is easier to visualize this (perhaps in
your head, or in "gitk HEAD origin origin@{1}"):
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic
and say:
$ git rebase --onto subsystem subsystem@{1}
The reflog reference "1" may be larger depending on the number of times
you fetched from them without rebasing, though.
[Footnote]
You did not cover why midstream rebase _forces_ downstream to rebase. If
the leaf-level person did not know better, or did not care, starting from
this topology:
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic
the leaf person can keep building on top of the old topic, and later when
the topic is mature, have subsystem merge the result. If the rebase the
subsystem did was simple enough, the merge will be easy to resolve (both
sides modifying the same way).
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
\ /
*---*---*---*---*---*---*
The problem is that the resulting history will keep two copies of the
morally equivalent commits from the subsystem. You know that, and I know
that, but the purpose of the document is to explain it to people who do
not know it yet.