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 <[email protected]>
---
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