summaryrefslogtreecommitdiff
path: root/sequencer.c
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2018-04-25 12:29:40 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-04-26 03:28:43 (GMT)
commit7543f6f4441a0ec76460a54f90ab8674fe424786 (patch)
tree86fdce64f8c39f3994e2c6635f2cd3070b17d434 /sequencer.c
parent1131ec98189e993dcc48043c4f8e8b0128f52055 (diff)
downloadgit-7543f6f4441a0ec76460a54f90ab8674fe424786.zip
git-7543f6f4441a0ec76460a54f90ab8674fe424786.tar.gz
git-7543f6f4441a0ec76460a54f90ab8674fe424786.tar.bz2
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.c')
-rw-r--r--sequencer.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/sequencer.c b/sequencer.c
index afa155c..e2f8394 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -3578,6 +3578,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
unsigned flags)
{
int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
+ int rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;
struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
struct strbuf label = STRBUF_INIT;
struct commit_list *commits = NULL, **tail = &commits, *iter;
@@ -3755,6 +3756,9 @@ static int make_script_with_merges(struct pretty_print_context *pp,
&commit->object.oid);
if (entry)
to = entry->string;
+ else if (!rebase_cousins)
+ to = label_oid(&commit->object.oid, NULL,
+ &state);
if (!to || !strcmp(to, "onto"))
fprintf(out, "%s onto\n", cmd_reset);