From 7c85a87c5449f6495fe0327cfdcd1e0940d8545a Mon Sep 17 00:00:00 2001 From: Thomas Gummerer Date: Sun, 26 Nov 2017 19:43:51 +0000 Subject: [PATCH 1/6] checkout: factor out functions to new lib file Factor the functions out, so they can be re-used from other places. In particular these functions will be re-used in builtin/worktree.c to make git worktree add dwim more. While there add some docs to the function. Signed-off-by: Thomas Gummerer Signed-off-by: Junio C Hamano --- Makefile | 1 + builtin/checkout.c | 41 +---------------------------------------- checkout.c | 43 +++++++++++++++++++++++++++++++++++++++++++ checkout.h | 13 +++++++++++++ 4 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 checkout.c create mode 100644 checkout.h diff --git a/Makefile b/Makefile index e53750ca01..a80a8fcca9 100644 --- a/Makefile +++ b/Makefile @@ -759,6 +759,7 @@ LIB_OBJS += branch.o LIB_OBJS += bulk-checkin.o LIB_OBJS += bundle.o LIB_OBJS += cache-tree.o +LIB_OBJS += checkout.o LIB_OBJS += color.o LIB_OBJS += column.o LIB_OBJS += combine-diff.o diff --git a/builtin/checkout.c b/builtin/checkout.c index 7d8bcc3833..ad8f94044c 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1,5 +1,6 @@ #include "builtin.h" #include "config.h" +#include "checkout.h" #include "lockfile.h" #include "parse-options.h" #include "refs.h" @@ -872,46 +873,6 @@ static int git_checkout_config(const char *var, const char *value, void *cb) return git_xmerge_config(var, value, NULL); } -struct tracking_name_data { - /* const */ char *src_ref; - char *dst_ref; - struct object_id *dst_oid; - int unique; -}; - -static int check_tracking_name(struct remote *remote, void *cb_data) -{ - struct tracking_name_data *cb = cb_data; - struct refspec query; - memset(&query, 0, sizeof(struct refspec)); - query.src = cb->src_ref; - if (remote_find_tracking(remote, &query) || - get_oid(query.dst, cb->dst_oid)) { - free(query.dst); - return 0; - } - if (cb->dst_ref) { - free(query.dst); - cb->unique = 0; - return 0; - } - cb->dst_ref = query.dst; - return 0; -} - -static const char *unique_tracking_name(const char *name, struct object_id *oid) -{ - struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 }; - cb_data.src_ref = xstrfmt("refs/heads/%s", name); - cb_data.dst_oid = oid; - for_each_remote(check_tracking_name, &cb_data); - free(cb_data.src_ref); - if (cb_data.unique) - return cb_data.dst_ref; - free(cb_data.dst_ref); - return NULL; -} - static int parse_branchname_arg(int argc, const char **argv, int dwim_new_local_branch_ok, struct branch_info *new, diff --git a/checkout.c b/checkout.c new file mode 100644 index 0000000000..ac42630f74 --- /dev/null +++ b/checkout.c @@ -0,0 +1,43 @@ +#include "cache.h" +#include "remote.h" +#include "checkout.h" + +struct tracking_name_data { + /* const */ char *src_ref; + char *dst_ref; + struct object_id *dst_oid; + int unique; +}; + +static int check_tracking_name(struct remote *remote, void *cb_data) +{ + struct tracking_name_data *cb = cb_data; + struct refspec query; + memset(&query, 0, sizeof(struct refspec)); + query.src = cb->src_ref; + if (remote_find_tracking(remote, &query) || + get_oid(query.dst, cb->dst_oid)) { + free(query.dst); + return 0; + } + if (cb->dst_ref) { + free(query.dst); + cb->unique = 0; + return 0; + } + cb->dst_ref = query.dst; + return 0; +} + +const char *unique_tracking_name(const char *name, struct object_id *oid) +{ + struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 }; + cb_data.src_ref = xstrfmt("refs/heads/%s", name); + cb_data.dst_oid = oid; + for_each_remote(check_tracking_name, &cb_data); + free(cb_data.src_ref); + if (cb_data.unique) + return cb_data.dst_ref; + free(cb_data.dst_ref); + return NULL; +} diff --git a/checkout.h b/checkout.h new file mode 100644 index 0000000000..9980711179 --- /dev/null +++ b/checkout.h @@ -0,0 +1,13 @@ +#ifndef CHECKOUT_H +#define CHECKOUT_H + +#include "cache.h" + +/* + * Check if the branch name uniquely matches a branch name on a remote + * tracking branch. Return the name of the remote if such a branch + * exists, NULL otherwise. + */ +extern const char *unique_tracking_name(const char *name, struct object_id *oid); + +#endif /* CHECKOUT_H */ From c4738aedc0aee085e25e20b6c32b9c4680f265d1 Mon Sep 17 00:00:00 2001 From: Thomas Gummerer Date: Sun, 26 Nov 2017 19:43:52 +0000 Subject: [PATCH 2/6] worktree: add can be created from any commit-ish Currently 'git worktree add' is documented to take an optional argument, which is checked out in the new worktree. However it is more generally possible to use a commit-ish as the optional argument, and check that out into the new worktree. Document that this is a possibility, as new users of git worktree add might find it helpful. Reported-by: Randall S. Becker Signed-off-by: Thomas Gummerer Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index b472acc356..121895209d 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -9,7 +9,7 @@ git-worktree - Manage multiple working trees SYNOPSIS -------- [verse] -'git worktree add' [-f] [--detach] [--checkout] [--lock] [-b ] [] +'git worktree add' [-f] [--detach] [--checkout] [--lock] [-b ] [] 'git worktree list' [--porcelain] 'git worktree lock' [--reason ] 'git worktree prune' [-n] [-v] [--expire ] @@ -45,14 +45,14 @@ specifying `--reason` to explain why the working tree is locked. COMMANDS -------- -add []:: +add []:: -Create `` and checkout `` into it. The new working directory +Create `` and checkout `` into it. The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. `-` may also be -specified as ``; it is synonymous with `@{-1}`. +specified as ``; it is synonymous with `@{-1}`. + -If `` is omitted and neither `-b` nor `-B` nor `--detach` used, +If `` is omitted and neither `-b` nor `-B` nor `--detach` used, then, as a convenience, a new branch based at HEAD is created automatically, as if `-b $(basename )` was specified. @@ -84,25 +84,25 @@ OPTIONS -f:: --force:: - By default, `add` refuses to create a new working tree when `` + By default, `add` refuses to create a new working tree when `` is a branch name and is already checked out by another working tree. This option overrides that safeguard. -b :: -B :: With `add`, create a new branch named `` starting at - ``, and check out `` into the new working tree. - If `` is omitted, it defaults to HEAD. + ``, and check out `` into the new working tree. + If `` is omitted, it defaults to HEAD. By default, `-b` refuses to create a new branch if it already exists. `-B` overrides this safeguard, resetting `` to - ``. + ``. --detach:: With `add`, detach HEAD in the new working tree. See "DETACHED HEAD" in linkgit:git-checkout[1]. --[no-]checkout:: - By default, `add` checks out ``, however, `--no-checkout` can + By default, `add` checks out ``, however, `--no-checkout` can be used to suppress checkout in order to make customizations, such as configuring sparse-checkout. See "Sparse checkout" in linkgit:git-read-tree[1]. From e284e892ca278e4eb1e7eabd53a000bc897c3f25 Mon Sep 17 00:00:00 2001 From: Thomas Gummerer Date: Sun, 26 Nov 2017 19:43:53 +0000 Subject: [PATCH 3/6] worktree: add --[no-]track option to the add subcommand Currently 'git worktree add' sets up tracking branches if '' is a remote tracking branch, and doesn't set them up otherwise, as is the default for 'git branch'. This may or may not be what the user wants. Allow overriding this behaviour with a --[no-]track flag that gets passed through to 'git branch'. We already respect branch.autoSetupMerge, as 'git worktree' just calls 'git branch' internally. Signed-off-by: Thomas Gummerer Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 6 ++++ builtin/worktree.c | 8 ++++++ t/t2025-worktree-add.sh | 51 ++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 121895209d..15e58b18f7 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -107,6 +107,12 @@ OPTIONS such as configuring sparse-checkout. See "Sparse checkout" in linkgit:git-read-tree[1]. +--[no-]track:: + When creating a new branch, if `` is a branch, + mark it as "upstream" from the new branch. This is the + default if `` is a remote-tracking branch. See + "--track" in linkgit:git-branch[1] for details. + --lock:: Keep the working tree locked after creation. This is the equivalent of `git worktree lock` after `git worktree add`, diff --git a/builtin/worktree.c b/builtin/worktree.c index ed043d5f1c..ea9678cac8 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -341,6 +341,7 @@ static int add(int ac, const char **av, const char *prefix) const char *new_branch_force = NULL; char *path; const char *branch; + const char *opt_track = NULL; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout even if already checked out in other worktree")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), @@ -350,6 +351,9 @@ static int add(int ac, const char **av, const char *prefix) OPT_BOOL(0, "detach", &opts.detach, N_("detach HEAD at named commit")), OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")), OPT_BOOL(0, "lock", &opts.keep_locked, N_("keep the new working tree locked")), + OPT_PASSTHRU(0, "track", &opt_track, NULL, + N_("set up tracking mode (see git-branch(1))"), + PARSE_OPT_NOARG | PARSE_OPT_OPTARG), OPT_END() }; @@ -394,9 +398,13 @@ static int add(int ac, const char **av, const char *prefix) argv_array_push(&cp.args, "--force"); argv_array_push(&cp.args, opts.new_branch); argv_array_push(&cp.args, branch); + if (opt_track) + argv_array_push(&cp.args, opt_track); if (run_command(&cp)) return -1; branch = opts.new_branch; + } else if (opt_track) { + die(_("--[no-]track can only be used if a new branch is created")); } UNLEAK(path); diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index b5c47ac602..72e8b62927 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -313,5 +313,56 @@ test_expect_success 'checkout a branch under bisect' ' test_expect_success 'rename a branch under bisect not allowed' ' test_must_fail git branch -M under-bisect bisect-with-new-name ' +# Is branch "refs/heads/$1" set to pull from "$2/$3"? +test_branch_upstream () { + printf "%s\n" "$2" "refs/heads/$3" >expect.upstream && + { + git config "branch.$1.remote" && + git config "branch.$1.merge" + } >actual.upstream && + test_cmp expect.upstream actual.upstream +} + +test_expect_success '--track sets up tracking' ' + test_when_finished rm -rf track && + git worktree add --track -b track track master && + test_branch_upstream track . master +' + +# setup remote repository $1 and repository $2 with $1 set up as +# remote. The remote has two branches, master and foo. +setup_remote_repo () { + git init $1 && + ( + cd $1 && + test_commit $1_master && + git checkout -b foo && + test_commit upstream_foo + ) && + git init $2 && + ( + cd $2 && + test_commit $2_master && + git remote add $1 ../$1 && + git config remote.$1.fetch \ + "refs/heads/*:refs/remotes/$1/*" && + git fetch --all + ) +} + +test_expect_success '--no-track avoids setting up tracking' ' + test_when_finished rm -rf repo_upstream repo_local foo && + setup_remote_repo repo_upstream repo_local && + ( + cd repo_local && + git worktree add --no-track -b foo ../foo repo_upstream/foo + ) && + ( + cd foo && + test_must_fail git config "branch.foo.remote" && + test_must_fail git config "branch.foo.merge" && + test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo + ) +' test_done From 4e8533319760c1e9255c56c2059c721286dc8dab Mon Sep 17 00:00:00 2001 From: Thomas Gummerer Date: Sun, 26 Nov 2017 19:43:54 +0000 Subject: [PATCH 4/6] worktree: make add dwim Currently 'git worktree add ', errors out when 'branch' is not a local branch. It has no additional dwim'ing features that one might expect. Make it behave more like 'git checkout ' when the branch doesn't exist locally, but a remote tracking branch uniquely matches the desired branch name, i.e. create a new branch from the remote tracking branch and set the upstream to the remote tracking branch. As 'git worktree add' currently just dies in this situation, there are no backwards compatibility worries when introducing this feature. Signed-off-by: Thomas Gummerer Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 8 ++++++++ builtin/worktree.c | 16 ++++++++++++++++ t/t2025-worktree-add.sh | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 15e58b18f7..3044d305a6 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -52,6 +52,14 @@ is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. `-` may also be specified as ``; it is synonymous with `@{-1}`. + +If is a branch name (call it `` and is not found, +and neither `-b` nor `-B` nor `--detach` are used, but there does +exist a tracking branch in exactly one remote (call it ``) +with a matching name, treat as equivalent to +------------ +$ git worktree add --track -b / +------------ ++ If `` is omitted and neither `-b` nor `-B` nor `--detach` used, then, as a convenience, a new branch based at HEAD is created automatically, as if `-b $(basename )` was specified. diff --git a/builtin/worktree.c b/builtin/worktree.c index ea9678cac8..7021d02585 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "checkout.h" #include "config.h" #include "builtin.h" #include "dir.h" @@ -390,6 +391,21 @@ static int add(int ac, const char **av, const char *prefix) opts.new_branch = xstrndup(s, n); } + if (ac == 2 && !opts.new_branch && !opts.detach) { + struct object_id oid; + struct commit *commit; + const char *remote; + + commit = lookup_commit_reference_by_name(branch); + if (!commit) { + remote = unique_tracking_name(branch, &oid); + if (remote) { + opts.new_branch = branch; + branch = remote; + } + } + } + if (opts.new_branch) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index 72e8b62927..96ebc63d04 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -365,4 +365,23 @@ test_expect_success '--no-track avoids setting up tracking' ' ) ' +test_expect_success '"add" fails' ' + test_must_fail git worktree add foo non-existent +' + +test_expect_success '"add" dwims' ' + test_when_finished rm -rf repo_upstream repo_dwim foo && + setup_remote_repo repo_upstream repo_dwim && + git init repo_dwim && + ( + cd repo_dwim && + git worktree add ../foo foo + ) && + ( + cd foo && + test_branch_upstream foo repo_upstream foo && + test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo + ) +' + test_done From 71d6682d8ca9870cbe457cf55c83402c33b41030 Mon Sep 17 00:00:00 2001 From: Thomas Gummerer Date: Wed, 29 Nov 2017 20:04:50 +0000 Subject: [PATCH 5/6] worktree: add --guess-remote flag to add subcommand Currently 'git worktree add ' creates a new branch named after the basename of the , that matches the HEAD of whichever worktree we were on when calling "git worktree add ". It's sometimes useful to have 'git worktree add behave more like the dwim machinery in 'git checkout ', i.e. check if the new branch name, derived from the basename of the , uniquely matches the branch name of a remote-tracking branch, and if so check out that branch and set the upstream to the remote-tracking branch. Add a new --guess-remote option that enables exactly that behaviour. Signed-off-by: Thomas Gummerer Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 7 +++++++ builtin/worktree.c | 10 ++++++++++ t/t2025-worktree-add.sh | 29 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 3044d305a6..2a4ea7609f 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -115,6 +115,13 @@ OPTIONS such as configuring sparse-checkout. See "Sparse checkout" in linkgit:git-read-tree[1]. +--[no-]guess-remote:: + With `worktree add `, without ``, instead + of creating a new branch from HEAD, if there exists a tracking + branch in exactly one remote matching the basename of `, + base the new branch on the remote-tracking branch, and mark + the remote-tracking branch as "upstream" from the new branch. + --[no-]track:: When creating a new branch, if `` is a branch, mark it as "upstream" from the new branch. This is the diff --git a/builtin/worktree.c b/builtin/worktree.c index 7021d02585..15cb1600ee 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -343,6 +343,7 @@ static int add(int ac, const char **av, const char *prefix) char *path; const char *branch; const char *opt_track = NULL; + int guess_remote = 0; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout even if already checked out in other worktree")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), @@ -355,6 +356,8 @@ static int add(int ac, const char **av, const char *prefix) OPT_PASSTHRU(0, "track", &opt_track, NULL, N_("set up tracking mode (see git-branch(1))"), PARSE_OPT_NOARG | PARSE_OPT_OPTARG), + OPT_BOOL(0, "guess-remote", &guess_remote, + N_("try to match the new branch name with a remote-tracking branch")), OPT_END() }; @@ -389,6 +392,13 @@ static int add(int ac, const char **av, const char *prefix) int n; const char *s = worktree_basename(path, &n); opts.new_branch = xstrndup(s, n); + if (guess_remote) { + struct object_id oid; + const char *remote = + unique_tracking_name(opts.new_branch, &oid); + if (remote) + branch = remote; + } } if (ac == 2 && !opts.new_branch && !opts.detach) { diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index 96ebc63d04..d25c774cb7 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -384,4 +384,33 @@ test_expect_success '"add" dwims' ' ) ' +test_expect_success 'git worktree add does not match remote' ' + test_when_finished rm -rf repo_a repo_b foo && + setup_remote_repo repo_a repo_b && + ( + cd repo_b && + git worktree add ../foo + ) && + ( + cd foo && + test_must_fail git config "branch.foo.remote" && + test_must_fail git config "branch.foo.merge" && + ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo + ) +' + +test_expect_success 'git worktree add --guess-remote sets up tracking' ' + test_when_finished rm -rf repo_a repo_b foo && + setup_remote_repo repo_a repo_b && + ( + cd repo_b && + git worktree add --guess-remote ../foo + ) && + ( + cd foo && + test_branch_upstream foo repo_a foo && + test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo + ) +' + test_done From e92445a73173cf21a11b8e79cb7be16485deec69 Mon Sep 17 00:00:00 2001 From: Thomas Gummerer Date: Wed, 29 Nov 2017 20:04:51 +0000 Subject: [PATCH 6/6] add worktree.guessRemote config option Some users might want to have the --guess-remote option introduced in the previous commit on by default, so they don't have to type it out every time they create a new worktree. Add a config option worktree.guessRemote that allows users to configure the default behaviour for themselves. Signed-off-by: Thomas Gummerer Signed-off-by: Junio C Hamano --- Documentation/config.txt | 10 ++++++++++ Documentation/git-worktree.txt | 3 +++ builtin/worktree.c | 14 ++++++++++++-- t/t2025-worktree-add.sh | 31 +++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 5f65fa9234..4966d90ebb 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -3425,3 +3425,13 @@ web.browser:: Specify a web browser that may be used by some commands. Currently only linkgit:git-instaweb[1] and linkgit:git-help[1] may use it. + +worktree.guessRemote:: + With `add`, if no branch argument, and neither of `-b` nor + `-B` nor `--detach` are given, the command defaults to + creating a new branch from HEAD. If `worktree.guessRemote` is + set to true, `worktree add` tries to find a remote-tracking + branch whose name uniquely matches the new branch name. If + such a branch exists, it is checked out and set as "upstream" + for the new branch. If no such match can be found, it falls + back to creating a new branch from the current HEAD. diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 2a4ea7609f..f850e8ffb6 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -121,6 +121,9 @@ OPTIONS branch in exactly one remote matching the basename of `, base the new branch on the remote-tracking branch, and mark the remote-tracking branch as "upstream" from the new branch. ++ +This can also be set up as the default behaviour by using the +`worktree.guessRemote` config option. --[no-]track:: When creating a new branch, if `` is a branch, diff --git a/builtin/worktree.c b/builtin/worktree.c index 15cb1600ee..002a569a11 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -33,8 +33,19 @@ struct add_opts { static int show_only; static int verbose; +static int guess_remote; static timestamp_t expire; +static int git_worktree_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "worktree.guessremote")) { + guess_remote = git_config_bool(var, value); + return 0; + } + + return git_default_config(var, value, cb); +} + static int prune_worktree(const char *id, struct strbuf *reason) { struct stat st; @@ -343,7 +354,6 @@ static int add(int ac, const char **av, const char *prefix) char *path; const char *branch; const char *opt_track = NULL; - int guess_remote = 0; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout even if already checked out in other worktree")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), @@ -591,7 +601,7 @@ int cmd_worktree(int ac, const char **av, const char *prefix) OPT_END() }; - git_config(git_default_config, NULL); + git_config(git_worktree_config, NULL); if (ac < 2) usage_with_options(worktree_usage, options); diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index d25c774cb7..6ce9b9c070 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -413,4 +413,35 @@ test_expect_success 'git worktree add --guess-remote sets up tracking' ' ) ' +test_expect_success 'git worktree add with worktree.guessRemote sets up tracking' ' + test_when_finished rm -rf repo_a repo_b foo && + setup_remote_repo repo_a repo_b && + ( + cd repo_b && + git config worktree.guessRemote true && + git worktree add ../foo + ) && + ( + cd foo && + test_branch_upstream foo repo_a foo && + test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo + ) +' + +test_expect_success 'git worktree --no-guess-remote option overrides config' ' + test_when_finished rm -rf repo_a repo_b foo && + setup_remote_repo repo_a repo_b && + ( + cd repo_b && + git config worktree.guessRemote true && + git worktree add --no-guess-remote ../foo + ) && + ( + cd foo && + test_must_fail git config "branch.foo.remote" && + test_must_fail git config "branch.foo.merge" && + ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo + ) +' + test_done