diff options
author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2018-04-25 14:29:40 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-04-26 12:28:43 +0900 |
commit | 7543f6f4441a0ec76460a54f90ab8674fe424786 (patch) | |
tree | 86fdce64f8c39f3994e2c6635f2cd3070b17d434 /sequencer.h | |
parent | pull: accept --rebase=merges to recreate the branch topology (diff) | |
download | tgif-7543f6f4441a0ec76460a54f90ab8674fe424786.tar.xz |
rebase -i: introduce --rebase-merges=[no-]rebase-cousins
When running `git rebase --rebase-merges` non-interactively with an
ancestor of HEAD as <upstream> (or leaving the todo list unmodified),
we would ideally recreate the exact same commits as before the rebase.
However, if there are commits in the commit range <upstream>.. that do not
have <upstream> as direct ancestor (i.e. if `git log <upstream>..` would
show commits that are omitted by `git log --ancestry-path <upstream>..`),
this is currently not the case: we would turn them into commits that have
<upstream> as direct ancestor.
Let's illustrate that with a diagram:
C
/ \
A - B - E - F
\ /
D
Currently, after running `git rebase -i --rebase-merges B`, the new branch
structure would be (pay particular attention to the commit `D`):
--- C' --
/ \
A - B ------ E' - F'
\ /
D'
This is not really preserving the branch topology from before! The
reason is that the commit `D` does not have `B` as ancestor, and
therefore it gets rebased onto `B`.
This is unintuitive behavior. Even worse, when recreating branch
structure, most use cases would appear to want cousins *not* to be
rebased onto the new base commit. For example, Git for Windows (the
heaviest user of the Git garden shears, which served as the blueprint
for --rebase-merges) frequently merges branches from `next` early, and
these branches certainly do *not* want to be rebased. In the example
above, the desired outcome would look like this:
--- C' --
/ \
A - B ------ E' - F'
\ /
-- D' --
Let's introduce the term "cousins" for such commits ("D" in the
example), and let's not rebase them by default. For hypothetical
use cases where cousins *do* need to be rebased, `git rebase
--rebase=merges=rebase-cousins` needs to be used.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sequencer.h')
-rw-r--r-- | sequencer.h | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/sequencer.h b/sequencer.h index 6bc4da1724..d9570d92b1 100644 --- a/sequencer.h +++ b/sequencer.h @@ -60,6 +60,12 @@ int sequencer_remove_state(struct replay_opts *opts); #define TODO_LIST_SHORTEN_IDS (1U << 1) #define TODO_LIST_ABBREVIATE_CMDS (1U << 2) #define TODO_LIST_REBASE_MERGES (1U << 3) +/* + * When rebasing merges, commits that do have the base commit as ancestor + * ("cousins") are *not* rebased onto the new base by default. If those + * commits should be rebased onto the new base, this flag needs to be passed. + */ +#define TODO_LIST_REBASE_COUSINS (1U << 4) int sequencer_make_script(FILE *out, int argc, const char **argv, unsigned flags); |