@@ -21,6 +21,8 @@ branch.autoSetupRebase::
remote-tracking branches.
When `always`, rebase will be set to true for all tracking
branches.
+ When `merges`, rebase will be set to `merges` for all tracking
+ branches.
See "branch.autoSetupMerge" for details on how to set up a
branch to track another branch.
This option defaults to never.
@@ -34,17 +34,25 @@ static int find_tracked_branch(struct remote *remote, void *priv)
return 0;
}
-static int should_setup_rebase(const char *origin)
+typedef enum {
+ REBASE_FALSE,
+ REBASE_TRUE,
+ REBASE_MERGES
+} rebase_type;
+
+static rebase_type should_setup_rebase(const char *origin)
{
switch (autorebase) {
case AUTOREBASE_NEVER:
- return 0;
+ return REBASE_FALSE;
case AUTOREBASE_LOCAL:
- return origin == NULL;
+ return origin == NULL ? REBASE_TRUE : REBASE_FALSE;
case AUTOREBASE_REMOTE:
- return origin != NULL;
+ return origin != NULL ? REBASE_TRUE : REBASE_FALSE;
case AUTOREBASE_ALWAYS:
- return 1;
+ return REBASE_TRUE;
+ case AUTOREBASE_MERGES:
+ return REBASE_MERGES;
}
return 0;
}
@@ -59,7 +67,8 @@ int install_branch_config(int flag, const char *local, const char *origin, const
{
const char *shortname = NULL;
struct strbuf key = STRBUF_INIT;
- int rebasing = should_setup_rebase(origin);
+ rebase_type rebasing = should_setup_rebase(origin);
+ struct strbuf method = STRBUF_INIT;
if (skip_prefix(remote, "refs/heads/", &shortname)
&& !strcmp(local, shortname)
@@ -78,44 +87,51 @@ int install_branch_config(int flag, const char *local, const char *origin, const
if (git_config_set_gently(key.buf, remote) < 0)
goto out_err;
- if (rebasing) {
- strbuf_reset(&key);
- strbuf_addf(&key, "branch.%s.rebase", local);
- if (git_config_set_gently(key.buf, "true") < 0)
- goto out_err;
+ strbuf_reset(&key);
+ strbuf_addf(&key, "branch.%s.rebase", local);
+ switch(rebasing) {
+ case REBASE_TRUE:
+ strbuf_addstr(&method, " by rebasing");
+ if(git_config_set_gently(key.buf, "true") < 0)
+ goto out_err;
+ break;
+ case REBASE_MERGES:
+ strbuf_addstr(&method, " by rebasing while preserving merges");
+ if (git_config_set_gently(key.buf, "merges") < 0)
+ goto out_err;
+ break;
+ default:;
}
strbuf_release(&key);
if (flag & BRANCH_CONFIG_VERBOSE) {
if (shortname) {
if (origin)
- printf_ln(rebasing ?
- _("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.") :
- _("Branch '%s' set up to track remote branch '%s' from '%s'."),
- local, shortname, origin);
+ printf_ln(
+ _("Branch '%s' set up to track remote branch '%s' from '%s'%s."),
+ local, shortname, origin, method.buf);
else
- printf_ln(rebasing ?
- _("Branch '%s' set up to track local branch '%s' by rebasing.") :
- _("Branch '%s' set up to track local branch '%s'."),
- local, shortname);
+ printf_ln(
+ _("Branch '%s' set up to track local branch '%s'%s."),
+ local, shortname, method.buf);
} else {
if (origin)
- printf_ln(rebasing ?
- _("Branch '%s' set up to track remote ref '%s' by rebasing.") :
- _("Branch '%s' set up to track remote ref '%s'."),
- local, remote);
+ printf_ln(
+ _("Branch '%s' set up to track remote ref '%s'%s."),
+ local, remote, method.buf);
else
- printf_ln(rebasing ?
- _("Branch '%s' set up to track local ref '%s' by rebasing.") :
- _("Branch '%s' set up to track local ref '%s'."),
- local, remote);
+ printf_ln(
+ _("Branch '%s' set up to track local ref '%s'%s."),
+ local, remote, method.buf);
}
}
+ strbuf_release(&method);
return 0;
out_err:
strbuf_release(&key);
+ strbuf_release(&method);
error(_("Unable to write upstream branch configuration"));
advise(_(tracking_advice),
@@ -995,7 +995,8 @@ enum rebase_setup_type {
AUTOREBASE_NEVER = 0,
AUTOREBASE_LOCAL,
AUTOREBASE_REMOTE,
- AUTOREBASE_ALWAYS
+ AUTOREBASE_ALWAYS,
+ AUTOREBASE_MERGES
};
enum push_default_type {
@@ -1443,6 +1443,8 @@ static int git_default_branch_config(const char *var, const char *value)
autorebase = AUTOREBASE_REMOTE;
else if (!strcmp(value, "always"))
autorebase = AUTOREBASE_ALWAYS;
+ else if (!strcmp(value, "merges"))
+ autorebase = AUTOREBASE_MERGES;
else
return error(_("malformed value for %s"), var);
return 0;
@@ -1222,6 +1222,51 @@ test_expect_success 'autosetuprebase always on an untracked remote branch' '
test "z$(git config branch.myr20.rebase)" = z
'
+test_expect_success 'autosetuprebase merges on a tracked local branch' '
+ git config branch.autosetuprebase merges &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/o || git fetch local) &&
+ git branch mybase21 &&
+ git branch --track myr21 mybase3 &&
+ test "$(git config branch.myr21.remote)" = . &&
+ test "$(git config branch.myr21.merge)" = refs/heads/mybase3 &&
+ test "$(git config branch.myr21.rebase)" = merges
+'
+
+test_expect_success 'autosetuprebase merges on a tracked remote branch' '
+ git config branch.autosetuprebase merges &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/main || git fetch local) &&
+ git branch --track myr22 local/main &&
+ test "$(git config branch.myr22.remote)" = local &&
+ test "$(git config branch.myr22.merge)" = refs/heads/main &&
+ test "$(git config branch.myr22.rebase)" = merges
+'
+
+test_expect_success 'autosetuprebase merges on an untracked local branch' '
+ git config branch.autosetuprebase merges &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/main || git fetch local) &&
+ git branch --no-track myr23 mybase2 &&
+ test "z$(git config branch.myr23.remote)" = z &&
+ test "z$(git config branch.myr23.merge)" = z &&
+ test "z$(git config branch.myr23.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase merges on an untracked remote branch' '
+ git config branch.autosetuprebase merges &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/main || git fetch local) &&
+ git branch --no-track myr24 local/main &&
+ test "z$(git config branch.myr24.remote)" = z &&
+ test "z$(git config branch.myr24.merge)" = z &&
+ test "z$(git config branch.myr24.rebase)" = z
+'
+
test_expect_success 'autosetuprebase always on detached HEAD' '
git config branch.autosetupmerge always &&
test_when_finished git checkout main &&
@@ -210,7 +210,7 @@ test_expect_success 'clone a void' '
test_cmp target-6/.git/config target-7/.git/config
'
-test_expect_success 'clone respects global branch.autosetuprebase' '
+test_expect_success 'clone respects global branch.autosetuprebase remote' '
(
test_config="$HOME/.gitconfig" &&
git config -f "$test_config" branch.autosetuprebase remote &&
@@ -222,6 +222,18 @@ test_expect_success 'clone respects global branch.autosetuprebase' '
)
'
+test_expect_success 'clone respects global branch.autosetuprebase merges' '
+ (
+ test_config="$HOME/.gitconfig" &&
+ git config -f "$test_config" branch.autosetuprebase merges &&
+ rm -fr dst &&
+ git clone src dst &&
+ cd dst &&
+ actual="z$(git config branch.master.rebase)" &&
+ test zmerges = $actual
+ )
+'
+
test_expect_success 'respect url-encoding of file://' '
git init x+y &&
git clone "file://$PWD/x+y" xy-url-1 &&