* [PATCH v4 0/4] make git worktree add dwim more [not found] <mailto:20171118224706.13810-1-t.gummerer@gmail.com> @ 2017-11-22 22:30 ` Thomas Gummerer 2017-11-22 22:30 ` [PATCH v4 1/4] checkout: factor out functions to new lib file Thomas Gummerer ` (4 more replies) 0 siblings, 5 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-22 22:30 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Thomas Gummerer The previous rounds were at https://public-inbox.org/git/20171112134305.3949-1-t.gummerer@gmail.com/, https://public-inbox.org/git/20171118181103.28354-1-t.gummerer@gmail.com/ and https://public-inbox.org/git/20171118224706.13810-1-t.gummerer@gmail.com/. Thanks Eric for the review of the previous round. The main change is that the --[no-]track flag now works generally instead of just disabling the new dwim mode. Interdiff below: diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index eedead2c4c..abc8f1f50d 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -56,22 +56,23 @@ If <branch> 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 <remote>) with a matching name, treat as equivalent to ------------ -$ git worktree add -b <branch> <path> <remote>/<branch> +$ git worktree add --track -b <branch> <path> <remote>/<branch> ------------ + If `<branch>` is omitted and neither `-b` nor `-B` nor `--detach` used, then, as a convenience, if there exists a tracking branch in exactly -one remote (call it <remote>) matching the basename of the path -(call it <branch>), treat it as equivalent to +one remote (call it `<remote>`) matching the basename of the path +(call it `<branch>`), treat it as equivalent to ------------ -$ git worktree add -b <branch> <path> <remote>/<branch> +$ git worktree add --track -b <branch> <path> <remote>/<branch> ------------ -If no tracking branch exists in exactly one remote, <branch> is +If no tracking branch exists in exactly one remote, `<branch>` is created based on HEAD, as if `-b $(basename <path>)` was specified. + To disable the behaviour of trying to match the basename of <path> to a remote, and always create a new branch from HEAD, the `--no-track` flag can be passed to `git worktree add`. + list:: List details of each worktree. The main worktree is listed first, followed by @@ -123,6 +124,12 @@ OPTIONS such as configuring sparse-checkout. See "Sparse checkout" in linkgit:git-read-tree[1]. +--[no-]track:: + With `--track` `<branch>` is set as "tracking" branch for + `<new-branch>`. This is the default if `<branch>` is a remote + tracking branch, and can be suppressed with `--no-track`. See + also linkgit:git-branch[1]. + --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 b2a6dd020c..cbcceb0385 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -342,7 +342,7 @@ static int add(int ac, const char **av, const char *prefix) const char *new_branch_force = NULL; char *path; const char *branch; - int track_dwim = 1; + const char *opt_track = NULL; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), @@ -352,7 +352,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_BOOL(0, "track", &track_dwim, N_("checkout upstream branch if there's a unique match")), + OPT_PASSTHRU(0, "track", &opt_track, NULL, + N_("set up tracking mode (see git-branch(1))"), + PARSE_OPT_NOARG | PARSE_OPT_OPTARG), OPT_END() }; @@ -387,7 +389,7 @@ 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 (track_dwim) { + if (!opt_track || strcmp(opt_track, "--no-track")) { struct object_id oid; const char *remote = unique_tracking_name(opts.new_branch, &oid); @@ -402,11 +404,12 @@ static int add(int ac, const char **av, const char *prefix) const char *remote; commit = lookup_commit_reference_by_name(branch); - if (!commit) + if (!commit) { remote = unique_tracking_name(branch, &oid); - if (!commit && remote) { - opts.new_branch = branch; - branch = remote; + if (remote) { + opts.new_branch = branch; + branch = remote; + } } } @@ -418,9 +421,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 87e233f812..6fd3da4036 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -6,16 +6,6 @@ test_description='test git worktree add' . "$TEST_DIRECTORY"/lib-rebase.sh -# 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 'setup' ' test_commit init ' @@ -323,32 +313,72 @@ 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 '"add" <path> <non-existent-branch> fails' ' - test_must_fail git worktree add foo non-existent +test_expect_success '--track sets up tracking' ' + test_when_finished rm -rf track && + git worktree add --track -b track track master && + git config "branch.track.merge" && + ( + test_branch_upstream track . master + ) ' -test_expect_success '"add" <path> <branch> dwims' ' - test_when_finished rm -rf repo_upstream && - test_when_finished rm -rf repo_dwim && - test_when_finished rm -rf foo && - git init repo_upstream && +# 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 repo_upstream && - test_commit upstream_master && + cd $1 && + test_commit $1_master && git checkout -b foo && - test_commit a_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_branch_upstream foo repo_upstream foo && + git rev-parse repo_upstream/foo >expect && + git rev-parse foo >actual && + test_cmp expect actual + ) +' + +test_expect_success '"add" <path> <non-existent-branch> fails' ' + test_must_fail git worktree add foo non-existent +' + +test_expect_success '"add" <path> <branch> 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 && - test_commit dwim_master && - git remote add repo_upstream ../repo_upstream && - git config remote.repo_upstream.fetch \ - "refs/heads/*:refs/remotes/repo_upstream/*" && - git fetch --all && - test_must_fail git worktree add -b foo ../foo foo && - test_must_fail git worktree add --detach ../foo foo && git worktree add ../foo foo ) && ( @@ -361,60 +391,32 @@ test_expect_success '"add" <path> <branch> dwims' ' ' test_expect_success 'git worktree add --no-track does not set up tracking' ' - test_when_finished rm -rf repo_a && - test_when_finished rm -rf repo_b && - test_when_finished rm -rf foo && - git init repo_a && - ( - cd repo_a && - test_commit a_master && - git checkout -b foo && - test_commit a_foo - ) && - git init repo_b && + test_when_finished rm -rf repo_a repo_b foo && + setup_remote_repo repo_a repo_b && ( cd repo_b && - test_commit b_master && - git remote add repo_a ../repo_a && - git config remote.repo_a.fetch \ - "+refs/heads/*:refs/remotes/other_a/*" && - git fetch --all && git worktree add --no-track ../foo ) && ( cd foo && ! test_branch_upstream foo repo_a foo && - git rev-parse other_a/foo >expect && + git rev-parse repo_a/foo >expect && git rev-parse foo >actual && ! test_cmp expect actual ) ' test_expect_success 'git worktree add sets up tracking' ' - test_when_finished rm -rf repo_a && - test_when_finished rm -rf repo_b && - test_when_finished rm -rf foo && - git init repo_a && - ( - cd repo_a && - test_commit a_master && - git checkout -b foo && - test_commit a_foo - ) && - git init repo_b && + test_when_finished rm -rf repo_a repo_b && + setup_remote_repo repo_a repo_b && ( cd repo_b && - test_commit b_master && - git remote add repo_a ../repo_a && - git config remote.repo_a.fetch \ - "+refs/heads/*:refs/remotes/other_a/*" && - git fetch --all && git worktree add ../foo ) && ( cd foo && test_branch_upstream foo repo_a foo && - git rev-parse other_a/foo >expect && + git rev-parse repo_a/foo >expect && git rev-parse foo >actual && test_cmp expect actual ) Thomas Gummerer (4): checkout: factor out functions to new lib file worktree: add --[no-]track option to the add subcommand worktree: make add <path> <branch> dwim worktree: make add <path> dwim Documentation/git-worktree.txt | 27 ++++++++++- Makefile | 1 + builtin/checkout.c | 41 +--------------- builtin/worktree.c | 31 ++++++++++++ checkout.c | 42 ++++++++++++++++ checkout.h | 13 +++++ t/t2025-worktree-add.sh | 108 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 221 insertions(+), 42 deletions(-) create mode 100644 checkout.c create mode 100644 checkout.h -- 2.15.0.345.gf926f18f3 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v4 1/4] checkout: factor out functions to new lib file 2017-11-22 22:30 ` [PATCH v4 0/4] make git worktree add dwim more Thomas Gummerer @ 2017-11-22 22:30 ` Thomas Gummerer 2017-11-24 6:47 ` Junio C Hamano 2017-11-22 22:30 ` [PATCH v4 2/4] worktree: add --[no-]track option to the add subcommand Thomas Gummerer ` (3 subsequent siblings) 4 siblings, 1 reply; 36+ messages in thread From: Thomas Gummerer @ 2017-11-22 22:30 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Thomas Gummerer 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 <t.gummerer@gmail.com> --- Makefile | 1 + builtin/checkout.c | 41 +---------------------------------------- checkout.c | 42 ++++++++++++++++++++++++++++++++++++++++++ checkout.h | 13 +++++++++++++ 4 files changed, 57 insertions(+), 40 deletions(-) create mode 100644 checkout.c create mode 100644 checkout.h diff --git a/Makefile b/Makefile index cd75985991..8d603c7443 100644 --- a/Makefile +++ b/Makefile @@ -757,6 +757,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 fc4f8fd2ea..9e1cfd10b3 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" @@ -874,46 +875,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..b0c744d37a --- /dev/null +++ b/checkout.c @@ -0,0 +1,42 @@ +#include "cache.h" +#include "remote.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 */ -- 2.15.0.345.gf926f18f3 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v4 1/4] checkout: factor out functions to new lib file 2017-11-22 22:30 ` [PATCH v4 1/4] checkout: factor out functions to new lib file Thomas Gummerer @ 2017-11-24 6:47 ` Junio C Hamano 0 siblings, 0 replies; 36+ messages in thread From: Junio C Hamano @ 2017-11-24 6:47 UTC (permalink / raw) To: Thomas Gummerer; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine Thomas Gummerer <t.gummerer@gmail.com> writes: > 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 <t.gummerer@gmail.com> > --- > Makefile | 1 + > builtin/checkout.c | 41 +---------------------------------------- > checkout.c | 42 ++++++++++++++++++++++++++++++++++++++++++ > checkout.h | 13 +++++++++++++ > 4 files changed, 57 insertions(+), 40 deletions(-) > create mode 100644 checkout.c > create mode 100644 checkout.h > > diff --git a/Makefile b/Makefile > index cd75985991..8d603c7443 100644 > --- a/Makefile > +++ b/Makefile > @@ -757,6 +757,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 fc4f8fd2ea..9e1cfd10b3 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" With this, and also ... > diff --git a/checkout.c b/checkout.c > new file mode 100644 > index 0000000000..b0c744d37a > --- /dev/null > +++ b/checkout.c > @@ -0,0 +1,42 @@ > +#include "cache.h" > +#include "remote.h" ... with this, I sort of expected that builtin/checkout.c no longer has to include "remote.h" but can now rely on the common helpers in this new file to perform anything remote-related operation. But it seems that it is not the case (yet). Just recording my observation for future reference, as we might also want to move report_tracking(), etc., to this new file in the future. ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v4 2/4] worktree: add --[no-]track option to the add subcommand 2017-11-22 22:30 ` [PATCH v4 0/4] make git worktree add dwim more Thomas Gummerer 2017-11-22 22:30 ` [PATCH v4 1/4] checkout: factor out functions to new lib file Thomas Gummerer @ 2017-11-22 22:30 ` Thomas Gummerer 2017-11-24 6:57 ` Junio C Hamano 2017-11-22 22:30 ` [PATCH v4 3/4] worktree: make add <path> <branch> dwim Thomas Gummerer ` (2 subsequent siblings) 4 siblings, 1 reply; 36+ messages in thread From: Thomas Gummerer @ 2017-11-22 22:30 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Thomas Gummerer Currently 'git worktree add' sets up tracking branches if '<branch>' 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 <t.gummerer@gmail.com> --- Documentation/git-worktree.txt | 6 +++++ builtin/worktree.c | 8 ++++++ t/t2025-worktree-add.sh | 55 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index b472acc356..798a642f84 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:: + With `--track` `<branch>` is set as "tracking" branch for + `<new-branch>`. This is the default if `<branch>` is a remote + tracking branch, and can be suppressed with `--no-track`. See + also linkgit:git-branch[1]. + --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 7b9307aa58..8f9446d43c 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 <branch> 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..53042ce565 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -313,5 +313,60 @@ 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 && + git config "branch.track.merge" && + ( + 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_branch_upstream foo repo_upstream foo && + git rev-parse repo_upstream/foo >expect && + git rev-parse foo >actual && + test_cmp expect actual + ) +' test_done -- 2.15.0.345.gf926f18f3 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v4 2/4] worktree: add --[no-]track option to the add subcommand 2017-11-22 22:30 ` [PATCH v4 2/4] worktree: add --[no-]track option to the add subcommand Thomas Gummerer @ 2017-11-24 6:57 ` Junio C Hamano 2017-11-25 16:58 ` Thomas Gummerer 0 siblings, 1 reply; 36+ messages in thread From: Junio C Hamano @ 2017-11-24 6:57 UTC (permalink / raw) To: Thomas Gummerer; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine Thomas Gummerer <t.gummerer@gmail.com> writes: > diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh > index b5c47ac602..53042ce565 100755 > --- a/t/t2025-worktree-add.sh > +++ b/t/t2025-worktree-add.sh > @@ -313,5 +313,60 @@ 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 > +} OK. > +test_expect_success '--track sets up tracking' ' > + test_when_finished rm -rf track && > + git worktree add --track -b track track master && > + git config "branch.track.merge" && > + ( > + test_branch_upstream track . master > + ) > +' Is this "git config" necessary, or is it a remnant of a debugging session? It is tested in the helper that branch.track.merge is set to something, and otherwise the helper would fail the same way as this standalnoe "git config" would, no? > +# 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_branch_upstream foo repo_upstream foo && It is true that this test helper must yield failure. But what you expect probably is more than that, no? For example, the test helper would fail even if branch.foo.remote is set to the upstream as long as branch.foo.merge is not set to point at their foo, but what you really want to make sure is that neither configuration variable is set. > + git rev-parse repo_upstream/foo >expect && > + git rev-parse foo >actual && > + test_cmp expect actual > + ) > +' > > test_done ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 2/4] worktree: add --[no-]track option to the add subcommand 2017-11-24 6:57 ` Junio C Hamano @ 2017-11-25 16:58 ` Thomas Gummerer 0 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-25 16:58 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine On 11/24, Junio C Hamano wrote: > Thomas Gummerer <t.gummerer@gmail.com> writes: > > > diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh > > index b5c47ac602..53042ce565 100755 > > --- a/t/t2025-worktree-add.sh > > +++ b/t/t2025-worktree-add.sh > > @@ -313,5 +313,60 @@ 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 > > +} > > OK. > > > +test_expect_success '--track sets up tracking' ' > > + test_when_finished rm -rf track && > > + git worktree add --track -b track track master && > > + git config "branch.track.merge" && > > + ( > > + test_branch_upstream track . master > > + ) > > +' > > Is this "git config" necessary, or is it a remnant of a debugging > session? It is tested in the helper that branch.track.merge is set > to something, and otherwise the helper would fail the same way as > this standalnoe "git config" would, no? It's a remnant of a debugging session, sorry. It would indeed fail in the same way, so just leaving the 'test_branch_upstream' is enough. Also looking at that, there's no need for it to be in a subshell, will fix that as well. > > +# 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_branch_upstream foo repo_upstream foo && > > It is true that this test helper must yield failure. But what you > expect probably is more than that, no? For example, the test helper > would fail even if branch.foo.remote is set to the upstream as long > as branch.foo.merge is not set to point at their foo, but what you > really want to make sure is that neither configuration variable is > set. Yeah you're right, this test is a bit too loose. Will fix that in the re-roll. Thanks! > > + git rev-parse repo_upstream/foo >expect && > > + git rev-parse foo >actual && > > + test_cmp expect actual > > + ) > > +' > > > > test_done ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v4 3/4] worktree: make add <path> <branch> dwim 2017-11-22 22:30 ` [PATCH v4 0/4] make git worktree add dwim more Thomas Gummerer 2017-11-22 22:30 ` [PATCH v4 1/4] checkout: factor out functions to new lib file Thomas Gummerer 2017-11-22 22:30 ` [PATCH v4 2/4] worktree: add --[no-]track option to the add subcommand Thomas Gummerer @ 2017-11-22 22:30 ` Thomas Gummerer 2017-11-24 6:59 ` Junio C Hamano 2017-11-22 22:30 ` [PATCH v4 4/4] worktree: make add <path> dwim Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer 4 siblings, 1 reply; 36+ messages in thread From: Thomas Gummerer @ 2017-11-22 22:30 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Thomas Gummerer Currently 'git worktree add <path> <branch>', 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 <branch>' 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 <t.gummerer@gmail.com> --- Documentation/git-worktree.txt | 7 +++++++ builtin/worktree.c | 16 ++++++++++++++++ t/t2025-worktree-add.sh | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 798a642f84..45642d3b7f 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -52,6 +52,13 @@ is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. `-` may also be specified as `<branch>`; it is synonymous with `@{-1}`. + +If <branch> 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 <remote>) with a matching name, treat as equivalent to +------------ +$ git worktree add --track -b <branch> <path> <remote>/<branch> +------------ ++ If `<branch>` 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 <path>)` was specified. diff --git a/builtin/worktree.c b/builtin/worktree.c index 8f9446d43c..e9cc3f3872 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 53042ce565..ea144938a9 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -369,4 +369,25 @@ test_expect_success '--no-track avoids setting up tracking' ' ) ' +test_expect_success '"add" <path> <non-existent-branch> fails' ' + test_must_fail git worktree add foo non-existent +' + +test_expect_success '"add" <path> <branch> 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 && + git rev-parse repo_upstream/foo >expect && + git rev-parse foo >actual && + test_cmp expect actual + ) +' + test_done -- 2.15.0.345.gf926f18f3 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v4 3/4] worktree: make add <path> <branch> dwim 2017-11-22 22:30 ` [PATCH v4 3/4] worktree: make add <path> <branch> dwim Thomas Gummerer @ 2017-11-24 6:59 ` Junio C Hamano 0 siblings, 0 replies; 36+ messages in thread From: Junio C Hamano @ 2017-11-24 6:59 UTC (permalink / raw) To: Thomas Gummerer; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine Thomas Gummerer <t.gummerer@gmail.com> writes: > Currently 'git worktree add <path> <branch>', 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 <branch>' 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 <t.gummerer@gmail.com> > --- This step makes sense and I did not spot anything controversial. ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-22 22:30 ` [PATCH v4 0/4] make git worktree add dwim more Thomas Gummerer ` (2 preceding siblings ...) 2017-11-22 22:30 ` [PATCH v4 3/4] worktree: make add <path> <branch> dwim Thomas Gummerer @ 2017-11-22 22:30 ` Thomas Gummerer 2017-11-24 7:11 ` Junio C Hamano 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer 4 siblings, 1 reply; 36+ messages in thread From: Thomas Gummerer @ 2017-11-22 22:30 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Thomas Gummerer Currently 'git worktree add <path>' creates a new branch named after the basename of the <path>, that matches the HEAD of whichever worktree we were on when calling "git worktree add <path>". Make 'git worktree add <path> behave more like the dwim machinery in 'git checkout <new-branch>', i.e. check if the new branch name 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. This is a change of behaviour compared to the current behaviour, where we create a new branch matching HEAD. However as 'git worktree' is still an experimental feature, and it's easy to notice/correct the behaviour in case it's not what the user desired it's probably okay to break existing behaviour here. In order to also satisfy users who want the current behaviour of creating a new branch from HEAD, add a '--no-track' flag, which disables the new behaviour, and keeps the old behaviour of creating a new branch from the head of the current worktree. Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> --- Documentation/git-worktree.txt | 14 ++++++++++++-- builtin/worktree.c | 7 +++++++ t/t2025-worktree-add.sh | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 45642d3b7f..abc8f1f50d 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -60,8 +60,18 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch> ------------ + If `<branch>` 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 <path>)` was specified. +then, as a convenience, if there exists a tracking branch in exactly +one remote (call it `<remote>`) matching the basename of the path +(call it `<branch>`), treat it as equivalent to +------------ +$ git worktree add --track -b <branch> <path> <remote>/<branch> +------------ +If no tracking branch exists in exactly one remote, `<branch>` is +created based on HEAD, as if `-b $(basename <path>)` was specified. ++ +To disable the behaviour of trying to match the basename of <path> to +a remote, and always create a new branch from HEAD, the `--no-track` +flag can be passed to `git worktree add`. list:: diff --git a/builtin/worktree.c b/builtin/worktree.c index e9cc3f3872..cbcceb0385 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -389,6 +389,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 (!opt_track || strcmp(opt_track, "--no-track")) { + 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 ea144938a9..6fd3da4036 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -390,4 +390,36 @@ test_expect_success '"add" <path> <branch> dwims' ' ) ' +test_expect_success 'git worktree add --no-track does not set 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 --no-track ../foo + ) && + ( + cd foo && + ! test_branch_upstream foo repo_a foo && + git rev-parse repo_a/foo >expect && + git rev-parse foo >actual && + ! test_cmp expect actual + ) +' + +test_expect_success 'git worktree add sets up tracking' ' + test_when_finished rm -rf repo_a repo_b && + setup_remote_repo repo_a repo_b && + ( + cd repo_b && + git worktree add ../foo + ) && + ( + cd foo && + test_branch_upstream foo repo_a foo && + git rev-parse repo_a/foo >expect && + git rev-parse foo >actual && + test_cmp expect actual + ) +' + test_done -- 2.15.0.345.gf926f18f3 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-22 22:30 ` [PATCH v4 4/4] worktree: make add <path> dwim Thomas Gummerer @ 2017-11-24 7:11 ` Junio C Hamano 2017-11-25 17:50 ` Thomas Gummerer 0 siblings, 1 reply; 36+ messages in thread From: Junio C Hamano @ 2017-11-24 7:11 UTC (permalink / raw) To: Thomas Gummerer; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine Thomas Gummerer <t.gummerer@gmail.com> writes: > Currently 'git worktree add <path>' creates a new branch named after the > basename of the <path>, that matches the HEAD of whichever worktree we > were on when calling "git worktree add <path>". > > Make 'git worktree add <path> behave more like the dwim machinery in > 'git checkout <new-branch>', i.e. check if the new branch name 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. > > This is a change of behaviour compared to the current behaviour, where > we create a new branch matching HEAD. However as 'git worktree' is > still an experimental feature, and it's easy to notice/correct the > behaviour in case it's not what the user desired it's probably okay to > break existing behaviour here. Is it "easy to notice"? I doubt it. Even if you assume that everybody uses bash prompt that shows the name of the branch, the user sees the same name of the branch in either mode. > In order to also satisfy users who want the current behaviour of > creating a new branch from HEAD, add a '--no-track' flag, which disables > the new behaviour, and keeps the old behaviour of creating a new branch > from the head of the current worktree. I am not sure if this is a good match for "--track/--no-track"; which branch is to be checked out (either "automatically from the unique remote-tracking branch" or "the current one") is one choice, and whether the resulting branch is marked explicitly as integrating with the remote or not is another choice within one branch of the first choice. IOW, this makes it impossible to say "create the branch based on the unique remote-tracking branch, but do not add the two branch.*.{merge,remote} variables". Also, you have several mention of "remote tracking branch" in these patches. Please consistently spell them as "remote-tracking branch" to be consistent with Documentation/glossary-content.txt and avoid a casual/careful reference to "tracking branch" if possible, unless it is quite clear to the readers that you are being loose for the sake of brevity. Some people used "tracking branch" to mean the local branch that is marked as the branch to integrate with the work on a branch at a remote that caused user confusion in the past. That is refs/remotes/origin/topic is a remote-tracking branch for the branch 'topic' that came from the 'origin' remote. when you have branch.foo.remote=origin and branch.foo.merge=refs/heads/topic, then your local branch foo is marked to integrate with the 'topic' branch at the 'origin' remote. and these two are quite different things that people in the past and over time loosely used a phrase "tracking branch" to cause confusion. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-24 7:11 ` Junio C Hamano @ 2017-11-25 17:50 ` Thomas Gummerer 2017-11-25 18:26 ` Paul Smith 2017-11-26 3:35 ` Junio C Hamano 0 siblings, 2 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-25 17:50 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine On 11/24, Junio C Hamano wrote: > Thomas Gummerer <t.gummerer@gmail.com> writes: > > > Currently 'git worktree add <path>' creates a new branch named after the > > basename of the <path>, that matches the HEAD of whichever worktree we > > were on when calling "git worktree add <path>". > > > > Make 'git worktree add <path> behave more like the dwim machinery in > > 'git checkout <new-branch>', i.e. check if the new branch name 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. > > > > This is a change of behaviour compared to the current behaviour, where > > we create a new branch matching HEAD. However as 'git worktree' is > > still an experimental feature, and it's easy to notice/correct the > > behaviour in case it's not what the user desired it's probably okay to > > break existing behaviour here. > > Is it "easy to notice"? I doubt it. Even if you assume that > everybody uses bash prompt that shows the name of the branch, the > user sees the same name of the branch in either mode. With "easy" I meant at creation time, looking at the output of 'git worktree add', which with the new version shows that the the new branch has been set up to track the remote branch, and also shows the commit HEAD now points to. This would be the output in the new version: $ git worktree add ../bla Branch 'bla' set up to track remote branch 'bla' from 'origin'. Preparing ../bla (identifier bla) HEAD is now at 4aade43 bla vs. the output without the changed behaviour: $ git worktree add ../bla Preparing ../bla (identifier bla) HEAD is now at 0f215c9 initial import Of course that assumes that it's used directly, not in scripts, and that users will actually read the output of the command when they invoke it. Maybe these are not safe assumptions to make though, and we'd rather not have this on by default then. As I mentioned previously I would prefer having this as default, but I'm happy to hide this behaviour behind a flag if we want to be more careful about introducing this. Dunno? > > In order to also satisfy users who want the current behaviour of > > creating a new branch from HEAD, add a '--no-track' flag, which disables > > the new behaviour, and keeps the old behaviour of creating a new branch > > from the head of the current worktree. > > I am not sure if this is a good match for "--track/--no-track"; > which branch is to be checked out (either "automatically from the > unique remote-tracking branch" or "the current one") is one choice, > and whether the resulting branch is marked explicitly as integrating > with the remote or not is another choice within one branch of the > first choice. IOW, this makes it impossible to say "create the branch > based on the unique remote-tracking branch, but do not add the two > branch.*.{merge,remote} variables". Hmm good point. Maybe we'll need another flag for this. Maybe --[no-]guess-remote would work, and a corresponding worktree.guessRemote config would work? That's the best I could come up with, better suggestions are definitely welcome. > Also, you have several mention of "remote tracking branch" in these > patches. Please consistently spell them as "remote-tracking branch" > to be consistent with Documentation/glossary-content.txt and avoid a > casual/careful reference to "tracking branch" if possible, unless it > is quite clear to the readers that you are being loose for the sake > of brevity. Some people used "tracking branch" to mean the local > branch that is marked as the branch to integrate with the work on > a branch at a remote that caused user confusion in the past. I must admit I wasn't aware of Documentation/glossary-content.txt and have seen "tracking branch" in other places, so I was just repeating the pattern. > That is > > refs/remotes/origin/topic is a remote-tracking branch for the > branch 'topic' that came from the 'origin' remote. > > when you have branch.foo.remote=origin and > branch.foo.merge=refs/heads/topic, then your local branch foo is > marked to integrate with the 'topic' branch at the 'origin' > remote. > > and these two are quite different things that people in the past and > over time loosely used a phrase "tracking branch" to cause confusion. Thanks for the clarification, will fix in the re-roll. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-25 17:50 ` Thomas Gummerer @ 2017-11-25 18:26 ` Paul Smith 2017-11-25 20:06 ` Thomas Gummerer 2017-11-26 3:35 ` Junio C Hamano 1 sibling, 1 reply; 36+ messages in thread From: Paul Smith @ 2017-11-25 18:26 UTC (permalink / raw) To: git On Sat, 2017-11-25 at 17:50 +0000, Thomas Gummerer wrote: > This would be the output in the new version: > > $ git worktree add ../bla > Branch 'bla' set up to track remote branch 'bla' from 'origin'. > Preparing ../bla (identifier bla) > HEAD is now at 4aade43 bla > > vs. the output without the changed behaviour: > > $ git worktree add ../bla > Preparing ../bla (identifier bla) > HEAD is now at 0f215c9 initial import > > Of course that assumes that it's used directly, not in scripts, and > that users will actually read the output of the command when they > invoke it. Maybe these are not safe assumptions to make though, and > we'd rather not have this on by default then. As I mentioned > previously I would prefer having this as default, but I'm happy to > hide this behaviour behind a flag if we want to be more careful about > introducing this. Dunno? Speaking as a simple user, I find the current behavior of Git worktree add very frustrating; I am constantly wanting to create worktrees for other peoples' branches so I can look at the code there without messing up my workspace, and it's really inconvenient to do that now. Also, the current special handling of the directory name as a putative branch name is not helpful for me because many of the branches I need to examine use "/" as their separator. I don't begrudge making that feature more "DWIM" for those that can use it, but hopefully some help is forthcoming for those who can't. For example, I need to create a local worktree for the remote rel/1.0 branch... what do I do? What I want to work is this: git worktree add ../1.0 rel/1.0 and have it create a worktree at ../1.0, then do the equivalent of "git checkout rel/1.0" which includes setting up to track the remote branch. But of course this doesn't work at all; I get: fatal: invalid reference: rel/1.0 Personally I would think it odd to have to add an extra flag to get what I would expect would be "normal" behavior (checkout). But maybe that's just me. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-25 18:26 ` Paul Smith @ 2017-11-25 20:06 ` Thomas Gummerer 2017-11-25 20:39 ` Randall S. Becker 2017-11-25 23:11 ` Paul Smith 0 siblings, 2 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-25 20:06 UTC (permalink / raw) To: Paul Smith; +Cc: git On 11/25, Paul Smith wrote: > On Sat, 2017-11-25 at 17:50 +0000, Thomas Gummerer wrote: > > This would be the output in the new version: > > > > $ git worktree add ../bla > > Branch 'bla' set up to track remote branch 'bla' from 'origin'. > > Preparing ../bla (identifier bla) > > HEAD is now at 4aade43 bla > > > > vs. the output without the changed behaviour: > > > > $ git worktree add ../bla > > Preparing ../bla (identifier bla) > > HEAD is now at 0f215c9 initial import > > > > Of course that assumes that it's used directly, not in scripts, and > > that users will actually read the output of the command when they > > invoke it. Maybe these are not safe assumptions to make though, and > > we'd rather not have this on by default then. As I mentioned > > previously I would prefer having this as default, but I'm happy to > > hide this behaviour behind a flag if we want to be more careful about > > introducing this. Dunno? > > Speaking as a simple user, I find the current behavior of Git worktree > add very frustrating; I am constantly wanting to create worktrees for > other peoples' branches so I can look at the code there without messing > up my workspace, and it's really inconvenient to do that now. > > Also, the current special handling of the directory name as a putative > branch name is not helpful for me because many of the branches I need > to examine use "/" as their separator. I don't begrudge making that > feature more "DWIM" for those that can use it, but hopefully some help > is forthcoming for those who can't. > > For example, I need to create a local worktree for the remote rel/1.0 > branch... what do I do? > > What I want to work is this: > > git worktree add ../1.0 rel/1.0 > > and have it create a worktree at ../1.0, then do the equivalent of "git > checkout rel/1.0" which includes setting up to track the remote branch. > But of course this doesn't work at all; I get: > > fatal: invalid reference: rel/1.0 > > Personally I would think it odd to have to add an extra flag to get > what I would expect would be "normal" behavior (checkout). > > But maybe that's just me. This part is getting done in 3/4, and is definitely going to work without an additional flag, so this is (hopefully) soon going to work just as you want :) This is less controversial because as you mentioned this currently doesn't work at all, so there are no backwards compatibility worries. For the other case of git worktree add ../foo however we currently document one behaviour, which I would like to change (I usually have branches without a / in that I want to look at) we currently document one behaviour, which I'd like to change. So in that case we are a bit worried about backwards compatibility, and how this will affect current users that have a certain expectation of how the command is supposed to work, hence the discussion of whether to hide the new behaviour behind a flag or not. Either way, if we do put the behaviour behind a flag, I'll also add a configuration variable, which can be set to enable the new behaviour so one doesn't have to type out the flag all the time. ^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-25 20:06 ` Thomas Gummerer @ 2017-11-25 20:39 ` Randall S. Becker 2017-11-25 21:48 ` Thomas Gummerer 2017-11-25 23:11 ` Paul Smith 1 sibling, 1 reply; 36+ messages in thread From: Randall S. Becker @ 2017-11-25 20:39 UTC (permalink / raw) To: 'Thomas Gummerer', 'Paul Smith'; +Cc: git On November 25, 2017 3:06 PM Thomas Gummerer wrote: <big snip> >however we currently document one behaviour, which I would like to change (I usually have branches >without a / in that I want to look at) we currently document one behaviour, which I'd like to change. So >in that case we are a bit worried about backwards compatibility, and how this will affect current users >that have a certain expectation of how the command is supposed to work, hence the discussion of >whether to hide the new behaviour behind a flag or not. >Either way, if we do put the behaviour behind a flag, I'll also add a configuration variable, which can >be set to enable the new behaviour so one doesn't have to type out the flag all the time. To be consistent with other commands, you could put path after -- and the ambiguity with refs containing '/' goes away, as refs before the -- would always be considered refs while after you have paths. What I don't like is the current add syntax of: git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<branch>] where the path-spec precedes branch making things a bit icky. It might be better to have an alternate syntax of: git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<branch>] git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] [<branch>] -- <path> But since we only have one path, that may be redundant. Just a thought, as -- avoids a lot of interpretation evils. While we're here, I wonder whether <branch> should be changed to <ref-spec> for more general use. Consider release identifiers using tags, and using the tag instead of branch to define commit on which the worktree is based. Cheers, Randall -- Brief whoami: NonStop&UNIX developer since approximately UNIX(421664400)/NonStop(211288444200000000) -- In my real life, I talk too much. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-25 20:39 ` Randall S. Becker @ 2017-11-25 21:48 ` Thomas Gummerer 0 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-25 21:48 UTC (permalink / raw) To: Randall S. Becker; +Cc: 'Paul Smith', git On 11/25, Randall S. Becker wrote: > On November 25, 2017 3:06 PM Thomas Gummerer wrote: > <big snip> > >however we currently document one behaviour, which I would like to change > >(I usually have branches > >without a / in that I want to look at) we currently document one behaviour, > >which I'd like to change. So > >in that case we are a bit worried about backwards compatibility, and how > >this will affect current users > >that have a certain expectation of how the command is supposed to work, > >hence the discussion of > >whether to hide the new behaviour behind a flag or not. > > >Either way, if we do put the behaviour behind a flag, I'll also add a > >configuration variable, which can > >be set to enable the new behaviour so one doesn't have to type out the flag > >all the time. > > To be consistent with other commands, you could put path after -- and the > ambiguity with refs containing '/' goes away, as refs before the -- would > always be considered refs while after you have paths. > > What I don't like is the current add syntax of: > git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] > <path> [<branch>] > > where the path-spec precedes branch making things a bit icky. It might be > better to have an alternate syntax of: > > git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] > <path> [<branch>] > git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] > [<branch>] -- <path> Hmm I don't think there is any ambiguity there, the first argument always needs to be a path, and the second one is always a commit-ish. So this way there is no disambiguation needed. I'm not convinced the alternative syntax would buy us much, at least not in the context of what this series is trying to do. > But since we only have one path, that may be redundant. Just a thought, as > -- avoids a lot of interpretation evils. While we're here, I wonder whether > <branch> should be changed to <ref-spec> for more general use. Consider > release identifiers using tags, and using the tag instead of branch to > define commit on which the worktree is based. 'git worktree add' can already take a commit-ish, it's just not documented that way. I'll add a patch updating the documentation to the series. > Cheers, > Randall > > -- Brief whoami: NonStop&UNIX developer since approximately > UNIX(421664400)/NonStop(211288444200000000) > -- In my real life, I talk too much. > > > > > ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-25 20:06 ` Thomas Gummerer 2017-11-25 20:39 ` Randall S. Becker @ 2017-11-25 23:11 ` Paul Smith 1 sibling, 0 replies; 36+ messages in thread From: Paul Smith @ 2017-11-25 23:11 UTC (permalink / raw) To: Thomas Gummerer; +Cc: git On Sat, 2017-11-25 at 20:06 +0000, Thomas Gummerer wrote: > This part is getting done in 3/4, and is definitely going to work > without an additional flag, so this is (hopefully) soon going to work > just as you want :) Yay! Thanks! ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-25 17:50 ` Thomas Gummerer 2017-11-25 18:26 ` Paul Smith @ 2017-11-26 3:35 ` Junio C Hamano 2017-11-26 11:37 ` Thomas Gummerer 1 sibling, 1 reply; 36+ messages in thread From: Junio C Hamano @ 2017-11-26 3:35 UTC (permalink / raw) To: Thomas Gummerer; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine Thomas Gummerer <t.gummerer@gmail.com> writes: > Of course that assumes that it's used directly, not in scripts, and > that users will actually read the output of the command when they > invoke it. Maybe these are not safe assumptions to make though, and > we'd rather not have this on by default then. None of these is a safe assumption to make. With a transition plan, we could change the default eventually, but if this feature is already used by real users, the proposed change without any transition plan will hurt them and make them hate us, I am afraid. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 4/4] worktree: make add <path> dwim 2017-11-26 3:35 ` Junio C Hamano @ 2017-11-26 11:37 ` Thomas Gummerer 0 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 11:37 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine On 11/26, Junio C Hamano wrote: > Thomas Gummerer <t.gummerer@gmail.com> writes: > > > Of course that assumes that it's used directly, not in scripts, and > > that users will actually read the output of the command when they > > invoke it. Maybe these are not safe assumptions to make though, and > > we'd rather not have this on by default then. > > None of these is a safe assumption to make. With a transition plan, > we could change the default eventually, but if this feature is already > used by real users, the proposed change without any transition plan > will hurt them and make them hate us, I am afraid. Fair enough, I definitely wouldn't want users to hate us. I guess I'll add this to the list of things that I'd like to change when git 3.0 comes along. How about once we make the decision when git 3.0 happens, adding a warning: warning: The current behaviour of creating a branch from HEAD when no <branch> is given will change in git 3.0, to try and match the new branch name to a remote-tracking branch. To get rid of this warning in the meantime, set git.guessRemote to true or false, depending on whether you'd like to enable the new behaviour now, or would like to keep the existing behaviour. (see also --guess-remote in man git-worktree) or something along the lines, and once we decide to release git 3.0 we flip the default? The warning would be displayed whenever the new behaviour would be invoked, but no config option or flag is set. Either way I'm going to add a flag and a config option to hide this behaviour behind for now. Thanks! ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v5 0/6] make git worktree add dwim more 2017-11-22 22:30 ` [PATCH v4 0/4] make git worktree add dwim more Thomas Gummerer ` (3 preceding siblings ...) 2017-11-22 22:30 ` [PATCH v4 4/4] worktree: make add <path> dwim Thomas Gummerer @ 2017-11-26 19:43 ` Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 1/6] checkout: factor out functions to new lib file Thomas Gummerer ` (6 more replies) 4 siblings, 7 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 19:43 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer The previous rounds can be found at https://public-inbox.org/git/20171112134305.3949-1-t.gummerer@gmail.com/, https://public-inbox.org/git/20171118181103.28354-1-t.gummerer@gmail.com/, https://public-inbox.org/git/20171118224706.13810-1-t.gummerer@gmail.com/ and https://public-inbox.org/git/20171122223020.2780-1-t.gummerer@gmail.com/. Thanks Junio for the review of the previous round and Randall for the suggestion of documenting that git worktree add can take a commit-ish, not just a branch. The main changes in this round are hiding the new behaviour for 'git worktree <path>' behind a flag, and adding a config option to turn the new behaviour on by default. It's also no longer relying on the --[no]-track flag, but using a new --[no-]guess-remote flag instead. Interdiff between this and the previous round below: 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 abc8f1f50d..fd841886ef 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 <new-branch>] <path> [<branch>] +'git worktree add' [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>] 'git worktree list' [--porcelain] 'git worktree lock' [--reason <string>] <worktree> 'git worktree prune' [-n] [-v] [--expire <expire>] @@ -45,33 +45,24 @@ specifying `--reason` to explain why the working tree is locked. COMMANDS -------- -add <path> [<branch>]:: +add <path> [<commit-ish>]:: -Create `<path>` and checkout `<branch>` into it. The new working directory +Create `<path>` and checkout `<commit-ish>` 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 `<branch>`; it is synonymous with `@{-1}`. +specified as `<commit-ish>`; it is synonymous with `@{-1}`. + -If <branch> 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 <remote>) with a matching name, treat as equivalent to +If <commit-ish> is a branch name (call it `<branch>` 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 `<remote>`) +with a matching name, treat as equivalent to ------------ $ git worktree add --track -b <branch> <path> <remote>/<branch> ------------ + -If `<branch>` is omitted and neither `-b` nor `-B` nor `--detach` used, -then, as a convenience, if there exists a tracking branch in exactly -one remote (call it `<remote>`) matching the basename of the path -(call it `<branch>`), treat it as equivalent to ------------- -$ git worktree add --track -b <branch> <path> <remote>/<branch> ------------- -If no tracking branch exists in exactly one remote, `<branch>` is -created based on HEAD, as if `-b $(basename <path>)` was specified. -+ -To disable the behaviour of trying to match the basename of <path> to -a remote, and always create a new branch from HEAD, the `--no-track` -flag can be passed to `git worktree add`. +If `<commit-ish>` 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 <path>)` was specified. list:: @@ -101,34 +92,44 @@ OPTIONS -f:: --force:: - By default, `add` refuses to create a new working tree when `<branch>` + By default, `add` refuses to create a new working tree when `<commit-ish>` is a branch name and is already checked out by another working tree. This option overrides that safeguard. -b <new-branch>:: -B <new-branch>:: With `add`, create a new branch named `<new-branch>` starting at - `<branch>`, and check out `<new-branch>` into the new working tree. - If `<branch>` is omitted, it defaults to HEAD. + `<commit-ish>`, and check out `<new-branch>` into the new working tree. + If `<commit-ish>` is omitted, it defaults to HEAD. By default, `-b` refuses to create a new branch if it already exists. `-B` overrides this safeguard, resetting `<new-branch>` to - `<branch>`. + `<commit-ish>`. --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 `<branch>`, however, `--no-checkout` can + By default, `add` checks out `<commit-ish>`, 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]. +--[no-]guess-remote:: + With `add`, instead of creating a new branch from HEAD when + `<commit-ish>` is not given, if there exists a tracking branch + in exactly one remote matching the basename of the path, 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:: - With `--track` `<branch>` is set as "tracking" branch for - `<new-branch>`. This is the default if `<branch>` is a remote - tracking branch, and can be suppressed with `--no-track`. See - also linkgit:git-branch[1]. + When creating a new branch, if `<commit-ish>` is a branch, + mark it as "upstream" from the new branch. This is the + default if `<commit-ish>` 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 diff --git a/builtin/worktree.c b/builtin/worktree.c index 83c73ecb0d..426aea8761 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 0; +} + static int prune_worktree(const char *id, struct strbuf *reason) { struct stat st; @@ -355,9 +366,13 @@ 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() }; + git_config(git_worktree_config, NULL); + memset(&opts, 0, sizeof(opts)); opts.checkout = 1; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); @@ -389,7 +404,7 @@ 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 (!opt_track || strcmp(opt_track, "--no-track")) { + if (guess_remote) { struct object_id oid; const char *remote = unique_tracking_name(opts.new_branch, &oid); diff --git a/checkout.c b/checkout.c index b0c744d37a..ac42630f74 100644 --- a/checkout.c +++ b/checkout.c @@ -1,5 +1,6 @@ #include "cache.h" #include "remote.h" +#include "checkout.h" struct tracking_name_data { /* const */ char *src_ref; diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index 6fd3da4036..6ce9b9c070 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -326,10 +326,7 @@ test_branch_upstream () { test_expect_success '--track sets up tracking' ' test_when_finished rm -rf track && git worktree add --track -b track track master && - git config "branch.track.merge" && - ( - test_branch_upstream track . master - ) + test_branch_upstream track . master ' # setup remote repository $1 and repository $2 with $1 set up as @@ -362,10 +359,9 @@ test_expect_success '--no-track avoids setting up tracking' ' ) && ( cd foo && - ! test_branch_upstream foo repo_upstream foo && - git rev-parse repo_upstream/foo >expect && - git rev-parse foo >actual && - test_cmp expect actual + 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 ) ' @@ -384,41 +380,67 @@ test_expect_success '"add" <path> <branch> dwims' ' ( cd foo && test_branch_upstream foo repo_upstream foo && - git rev-parse repo_upstream/foo >expect && - git rev-parse foo >actual && - test_cmp expect actual + test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo ) ' -test_expect_success 'git worktree add --no-track does not set up tracking' ' +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 --no-track ../foo + git worktree add ../foo ) && ( cd foo && - ! test_branch_upstream foo repo_a foo && - git rev-parse repo_a/foo >expect && - git rev-parse foo >actual && - ! test_cmp expect actual + 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 sets up tracking' ' - test_when_finished rm -rf repo_a repo_b && +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_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 && - git rev-parse repo_a/foo >expect && - git rev-parse foo >actual && - test_cmp expect actual + 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 ) ' Thomas Gummerer (6): checkout: factor out functions to new lib file worktree: add can be created from any commit-ish worktree: add --[no-]track option to the add subcommand worktree: make add <path> <branch> dwim worktree: add --guess-remote flag to add subcommand add worktree.guessRemote config option Documentation/config.txt | 10 ++++ Documentation/git-worktree.txt | 44 ++++++++++---- Makefile | 1 + builtin/checkout.c | 41 +------------ builtin/worktree.c | 46 +++++++++++++++ checkout.c | 43 ++++++++++++++ checkout.h | 13 +++++ t/t2025-worktree-add.sh | 130 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 278 insertions(+), 50 deletions(-) create mode 100644 checkout.c create mode 100644 checkout.h -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v5 1/6] checkout: factor out functions to new lib file 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer @ 2017-11-26 19:43 ` Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 2/6] worktree: add can be created from any commit-ish Thomas Gummerer ` (5 subsequent siblings) 6 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 19:43 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer 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 <t.gummerer@gmail.com> --- 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 */ -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v5 2/6] worktree: add can be created from any commit-ish 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 1/6] checkout: factor out functions to new lib file Thomas Gummerer @ 2017-11-26 19:43 ` Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 3/6] worktree: add --[no-]track option to the add subcommand Thomas Gummerer ` (4 subsequent siblings) 6 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 19:43 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add' is documented to take an optional <branch> 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 <rsbecker@nexbridge.com> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> --- 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 <new-branch>] <path> [<branch>] +'git worktree add' [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>] 'git worktree list' [--porcelain] 'git worktree lock' [--reason <string>] <worktree> 'git worktree prune' [-n] [-v] [--expire <expire>] @@ -45,14 +45,14 @@ specifying `--reason` to explain why the working tree is locked. COMMANDS -------- -add <path> [<branch>]:: +add <path> [<commit-ish>]:: -Create `<path>` and checkout `<branch>` into it. The new working directory +Create `<path>` and checkout `<commit-ish>` 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 `<branch>`; it is synonymous with `@{-1}`. +specified as `<commit-ish>`; it is synonymous with `@{-1}`. + -If `<branch>` is omitted and neither `-b` nor `-B` nor `--detach` used, +If `<commit-ish>` 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 <path>)` was specified. @@ -84,25 +84,25 @@ OPTIONS -f:: --force:: - By default, `add` refuses to create a new working tree when `<branch>` + By default, `add` refuses to create a new working tree when `<commit-ish>` is a branch name and is already checked out by another working tree. This option overrides that safeguard. -b <new-branch>:: -B <new-branch>:: With `add`, create a new branch named `<new-branch>` starting at - `<branch>`, and check out `<new-branch>` into the new working tree. - If `<branch>` is omitted, it defaults to HEAD. + `<commit-ish>`, and check out `<new-branch>` into the new working tree. + If `<commit-ish>` is omitted, it defaults to HEAD. By default, `-b` refuses to create a new branch if it already exists. `-B` overrides this safeguard, resetting `<new-branch>` to - `<branch>`. + `<commit-ish>`. --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 `<branch>`, however, `--no-checkout` can + By default, `add` checks out `<commit-ish>`, 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]. -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v5 3/6] worktree: add --[no-]track option to the add subcommand 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 1/6] checkout: factor out functions to new lib file Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 2/6] worktree: add can be created from any commit-ish Thomas Gummerer @ 2017-11-26 19:43 ` Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 4/6] worktree: make add <path> <branch> dwim Thomas Gummerer ` (3 subsequent siblings) 6 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 19:43 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add' sets up tracking branches if '<branch>' 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 <t.gummerer@gmail.com> --- 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 `<commit-ish>` is a branch, + mark it as "upstream" from the new branch. This is the + default if `<commit-ish>` 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 <branch> 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v5 4/6] worktree: make add <path> <branch> dwim 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer ` (2 preceding siblings ...) 2017-11-26 19:43 ` [PATCH v5 3/6] worktree: add --[no-]track option to the add subcommand Thomas Gummerer @ 2017-11-26 19:43 ` Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 5/6] worktree: add --guess-remote flag to add subcommand Thomas Gummerer ` (2 subsequent siblings) 6 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 19:43 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add <path> <branch>', 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 <branch>' 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 <t.gummerer@gmail.com> --- 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 `<commit-ish>`; it is synonymous with `@{-1}`. + +If <commit-ish> is a branch name (call it `<branch>` 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 `<remote>`) +with a matching name, treat as equivalent to +------------ +$ git worktree add --track -b <branch> <path> <remote>/<branch> +------------ ++ If `<commit-ish>` 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 <path>)` 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" <path> <non-existent-branch> fails' ' + test_must_fail git worktree add foo non-existent +' + +test_expect_success '"add" <path> <branch> 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v5 5/6] worktree: add --guess-remote flag to add subcommand 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer ` (3 preceding siblings ...) 2017-11-26 19:43 ` [PATCH v5 4/6] worktree: make add <path> <branch> dwim Thomas Gummerer @ 2017-11-26 19:43 ` Thomas Gummerer 2017-11-27 6:36 ` Junio C Hamano 2017-11-26 19:43 ` [PATCH v5 6/6] add worktree.guessRemote config option Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer 6 siblings, 1 reply; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 19:43 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add <path>' creates a new branch named after the basename of the <path>, that matches the HEAD of whichever worktree we were on when calling "git worktree add <path>". It's sometimes useful to have 'git worktree add <path> behave more like the dwim machinery in 'git checkout <new-branch>', i.e. check if the new branch name 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 <t.gummerer@gmail.com> --- 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..a81cfb2229 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 `add`, instead of creating a new branch from HEAD when + `<commit-ish>` is not given, if there exists a tracking branch + in exactly one remote matching the basename of the path, 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 `<commit-ish>` 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 <branch> 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" <path> <branch> 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v5 5/6] worktree: add --guess-remote flag to add subcommand 2017-11-26 19:43 ` [PATCH v5 5/6] worktree: add --guess-remote flag to add subcommand Thomas Gummerer @ 2017-11-27 6:36 ` Junio C Hamano 2017-11-27 20:56 ` Thomas Gummerer 0 siblings, 1 reply; 36+ messages in thread From: Junio C Hamano @ 2017-11-27 6:36 UTC (permalink / raw) To: Thomas Gummerer Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine, Randall S. Becker, Paul Smith Thomas Gummerer <t.gummerer@gmail.com> writes: > Currently 'git worktree add <path>' creates a new branch named after the > basename of the <path>, that matches the HEAD of whichever worktree we > were on when calling "git worktree add <path>". > > It's sometimes useful to have 'git worktree add <path> behave more like > the dwim machinery in 'git checkout <new-branch>', i.e. check if the new > branch name 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. This paragraph was a bit hard to sympathize because it was not obvious that the new feature still assumes how <path> is used to compute the name of the new branch. Perhaps if it were written like so: check if the new branch name, derived from the basename of the <path>, uniquely matches the branch name of ... I would not have had to read it twice to understand what was going on. > +--[no-]guess-remote:: > + With `add`, instead of creating a new branch from HEAD when > + `<commit-ish>` is not given, if there exists a tracking branch > + in exactly one remote matching the basename of the path, base > + the new branch on the remote-tracking branch, and mark the > + remote-tracking branch as "upstream" from the new branch. > + Would git worktree add --guess-remote <path> <branch> be an error? It is allowed as long as <branch> and the basename of the <path> matches? The option is silently ignored? Something else? I am reacting to "with `add`" part of this desciption. I wouldn't be asking if it said "With `worktree add <path>` without <branch>", as that would make the scenario I am wondering about automatically "undefined". Yes, we should strive for leaving things undefined as little as practically possible, but at least saying something like "without <branch>" explicitly there would make sure that readers know in what scenario this option is meant to be used a bit better. > @@ -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; > + } > } I think the answer is "silently ignored", as the above hunk is inside "if (ac < 2 && !opts.new_branch && !opts.detach)". ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v5 5/6] worktree: add --guess-remote flag to add subcommand 2017-11-27 6:36 ` Junio C Hamano @ 2017-11-27 20:56 ` Thomas Gummerer 0 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-27 20:56 UTC (permalink / raw) To: Junio C Hamano Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine, Randall S. Becker, Paul Smith On 11/27, Junio C Hamano wrote: > Thomas Gummerer <t.gummerer@gmail.com> writes: > > > Currently 'git worktree add <path>' creates a new branch named after the > > basename of the <path>, that matches the HEAD of whichever worktree we > > were on when calling "git worktree add <path>". > > > > It's sometimes useful to have 'git worktree add <path> behave more like > > the dwim machinery in 'git checkout <new-branch>', i.e. check if the new > > branch name 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. > > This paragraph was a bit hard to sympathize because it was not > obvious that the new feature still assumes how <path> is used to > compute the name of the new branch. Perhaps if it were written like > so: > > check if the new branch name, derived from the basename of > the <path>, uniquely matches the branch name of ... > > I would not have had to read it twice to understand what was going > on. Sorry about that, will re-phrase. > > +--[no-]guess-remote:: > > + With `add`, instead of creating a new branch from HEAD when > > + `<commit-ish>` is not given, if there exists a tracking branch > > + in exactly one remote matching the basename of the path, base > > + the new branch on the remote-tracking branch, and mark the > > + remote-tracking branch as "upstream" from the new branch. > > + > > Would > > git worktree add --guess-remote <path> <branch> > > be an error? It is allowed as long as <branch> and the basename of > the <path> matches? The option is silently ignored? Something > else? > > I am reacting to "with `add`" part of this desciption. I wouldn't > be asking if it said "With `worktree add <path>` without <branch>", > as that would make the scenario I am wondering about automatically > "undefined". Yes, we should strive for leaving things undefined as > little as practically possible, but at least saying something like > "without <branch>" explicitly there would make sure that readers > know in what scenario this option is meant to be used a bit better. As you mentioned below it's silently ignored. The main reason for not erroring out is that it would get a little bit (although not too much) more annoying once the config variable is introduced. If it's strongly preferred to error out when <branch> is given I can change it to that. Either way I'll update the documentation. Thanks! > > @@ -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; > > + } > > } > > I think the answer is "silently ignored", as the above hunk is > inside "if (ac < 2 && !opts.new_branch && !opts.detach)". > ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v5 6/6] add worktree.guessRemote config option 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer ` (4 preceding siblings ...) 2017-11-26 19:43 ` [PATCH v5 5/6] worktree: add --guess-remote flag to add subcommand Thomas Gummerer @ 2017-11-26 19:43 ` Thomas Gummerer 2017-11-27 6:45 ` Junio C Hamano 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer 6 siblings, 1 reply; 36+ messages in thread From: Thomas Gummerer @ 2017-11-26 19:43 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer 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 <t.gummerer@gmail.com> --- Documentation/config.txt | 10 ++++++++++ Documentation/git-worktree.txt | 3 +++ builtin/worktree.c | 14 +++++++++++++- t/t2025-worktree-add.sh | 31 +++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) 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 a81cfb2229..fd841886ef 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -121,6 +121,9 @@ OPTIONS in exactly one remote matching the basename of the path, 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 `<commit-ish>` is a branch, diff --git a/builtin/worktree.c b/builtin/worktree.c index 15cb1600ee..426aea8761 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 0; +} + 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 <branch> even if already checked out in other worktree")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), @@ -361,6 +371,8 @@ static int add(int ac, const char **av, const char *prefix) OPT_END() }; + git_config(git_worktree_config, NULL); + memset(&opts, 0, sizeof(opts)); opts.checkout = 1; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v5 6/6] add worktree.guessRemote config option 2017-11-26 19:43 ` [PATCH v5 6/6] add worktree.guessRemote config option Thomas Gummerer @ 2017-11-27 6:45 ` Junio C Hamano 2017-11-27 20:59 ` Thomas Gummerer 0 siblings, 1 reply; 36+ messages in thread From: Junio C Hamano @ 2017-11-27 6:45 UTC (permalink / raw) To: Thomas Gummerer Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine, Randall S. Becker, Paul Smith Thomas Gummerer <t.gummerer@gmail.com> writes: > +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. Unlike the part I commented on in the previous step, this one is clear that the feature only kicks in for 'add <path>' without anything else, which is good. > diff --git a/builtin/worktree.c b/builtin/worktree.c > index 15cb1600ee..426aea8761 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 0; > +} > + It is a lot more consistent with the established practice if this function had return git_default_config(var, value, cb); instead of "return 0" at the end, and then have the call to git_config(git_default_config, NULL); we have in cmd_worktree() replaced with git_config(git_worktree_config, NULL); That would avoid having to scan the entire set of config keys once in cmd_worktree() and then again in add(), the latter one only looking for a single variable. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v5 6/6] add worktree.guessRemote config option 2017-11-27 6:45 ` Junio C Hamano @ 2017-11-27 20:59 ` Thomas Gummerer 0 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-27 20:59 UTC (permalink / raw) To: Junio C Hamano Cc: git, Nguyễn Thái Ngọc Duy, Eric Sunshine, Randall S. Becker, Paul Smith On 11/27, Junio C Hamano wrote: > Thomas Gummerer <t.gummerer@gmail.com> writes: > > > +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. > > Unlike the part I commented on in the previous step, this one is > clear that the feature only kicks in for 'add <path>' without > anything else, which is good. > > > diff --git a/builtin/worktree.c b/builtin/worktree.c > > index 15cb1600ee..426aea8761 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 0; > > +} > > + > > It is a lot more consistent with the established practice if this > function had > > return git_default_config(var, value, cb); > > instead of "return 0" at the end, and then have the call to > > git_config(git_default_config, NULL); > > we have in cmd_worktree() replaced with > > git_config(git_worktree_config, NULL); > > That would avoid having to scan the entire set of config keys once > in cmd_worktree() and then again in add(), the latter one only > looking for a single variable. Makes sense, I missed that. I'll fix it in the re-roll. I'll wait a few days to see if there are any more comments on the series and then re-roll it with the suggested changes. Thanks for the review! ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v6 0/6] make git worktree add dwim more 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer ` (5 preceding siblings ...) 2017-11-26 19:43 ` [PATCH v5 6/6] add worktree.guessRemote config option Thomas Gummerer @ 2017-11-29 20:04 ` Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 1/6] checkout: factor out functions to new lib file Thomas Gummerer ` (5 more replies) 6 siblings, 6 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-29 20:04 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer The previous rounds were at https://public-inbox.org/git/20171112134305.3949-1-t.gummerer@gmail.com/, https://public-inbox.org/git/20171118181103.28354-1-t.gummerer@gmail.com/, https://public-inbox.org/git/20171118224706.13810-1-t.gummerer@gmail.com/, https://public-inbox.org/git/20171122223020.2780-1-t.gummerer@gmail.com/ and https://public-inbox.org/git/20171126194356.16187-1-t.gummerer@gmail.com. Thanks Junio for the review of the last round! Changes since the last round: - rephrased documentation and commit messaegs a bit use the - established pattern and call git_config only once, instead of calling it multiple times. Interdiff below: diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index fd841886ef..89ad0faecf 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -116,11 +116,11 @@ OPTIONS in linkgit:git-read-tree[1]. --[no-]guess-remote:: - With `add`, instead of creating a new branch from HEAD when - `<commit-ish>` is not given, if there exists a tracking branch - in exactly one remote matching the basename of the path, base - the new branch on the remote-tracking branch, and mark the - remote-tracking branch as "upstream" from the new branch. + With `worktree add <path>`, withouth `<commit-ish>`, instead + of creating a new branch from HEAD, if there exists a tracking + branch in exactly one remote matching the basename of `<path>, + 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. diff --git a/builtin/worktree.c b/builtin/worktree.c index 426aea8761..002a569a11 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -43,7 +43,7 @@ static int git_worktree_config(const char *var, const char *value, void *cb) return 0; } - return 0; + return git_default_config(var, value, cb); } static int prune_worktree(const char *id, struct strbuf *reason) @@ -371,8 +371,6 @@ static int add(int ac, const char **av, const char *prefix) OPT_END() }; - git_config(git_worktree_config, NULL); - memset(&opts, 0, sizeof(opts)); opts.checkout = 1; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); @@ -603,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); Thomas Gummerer (6): checkout: factor out functions to new lib file worktree: add can be created from any commit-ish worktree: add --[no-]track option to the add subcommand worktree: make add <path> <branch> dwim worktree: add --guess-remote flag to add subcommand add worktree.guessRemote config option Documentation/config.txt | 10 ++++ Documentation/git-worktree.txt | 44 ++++++++++---- Makefile | 1 + builtin/checkout.c | 41 +------------ builtin/worktree.c | 46 ++++++++++++++- checkout.c | 43 ++++++++++++++ checkout.h | 13 +++++ t/t2025-worktree-add.sh | 130 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 277 insertions(+), 51 deletions(-) create mode 100644 checkout.c create mode 100644 checkout.h -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v6 1/6] checkout: factor out functions to new lib file 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer @ 2017-11-29 20:04 ` Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 2/6] worktree: add can be created from any commit-ish Thomas Gummerer ` (4 subsequent siblings) 5 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-29 20:04 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer 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 <t.gummerer@gmail.com> --- 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 */ -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v6 2/6] worktree: add can be created from any commit-ish 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 1/6] checkout: factor out functions to new lib file Thomas Gummerer @ 2017-11-29 20:04 ` Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 3/6] worktree: add --[no-]track option to the add subcommand Thomas Gummerer ` (3 subsequent siblings) 5 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-29 20:04 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add' is documented to take an optional <branch> 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 <rsbecker@nexbridge.com> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> --- 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 <new-branch>] <path> [<branch>] +'git worktree add' [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>] 'git worktree list' [--porcelain] 'git worktree lock' [--reason <string>] <worktree> 'git worktree prune' [-n] [-v] [--expire <expire>] @@ -45,14 +45,14 @@ specifying `--reason` to explain why the working tree is locked. COMMANDS -------- -add <path> [<branch>]:: +add <path> [<commit-ish>]:: -Create `<path>` and checkout `<branch>` into it. The new working directory +Create `<path>` and checkout `<commit-ish>` 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 `<branch>`; it is synonymous with `@{-1}`. +specified as `<commit-ish>`; it is synonymous with `@{-1}`. + -If `<branch>` is omitted and neither `-b` nor `-B` nor `--detach` used, +If `<commit-ish>` 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 <path>)` was specified. @@ -84,25 +84,25 @@ OPTIONS -f:: --force:: - By default, `add` refuses to create a new working tree when `<branch>` + By default, `add` refuses to create a new working tree when `<commit-ish>` is a branch name and is already checked out by another working tree. This option overrides that safeguard. -b <new-branch>:: -B <new-branch>:: With `add`, create a new branch named `<new-branch>` starting at - `<branch>`, and check out `<new-branch>` into the new working tree. - If `<branch>` is omitted, it defaults to HEAD. + `<commit-ish>`, and check out `<new-branch>` into the new working tree. + If `<commit-ish>` is omitted, it defaults to HEAD. By default, `-b` refuses to create a new branch if it already exists. `-B` overrides this safeguard, resetting `<new-branch>` to - `<branch>`. + `<commit-ish>`. --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 `<branch>`, however, `--no-checkout` can + By default, `add` checks out `<commit-ish>`, 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]. -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v6 3/6] worktree: add --[no-]track option to the add subcommand 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 1/6] checkout: factor out functions to new lib file Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 2/6] worktree: add can be created from any commit-ish Thomas Gummerer @ 2017-11-29 20:04 ` Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 4/6] worktree: make add <path> <branch> dwim Thomas Gummerer ` (2 subsequent siblings) 5 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-29 20:04 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add' sets up tracking branches if '<branch>' 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 <t.gummerer@gmail.com> --- 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 `<commit-ish>` is a branch, + mark it as "upstream" from the new branch. This is the + default if `<commit-ish>` 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 <branch> 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v6 4/6] worktree: make add <path> <branch> dwim 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer ` (2 preceding siblings ...) 2017-11-29 20:04 ` [PATCH v6 3/6] worktree: add --[no-]track option to the add subcommand Thomas Gummerer @ 2017-11-29 20:04 ` Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 5/6] worktree: add --guess-remote flag to add subcommand Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 6/6] add worktree.guessRemote config option Thomas Gummerer 5 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-29 20:04 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add <path> <branch>', 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 <branch>' 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 <t.gummerer@gmail.com> --- 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 `<commit-ish>`; it is synonymous with `@{-1}`. + +If <commit-ish> is a branch name (call it `<branch>` 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 `<remote>`) +with a matching name, treat as equivalent to +------------ +$ git worktree add --track -b <branch> <path> <remote>/<branch> +------------ ++ If `<commit-ish>` 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 <path>)` 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" <path> <non-existent-branch> fails' ' + test_must_fail git worktree add foo non-existent +' + +test_expect_success '"add" <path> <branch> 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v6 5/6] worktree: add --guess-remote flag to add subcommand 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer ` (3 preceding siblings ...) 2017-11-29 20:04 ` [PATCH v6 4/6] worktree: make add <path> <branch> dwim Thomas Gummerer @ 2017-11-29 20:04 ` Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 6/6] add worktree.guessRemote config option Thomas Gummerer 5 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-29 20:04 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer Currently 'git worktree add <path>' creates a new branch named after the basename of the <path>, that matches the HEAD of whichever worktree we were on when calling "git worktree add <path>". It's sometimes useful to have 'git worktree add <path> behave more like the dwim machinery in 'git checkout <new-branch>', i.e. check if the new branch name, derived from the basename of the <path>, 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 <t.gummerer@gmail.com> --- 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..a4ffee5e08 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 <path>`, withouth `<commit-ish>`, instead + of creating a new branch from HEAD, if there exists a tracking + branch in exactly one remote matching the basename of `<path>, + 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 `<commit-ish>` 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 <branch> 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" <path> <branch> 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v6 6/6] add worktree.guessRemote config option 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer ` (4 preceding siblings ...) 2017-11-29 20:04 ` [PATCH v6 5/6] worktree: add --guess-remote flag to add subcommand Thomas Gummerer @ 2017-11-29 20:04 ` Thomas Gummerer 5 siblings, 0 replies; 36+ messages in thread From: Thomas Gummerer @ 2017-11-29 20:04 UTC (permalink / raw) To: git Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano, Eric Sunshine, Randall S. Becker, Paul Smith, Thomas Gummerer 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 <t.gummerer@gmail.com> --- 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 a4ffee5e08..89ad0faecf 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 `<path>, 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 `<commit-ish>` 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 <branch> 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 -- 2.15.0.426.gb06021eeb ^ permalink raw reply related [flat|nested] 36+ messages in thread
end of thread, other threads:[~2017-11-29 20:03 UTC | newest] Thread overview: 36+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <mailto:20171118224706.13810-1-t.gummerer@gmail.com> 2017-11-22 22:30 ` [PATCH v4 0/4] make git worktree add dwim more Thomas Gummerer 2017-11-22 22:30 ` [PATCH v4 1/4] checkout: factor out functions to new lib file Thomas Gummerer 2017-11-24 6:47 ` Junio C Hamano 2017-11-22 22:30 ` [PATCH v4 2/4] worktree: add --[no-]track option to the add subcommand Thomas Gummerer 2017-11-24 6:57 ` Junio C Hamano 2017-11-25 16:58 ` Thomas Gummerer 2017-11-22 22:30 ` [PATCH v4 3/4] worktree: make add <path> <branch> dwim Thomas Gummerer 2017-11-24 6:59 ` Junio C Hamano 2017-11-22 22:30 ` [PATCH v4 4/4] worktree: make add <path> dwim Thomas Gummerer 2017-11-24 7:11 ` Junio C Hamano 2017-11-25 17:50 ` Thomas Gummerer 2017-11-25 18:26 ` Paul Smith 2017-11-25 20:06 ` Thomas Gummerer 2017-11-25 20:39 ` Randall S. Becker 2017-11-25 21:48 ` Thomas Gummerer 2017-11-25 23:11 ` Paul Smith 2017-11-26 3:35 ` Junio C Hamano 2017-11-26 11:37 ` Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 0/6] make git worktree add dwim more Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 1/6] checkout: factor out functions to new lib file Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 2/6] worktree: add can be created from any commit-ish Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 3/6] worktree: add --[no-]track option to the add subcommand Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 4/6] worktree: make add <path> <branch> dwim Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 5/6] worktree: add --guess-remote flag to add subcommand Thomas Gummerer 2017-11-27 6:36 ` Junio C Hamano 2017-11-27 20:56 ` Thomas Gummerer 2017-11-26 19:43 ` [PATCH v5 6/6] add worktree.guessRemote config option Thomas Gummerer 2017-11-27 6:45 ` Junio C Hamano 2017-11-27 20:59 ` Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 0/6] make git worktree add dwim more Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 1/6] checkout: factor out functions to new lib file Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 2/6] worktree: add can be created from any commit-ish Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 3/6] worktree: add --[no-]track option to the add subcommand Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 4/6] worktree: make add <path> <branch> dwim Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 5/6] worktree: add --guess-remote flag to add subcommand Thomas Gummerer 2017-11-29 20:04 ` [PATCH v6 6/6] add worktree.guessRemote config option Thomas Gummerer
Code repositories for project(s) associated with this public inbox https://80x24.org/mirrors/git.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).