A common scenario is if a user is working on a topic branch and they
wish to make some changes to intermediate commits or autosquashing, they
would run something such as

        git rebase -i --onto master... master

in order to preserve the merge base. This prevents unnecessary commit
churning.

Alternatively, a user wishing to test individual commits in a topic
branch without changing anything may run

        git rebase -x ./test.sh master... master

Since rebasing onto the merge base of the branch and the upstream is
such a common case, introduce the --keep-base option as a shortcut.

This allows us to rewrite the above as

        git rebase -i --keep-base master

and

        git rebase -x ./test.sh --keep-base master

respectively.

Signed-off-by: Denton Liu <liu.den...@gmail.com>
---
 builtin/rebase.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 77deebc65c..fffee89064 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -27,8 +27,8 @@
 #include "branch.h"
 
 static char const * const builtin_rebase_usage[] = {
-       N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
-               "[<upstream>] [<branch>]"),
+       N_("git rebase [-i] [options] [--exec <cmd>] "
+               "[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
        N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
                "--root [<branch>]"),
        N_("git rebase --continue | --abort | --skip | --edit-todo"),
@@ -1018,6 +1018,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
        };
        const char *branch_name;
        int ret, flags, total_argc, in_progress = 0;
+       int keep_base = 0;
        int ok_to_skip_pre_rebase = 0;
        struct strbuf msg = STRBUF_INIT;
        struct strbuf revisions = STRBUF_INIT;
@@ -1051,6 +1052,8 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
                OPT_STRING(0, "onto", &options.onto_name,
                           N_("revision"),
                           N_("rebase onto given branch instead of upstream")),
+               OPT_BOOL(0, "keep-base", &keep_base,
+                        N_("use the merge-base of upstream and branch as the 
current base")),
                OPT_BOOL(0, "no-verify", &ok_to_skip_pre_rebase,
                         N_("allow pre-rebase hook to run")),
                OPT_NEGBIT('q', "quiet", &options.flags,
@@ -1217,6 +1220,13 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
                usage_with_options(builtin_rebase_usage,
                                   builtin_rebase_options);
 
+       if (keep_base) {
+               if (options.onto_name)
+                       die(_("cannot combine '--keep-base' with '--onto'"));
+               if (options.root)
+                       die(_("cannot combine '--keep-base' with '--root'"));
+       }
+
        if (action != NO_ACTION && !in_progress)
                die(_("No rebase in progress?"));
        setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
@@ -1541,10 +1551,19 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
        }
 
        /* Make sure the branch to rebase onto is valid. */
-       if (!options.onto_name)
+       if (keep_base) {
+           strbuf_reset(&buf);
+           strbuf_addstr(&buf, options.upstream_name);
+           strbuf_addstr(&buf, "...");
+           options.onto_name = xstrdup(buf.buf);
+       } else if (!options.onto_name)
                options.onto_name = options.upstream_name;
        if (strstr(options.onto_name, "...")) {
                if (get_oid_mb(options.onto_name, &merge_base) < 0)
+                   if (keep_base)
+                       die(_("'%s': need exactly one merge base with branch"),
+                               options.upstream_name);
+                   else
                        die(_("'%s': need exactly one merge base"),
                            options.onto_name);
                options.onto = lookup_commit_or_die(&merge_base,
-- 
2.21.0.512.g57bf1b23e1

Reply via email to