The `branch.autoSetupMerge` works well for setting up tracking a local branch, but there is no mechanism to automatically set up a remote tracking situation. This patch adds the following configuration values: - `branch.defaultRemote`: initializes `branch.<name>.remote` if not otherwise given; - `branch.defaultPushRemote`: initializes `branch.<name>.pushRemote` (currently falls back on `remote.pushDefault` when pushing); and - `branch.defaultMerge`: initializes `branch.<name>.merge` if not otherwise given. Signed-off-by: Ben Boeckel <mathstuf@xxxxxxxxx> --- Documentation/config/branch.txt | 15 +++++++++ branch.c | 28 ++++++++++------ branch.h | 3 ++ config.c | 15 +++++++++ environment.c | 3 ++ t/t3200-branch.sh | 57 +++++++++++++++++++++++++++++++++ 6 files changed, 111 insertions(+), 10 deletions(-) diff --git a/Documentation/config/branch.txt b/Documentation/config/branch.txt index cc5f3249fc..6e9d446066 100644 --- a/Documentation/config/branch.txt +++ b/Documentation/config/branch.txt @@ -1,3 +1,18 @@ +branch.defaultRemote:: + When a new branch is created with 'git branch', 'git switch' or 'git + checkout', this value will be used to initialize the + "branch.<name>.remote" setting. + +branch.defaultPushRemote:: + When a new branch is created with 'git branch', 'git switch' or 'git + checkout', this value will be used to initialize the + "branch.<name>.pushRemote" setting. + +branch.defaultMerge:: + When a new branch is created with 'git branch', 'git switch' or 'git + checkout', this value will be used to initialize the + "branch.<name>.merge" setting. + branch.autoSetupMerge:: Tells 'git branch', 'git switch' and 'git checkout' to set up new branches so that linkgit:git-pull[1] will appropriately merge from the diff --git a/branch.c b/branch.c index 7a88a4861e..0e8ece8259 100644 --- a/branch.c +++ b/branch.c @@ -60,6 +60,9 @@ 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); + const char *actual_origin = origin ? origin : git_branch_remote; + const char *actual_push_origin = git_branch_push_remote; + const char *actual_remote = remote ? remote : git_branch_merge; if (skip_prefix(remote, "refs/heads/", &shortname) && !strcmp(local, shortname) @@ -70,12 +73,17 @@ int install_branch_config(int flag, const char *local, const char *origin, const } strbuf_addf(&key, "branch.%s.remote", local); - if (git_config_set_gently(key.buf, origin ? origin : ".") < 0) + if (git_config_set_gently(key.buf, actual_origin ? actual_origin : ".") < 0) + goto out_err; + + strbuf_reset(&key); + strbuf_addf(&key, "branch.%s.pushremote", local); + if (git_config_set_gently(key.buf, actual_push_origin) < 0) goto out_err; strbuf_reset(&key); strbuf_addf(&key, "branch.%s.merge", local); - if (git_config_set_gently(key.buf, remote) < 0) + if (git_config_set_gently(key.buf, actual_remote) < 0) goto out_err; if (rebasing) { @@ -88,27 +96,27 @@ int install_branch_config(int flag, const char *local, const char *origin, const if (flag & BRANCH_CONFIG_VERBOSE) { if (shortname) { - if (origin) + if (actual_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); + local, shortname, actual_origin); 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); } else { - if (origin) + if (actual_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); + local, actual_remote); 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); + local, actual_remote); } } @@ -119,9 +127,9 @@ int install_branch_config(int flag, const char *local, const char *origin, const error(_("Unable to write upstream branch configuration")); advise(_(tracking_advice), - origin ? origin : "", - origin ? "/" : "", - shortname ? shortname : remote); + actual_origin ? actual_origin : "", + actual_origin ? "/" : "", + shortname ? shortname : actual_remote); return -1; } diff --git a/branch.h b/branch.h index df0be61506..6ce978731d 100644 --- a/branch.h +++ b/branch.h @@ -14,6 +14,9 @@ enum branch_track { }; extern enum branch_track git_branch_track; +extern const char* git_branch_remote; +extern const char* git_branch_push_remote; +extern const char* git_branch_merge; /* Functions for acting on the information about branches. */ diff --git a/config.c b/config.c index f33abeab85..42fc510a9f 100644 --- a/config.c +++ b/config.c @@ -1599,6 +1599,21 @@ static int git_default_branch_config(const char *var, const char *value) return error(_("malformed value for %s"), var); return 0; } + if (!strcmp(var, "branch.defaultremote")) { + if (!value) + return config_error_nonbool(var); + return git_config_string(&git_branch_remote, var, value); + } + if (!strcmp(var, "branch.defaultpushremote")) { + if (!value) + return config_error_nonbool(var); + return git_config_string(&git_branch_push_remote, var, value); + } + if (!strcmp(var, "branch.defaultmerge")) { + if (!value) + return config_error_nonbool(var); + return git_config_string(&git_branch_merge, var, value); + } /* Add other config variables here and to Documentation/config.txt. */ return 0; diff --git a/environment.c b/environment.c index 2f27008424..3b4d54e7dc 100644 --- a/environment.c +++ b/environment.c @@ -60,6 +60,9 @@ int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN; char *check_roundtrip_encoding = "SHIFT-JIS"; unsigned whitespace_rule_cfg = WS_DEFAULT_RULE; enum branch_track git_branch_track = BRANCH_TRACK_REMOTE; +const char* git_branch_remote = NULL; +const char* git_branch_push_remote = NULL; +const char* git_branch_merge = NULL; enum rebase_setup_type autorebase = AUTOREBASE_NEVER; enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; #ifndef OBJECT_CREATION_MODE diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index cc4b10236e..2edfb50872 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -797,6 +797,63 @@ test_expect_success 'test tracking setup via --track but deeper' ' test "$(git config branch.my7.merge)" = refs/heads/o/o ' +test_expect_success 'test tracking setup via branch.default* and --track' ' + git config branch.autosetupmerge always && + git config branch.defaultremote local && + git config branch.defaultmerge main && + 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 other/foo my2 && + git config branch.autosetupmerge false && + test "$(git config branch.my2.remote)" = other && + ! test "$(git config branch.my2.pushremote)" = other && + test "$(git config branch.my2.merge)" = refs/heads/foo +' + +test_expect_success 'test tracking setup via branch.default* and --no-track' ' + git config branch.autosetupmerge always && + git config branch.defaultremote local && + git config branch.defaultmerge main && + 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 my2 && + git config branch.autosetupmerge false && + ! test "$(git config branch.my2.remote)" = local && + ! test "$(git config branch.my2.pushremote)" = other && + ! test "$(git config branch.my2.merge)" = refs/heads/main +' + +test_expect_success 'test tracking setup via branch.default*' ' + git config branch.autosetupmerge always && + git config branch.defaultremote local && + git config branch.defaultmerge main && + 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 my2 && + git config branch.autosetupmerge false && + test "$(git config branch.my2.remote)" = local && + ! test "$(git config branch.my2.pushremote)" = other && + test "$(git config branch.my2.merge)" = refs/heads/main +' + +test_expect_success 'test tracking setup via branch.default* with pushremote' ' + git config branch.autosetupmerge always && + git config branch.defaultremote local && + git config branch.defaultpushremote other && + git config branch.defaultmerge main && + 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 my2 && + git config branch.autosetupmerge false && + test "$(git config branch.my2.remote)" = local && + test "$(git config branch.my2.pushremote)" = other && + test "$(git config branch.my2.merge)" = refs/heads/main +' + test_expect_success 'test deleting branch deletes branch config' ' git branch -d my7 && test -z "$(git config branch.my7.remote)" && -- 2.31.1