rebase -r: do not (re-)generate root commits with `--root` *and* `--onto`
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Wed, 31 Jul 2019 15:18:49 +0000 (08:18 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 31 Jul 2019 19:24:07 +0000 (12:24 -0700)
When rebasing a complete commit history onto a given commit, it is
pretty obvious that the root commits should be rebased on top of said
given commit.

To test this, let's kill two birds with one stone and add a test case to
t3427-rebase-subtree.sh that not only demonstrates that this works, but
also that `git rebase -r` works with merge strategies now.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/rebase.c
sequencer.c
sequencer.h
t/t3427-rebase-subtree.sh
index 625f50c63779afb39cf78ba82dd43a155c86ecd6..ee2bc8b032a2fad1bf016314d31a655948683cd4 100644 (file)
@@ -62,7 +62,7 @@ struct rebase_options {
        const char *onto_name;
        const char *revisions;
        const char *switch_to;
-       int root;
+       int root, root_with_onto;
        struct object_id *squash_onto;
        struct commit *restrict_revision;
        int dont_finish_rebase;
@@ -374,6 +374,7 @@ static int run_rebase_interactive(struct rebase_options *opts,
        flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
        flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
        flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
+       flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0;
        flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
 
        switch (command) {
@@ -1841,7 +1842,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                        options.squash_onto = &squash_onto;
                        options.onto_name = squash_onto_name =
                                xstrdup(oid_to_hex(&squash_onto));
-               }
+               } else
+                       options.root_with_onto = 1;
+
                options.upstream_name = NULL;
                options.upstream = NULL;
                if (argc > 1)
index d228448cd8c54a1d8412d4d7d1658ae4945293cc..ca119c84e577c958a34ea69128dc9a22cc15fb56 100644 (file)
@@ -4440,6 +4440,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
 {
        int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
        int rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;
+       int root_with_onto = flags & TODO_LIST_ROOT_WITH_ONTO;
        struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
        struct strbuf label = STRBUF_INIT;
        struct commit_list *commits = NULL, **tail = &commits, *iter;
@@ -4606,7 +4607,8 @@ static int make_script_with_merges(struct pretty_print_context *pp,
 
                if (!commit)
                        strbuf_addf(out, "%s %s\n", cmd_reset,
-                                   rebase_cousins ? "onto" : "[new root]");
+                                   rebase_cousins || root_with_onto ?
+                                   "onto" : "[new root]");
                else {
                        const char *to = NULL;
 
index 0c494b83d43e2c0d71822a23dd274176fe743490..d506081d3c8656d0b290f0b39492271dbb0917f0 100644 (file)
@@ -142,6 +142,12 @@ int sequencer_remove_state(struct replay_opts *opts);
  */
 #define TODO_LIST_REBASE_COUSINS (1U << 4)
 #define TODO_LIST_APPEND_TODO_HELP (1U << 5)
+/*
+ * When generating a script that rebases merges with `--root` *and* with
+ * `--onto`, we do not want to re-generate the root commits.
+ */
+#define TODO_LIST_ROOT_WITH_ONTO (1U << 6)
+
 
 int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
                          const char **argv, unsigned flags);
index 7a37235768574db87e76b3659ca4cfd39f248563..39e348de163b722c792e1576a4ab2af62757fd79 100755 (executable)
@@ -93,4 +93,15 @@ test_expect_success 'Rebase -Xsubtree --keep-empty --onto commit' '
        verbose test "$(commit_message HEAD)" = "Empty commit"
 '
 
+test_expect_success 'Rebase -Xsubtree --keep-empty --rebase-merges --onto commit' '
+       reset_rebase &&
+       git checkout -b rebase-merges-onto to-rebase &&
+       test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --rebase-merges --onto files-master --root &&
+       : first pick results in no changes &&
+       git rebase --continue &&
+       verbose test "$(commit_message HEAD~2)" = "master4" &&
+       verbose test "$(commit_message HEAD~)" = "files_subtree/master5" &&
+       verbose test "$(commit_message HEAD)" = "Empty commit"
+'
+
 test_done