{"thread":{"id":"47657","subject":"[PATCH] worktree: teach \"add\" to check out existing branches","startedAt":"2018-01-21T12:00:06Z","lastAt":"2018-04-30T00:07:20Z","messageCount":112,"participants":["Thomas Gummerer","Robert P. J. Day","Duy Nguyen","Junio C Hamano","Eric Sunshine"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"337026","messageId":"20180121120208.12760-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":null,"subject":"[PATCH] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-01-21T12:02:08Z","receivedAt":"2018-01-21T12:00:06Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a brach with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n\nThis is a follow-up to\nhttps://public-inbox.org/git/20171118181345.GC32324@hank/, where this\nwas first suggested, but I didn't want to do it as part of that\nseries.  Now I finally got around to implementing it.\n\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 22 +++++++++++++++-------\n t/t2025-worktree-add.sh        | 15 ++++++++++++---\n 3 files changed, 34 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..98731b71a7 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, a worktree with a branch named after\n+`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` exists in the repository,\n+it will be checked out in the new worktree, if it's not checked out\n+anywhere else, otherwise the command will refuse to create the\n+worktree.\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..148a864bb9 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -411,13 +411,21 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n \t\tint n;\n \t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n+\t\tconst char *branchname = xstrndup(s, n);\n+\t\tstruct strbuf ref = STRBUF_INIT;\n+\t\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t\t    ref_exists(ref.buf)) {\n+\t\t\tbranch = branchname;\n+\t\t\topts.checkout = 1;\n+\t\t} else {\n+\t\t\topts.new_branch = branchname;\n+\t\t\tif (guess_remote) {\n+\t\t\t\tstruct object_id oid;\n+\t\t\t\tconst char *remote =\n+\t\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n+\t\t\t\tif (remote)\n+\t\t\t\t\tbranch = remote;\n+\t\t\t}\n \t\t}\n \t}\n \ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..721b0e4c26 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n+test_expect_success '\"add\" auto-vivify checks out existing branch' '\n \ttest_commit c1 &&\n \ttest_commit c2 &&\n \tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n+\tgit worktree add precious &&\n \ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+\t(\n+\t\tcd precious &&\n+\t\ttest_cmp_rev precious HEAD\n+\t)\n+'\n+\n+test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.16.0.312.g896df04e46\n\n"},{"id":"337027","messageId":"alpine.LFD.2.21.1801210701340.22979@localhost.localdomain","threadId":"47657","inReplyTo":"20180121120208.12760-1-t.gummerer@gmail.com","subject":"Re: [PATCH] worktree: teach \"add\" to check out existing branches","fromName":"Robert P. J. Day","fromEmail":"rpjday@crashcourse.ca","sentAt":"2018-01-21T12:02:10Z","receivedAt":"2018-01-21T12:02:17Z","isPatch":true,"sender":{"key":"rpjday@crashcourse.ca","avatar":"https://avatars.githubusercontent.com/u/226084077?v=4"},"body":"On Sun, 21 Jan 2018, Thomas Gummerer wrote:\n\n> Currently 'git worktree add <path>' creates a new branch named after the\n> basename of the path by default.  If a branch with that name already\n> exists, the command refuses to do anything, unless the '--force' option\n> is given.\n>\n> However we can do a little better than that, and check the branch out if\n> it is not checked out anywhere else.  This will help users who just want\n> to check an existing branch out into a new worktree, and save a few\n> keystrokes.\n>\n> As the current behaviour is to simply 'die()' when a brach with the name\n                                                       ^^^^^\n"},{"id":"337074","messageId":"CACsJy8D9LS7e=cVE3Fq2qOnxK5++nFg2vjuhkNtRO-Bx0X1j6w@mail.gmail.com","threadId":"47657","inReplyTo":"20180121120208.12760-1-t.gummerer@gmail.com","subject":"Re: [PATCH] worktree: teach \"add\" to check out existing branches","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-01-22T11:18:57Z","receivedAt":"2018-01-22T11:19:36Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sun, Jan 21, 2018 at 7:02 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently 'git worktree add <path>' creates a new branch named after the\n> basename of the path by default.  If a branch with that name already\n> exists, the command refuses to do anything, unless the '--force' option\n> is given.\n>\n> However we can do a little better than that, and check the branch out if\n> it is not checked out anywhere else.  This will help users who just want\n> to check an existing branch out into a new worktree, and save a few\n> keystrokes.\n>\n> As the current behaviour is to simply 'die()' when a brach with the name\n> of the basename of the path already exists, there are no backwards\n> compatibility worries here.\n>\n> We will still 'die()' if the branch is checked out in another worktree,\n> unless the --force flag is passed.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n>\n> This is a follow-up to\n> https://public-inbox.org/git/20171118181345.GC32324@hank/, where this\n> was first suggested, but I didn't want to do it as part of that\n> series.  Now I finally got around to implementing it.\n>\n>  Documentation/git-worktree.txt |  9 +++++++--\n>  builtin/worktree.c             | 22 +++++++++++++++-------\n>  t/t2025-worktree-add.sh        | 15 ++++++++++++---\n>  3 files changed, 34 insertions(+), 12 deletions(-)\n>\n> diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\n> index 41585f535d..98731b71a7 100644\n> --- a/Documentation/git-worktree.txt\n> +++ b/Documentation/git-worktree.txt\n> @@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n>  ------------\n>  +\n>  If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n> -then, as a convenience, a new branch based at HEAD is created automatically,\n> -as if `-b $(basename <path>)` was specified.\n> +then, as a convenience, a worktree with a branch named after\n> +`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n> +doesn't exist, a new branch based on HEAD is automatically created as\n> +if `-b <branch>` was given.  If `<branch>` exists in the repository,\n> +it will be checked out in the new worktree, if it's not checked out\n> +anywhere else, otherwise the command will refuse to create the\n> +worktree.\n\nIt starts getting a bit too magical to me. We probably should print\nsomething \"switching to branch...\" or \"creating new branch ...\"  to\nlet people know what decision was taken, unless --quiet is given. Yeah\nI know --quiet does not exist. You don't need to add it now either\nsince nobody has asked for it.\n\nMore or less related to this, there was a question [1] whether we\ncould do better than $(basename <path>) for determining branch name.\nSince you're doing start to check if a branch exists, people may start\nasking to check for branch \"foo/bar\" from the path abc/foo/bar instead\nof just branch \"bar\".\n\n[1] https://github.com/git-for-windows/git/issues/1390\n\n>\n>  list::\n>\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> index 7cef5b120b..148a864bb9 100644\n> --- a/builtin/worktree.c\n> +++ b/builtin/worktree.c\n> @@ -411,13 +411,21 @@ static int add(int ac, const char **av, const char *prefix)\n>         if (ac < 2 && !opts.new_branch && !opts.detach) {\n>                 int n;\n>                 const char *s = worktree_basename(path, &n);\n> -               opts.new_branch = xstrndup(s, n);\n> -               if (guess_remote) {\n> -                       struct object_id oid;\n> -                       const char *remote =\n> -                               unique_tracking_name(opts.new_branch, &oid);\n> -                       if (remote)\n> -                               branch = remote;\n> +               const char *branchname = xstrndup(s, n);\n> +               struct strbuf ref = STRBUF_INIT;\n\nPerhaps a blank line after this to separate var declarations and the rest.\n\n> +               if (!strbuf_check_branch_ref(&ref, branchname) &&\n> +                   ref_exists(ref.buf)) {\n> +                       branch = branchname;\n\nHmm.. do we need UNLEAK(branch);? Maybe you should try valgrind, I'm not sure.\n\n> +                       opts.checkout = 1;\n> +               } else {\n> +                       opts.new_branch = branchname;\n> +                       if (guess_remote) {\n> +                               struct object_id oid;\n> +                               const char *remote =\n> +                                       unique_tracking_name(opts.new_branch, &oid);\n> +                               if (remote)\n> +                                       branch = remote;\n> +                       }\n>                 }\n>         }\n>\n> diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> index 2b95944973..721b0e4c26 100755\n> --- a/t/t2025-worktree-add.sh\n> +++ b/t/t2025-worktree-add.sh\n> @@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n>         test_cmp_rev HEAD bat\n>  '\n>\n> -test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n> +test_expect_success '\"add\" auto-vivify checks out existing branch' '\n>         test_commit c1 &&\n>         test_commit c2 &&\n>         git branch precious HEAD~1 &&\n> -       test_must_fail git worktree add precious &&\n> +       git worktree add precious &&\n>         test_cmp_rev HEAD~1 precious &&\n> -       test_path_is_missing precious\n> +       (\n> +               cd precious &&\n> +               test_cmp_rev precious HEAD\n> +       )\n> +'\n> +\n> +test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n> +       git checkout -b test-branch &&\n> +       test_must_fail git worktree add test-branch &&\n> +       test_path_is_missing test-branch\n>  '\n>\n>  test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n> --\n> 2.16.0.312.g896df04e46\n>\n\n\n\n-- \nDuy\n"},{"id":"337104","messageId":"20180122201728.GA2130@hank","threadId":"47657","inReplyTo":"CACsJy8D9LS7e=cVE3Fq2qOnxK5++nFg2vjuhkNtRO-Bx0X1j6w@mail.gmail.com","subject":"Re: [PATCH] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-01-22T20:17:28Z","receivedAt":"2018-01-22T20:15:14Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 01/22, Duy Nguyen wrote:\n> On Sun, Jan 21, 2018 at 7:02 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > [...]\n> >  +\n> >  If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n> > -then, as a convenience, a new branch based at HEAD is created automatically,\n> > -as if `-b $(basename <path>)` was specified.\n> > +then, as a convenience, a worktree with a branch named after\n> > +`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n> > +doesn't exist, a new branch based on HEAD is automatically created as\n> > +if `-b <branch>` was given.  If `<branch>` exists in the repository,\n> > +it will be checked out in the new worktree, if it's not checked out\n> > +anywhere else, otherwise the command will refuse to create the\n> > +worktree.\n> \n> It starts getting a bit too magical to me. We probably should print\n> something \"switching to branch...\" or \"creating new branch ...\"  to\n> let people know what decision was taken, unless --quiet is given. Yeah\n> I know --quiet does not exist. You don't need to add it now either\n> since nobody has asked for it.\n\nI think that's a good idea.  I'll add that, thanks.\n\n> More or less related to this, there was a question [1] whether we\n> could do better than $(basename <path>) for determining branch name.\n> Since you're doing start to check if a branch exists, people may start\n> asking to check for branch \"foo/bar\" from the path abc/foo/bar instead\n> of just branch \"bar\".\n\nThanks for pointing me at this.  I feel like we might get ourselves\nsome backwards compatibility worries when doing that.  Lets say\nsomeone has a branch 'feature/a', using 'git worktree feature/a' would\ncurrently create a new branch 'a', and does not die.\n\nI'd guess most users would want 'feature/a' checked out in that case,\nbut we can't exactly be sure we won't break anyones workflow here.\nWith your suggestion I guess that would be mitigated somehow as it\nshows which action is taken, but dunno.\n\nShould we hide this behaviour behind a flag, and plan for it\neventually becoming the default?\n\n> [1] https://github.com/git-for-windows/git/issues/1390\n> \n> >\n> >  list::\n> >\n> > diff --git a/builtin/worktree.c b/builtin/worktree.c\n> > index 7cef5b120b..148a864bb9 100644\n> > --- a/builtin/worktree.c\n> > +++ b/builtin/worktree.c\n> > @@ -411,13 +411,21 @@ static int add(int ac, const char **av, const char *prefix)\n> >         if (ac < 2 && !opts.new_branch && !opts.detach) {\n> >                 int n;\n> >                 const char *s = worktree_basename(path, &n);\n> > -               opts.new_branch = xstrndup(s, n);\n> > -               if (guess_remote) {\n> > -                       struct object_id oid;\n> > -                       const char *remote =\n> > -                               unique_tracking_name(opts.new_branch, &oid);\n> > -                       if (remote)\n> > -                               branch = remote;\n> > +               const char *branchname = xstrndup(s, n);\n> > +               struct strbuf ref = STRBUF_INIT;\n> \n> Perhaps a blank line after this to separate var declarations and the rest.\n\nWill add. \n\n> > +               if (!strbuf_check_branch_ref(&ref, branchname) &&\n> > +                   ref_exists(ref.buf)) {\n> > +                       branch = branchname;\n> \n> Hmm.. do we need UNLEAK(branch);? Maybe you should try valgrind, I'm not sure.\n\nGood question, I'll have a look, thanks.\n\n> > +                       opts.checkout = 1;\n> > +               } else {\n> > +                       opts.new_branch = branchname;\n> > +                       if (guess_remote) {\n> > +                               struct object_id oid;\n> > +                               const char *remote =\n> > +                                       unique_tracking_name(opts.new_branch, &oid);\n> > +                               if (remote)\n> > +                                       branch = remote;\n> > +                       }\n> >                 }\n> >         }\n> >\n> > diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> > index 2b95944973..721b0e4c26 100755\n> > --- a/t/t2025-worktree-add.sh\n> > +++ b/t/t2025-worktree-add.sh\n> > @@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n> >         test_cmp_rev HEAD bat\n> >  '\n> >\n> > -test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n> > +test_expect_success '\"add\" auto-vivify checks out existing branch' '\n> >         test_commit c1 &&\n> >         test_commit c2 &&\n> >         git branch precious HEAD~1 &&\n> > -       test_must_fail git worktree add precious &&\n> > +       git worktree add precious &&\n> >         test_cmp_rev HEAD~1 precious &&\n> > -       test_path_is_missing precious\n> > +       (\n> > +               cd precious &&\n> > +               test_cmp_rev precious HEAD\n> > +       )\n> > +'\n> > +\n> > +test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n> > +       git checkout -b test-branch &&\n> > +       test_must_fail git worktree add test-branch &&\n> > +       test_path_is_missing test-branch\n> >  '\n> >\n> >  test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n> > --\n> > 2.16.0.312.g896df04e46\n> >\n> \n> \n> \n> -- \n> Duy\n"},{"id":"338176","messageId":"20180204221305.28300-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180121120208.12760-1-t.gummerer@gmail.com","subject":"[PATCH v2 0/3] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-04T22:13:02Z","receivedAt":"2018-02-04T22:13:12Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"The previous round was at <20180121120208.12760-1-t.gummerer@gmail.com>.\nThanks Duy for the comments on the previous round.\n\nIn addition to the additional functionality, this series now includes\nimprovements to the output of the \"git worktree add\" command.  It\ndoesn't include any new magic to guess the branchname, as was\nsuggested, as that would be a bigger change in the behaviour of git\nworktree, and is not a particular itch I have right now, so I'd prefer\nto keep it separate.\n\nThomas Gummerer (3):\n  worktree: improve message when creating a new worktree\n  worktree: be clearer when \"add\" dwim-ery kicks in\n  worktree: teach \"add\" to check out existing branches\n\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 45 +++++++++++++++++++++++++++++++++---------\n t/t2025-worktree-add.sh        | 15 +++++++++++---\n 3 files changed, 55 insertions(+), 14 deletions(-)\n\n-- \n2.16.1.101.gde0f0111ea\n\n"},{"id":"338177","messageId":"20180204221305.28300-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180204221305.28300-1-t.gummerer@gmail.com","subject":"[PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-04T22:13:03Z","receivedAt":"2018-02-04T22:13:16Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following, when\n'--no-checkout' is not given:\n\n    Preparing foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nwhere the first line is written to stderr, and the second line coming\nfrom 'git reset --hard' is written to stdout, even though both lines are\nsupposed to tell the user what has happened.  In addition to someone not\nfamiliar with 'git worktree', this might seem as if the current HEAD was\nmodified, not the HEAD in the new working tree.\n\nIf the '--no-checkout' flag is given, the output of 'git worktree add'\nis just:\n\n    Preparing foo (identifier foo)\n\neven though the HEAD is set to a commit, which is just not checked out.\n\nFix these inconsistencies by making the 'git reset --hard' call quiet,\nand printing the message ourselves instead.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n\nWe might want to do something similar for the 'git branch' command in\nthe 'add()' function, which currently prints some output if a branch\nis set up to track a remote.  I couldn't find a good way to convey\nthat information in the output here, without making it too verbose,\nand it's probably not great to loose that output either.\n\nIf anyone has any suggestions for that, I'd be glad to hear them :)\n\n builtin/worktree.c | 13 +++++++++++--\n 1 file changed, 11 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..d1549e441d 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -303,7 +303,7 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n+\tfprintf(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n \n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n@@ -320,10 +320,19 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tfprintf(stderr, _(\", setting HEAD to %s\"),\n+\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n+\n+\tstrbuf_reset(&sb);\n+\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\tif (sb.len > 0)\n+\t\tfprintf(stderr, \" %s\", sb.buf);\n+\tfputc('\\n', stderr);\n+\n \tif (opts->checkout) {\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n-\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n+\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n \t\tcp.env = child_env.argv;\n \t\tret = run_command(&cp);\n \t\tif (ret)\n-- \n2.16.1.101.gde0f0111ea\n\n"},{"id":"338178","messageId":"20180204221305.28300-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180204221305.28300-1-t.gummerer@gmail.com","subject":"[PATCH v2 2/3] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-04T22:13:04Z","receivedAt":"2018-02-04T22:13:18Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently there is no indication in the \"git worktree add\" output that\na new branch was created.  This would be especially useful information\nin the case where the dwim of \"git worktree add <path>\" kicks in, as the\nuser didn't explicitly ask for a new branch, but we create one from\nthem.\n\nPrint some additional output showing that a branch was created and the\nbranch name to help the user.\n\nThis will also be useful in the next commit, which introduces a new kind\nof dwim-ery of checking out the branch if it exists instead of refusing\nto create a new worktree in that case, and where it's nice to tell the\nuser which kind of dwim-ery kicked in.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex d1549e441d..74a853c2a3 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -320,6 +320,9 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tif (opts->new_branch)\n+\t\tfprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n+\n \tfprintf(stderr, _(\", setting HEAD to %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n \n-- \n2.16.1.101.gde0f0111ea\n\n"},{"id":"338179","messageId":"20180204221305.28300-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180204221305.28300-1-t.gummerer@gmail.com","subject":"[PATCH v2 3/3] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-04T22:13:05Z","receivedAt":"2018-02-04T22:13:21Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 31 +++++++++++++++++++++++--------\n t/t2025-worktree-add.sh        | 15 ++++++++++++---\n 3 files changed, 42 insertions(+), 13 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..98731b71a7 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, a worktree with a branch named after\n+`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` exists in the repository,\n+it will be checked out in the new worktree, if it's not checked out\n+anywhere else, otherwise the command will refuse to create the\n+worktree.\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 74a853c2a3..ea420bb90b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -29,6 +29,7 @@ struct add_opts {\n \tint keep_locked;\n \tconst char *new_branch;\n \tint force_new_branch;\n+\tint checkout_existing_branch;\n };\n \n static int show_only;\n@@ -320,7 +321,10 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n-\tif (opts->new_branch)\n+\tif (opts->checkout_existing_branch)\n+\t\tfprintf(stderr, _(\", checking out existing branch '%s'\"),\n+\t\t\trefname);\n+\telse if (opts->new_branch)\n \t\tfprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n \n \tfprintf(stderr, _(\", setting HEAD to %s\"),\n@@ -423,14 +427,25 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n \t\tint n;\n \t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n+\t\tconst char *branchname = xstrndup(s, n);\n+\t\tstruct strbuf ref = STRBUF_INIT;\n+\n+\t\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t\t    ref_exists(ref.buf)) {\n+\t\t\tbranch = branchname;\n+\t\t\topts.checkout_existing_branch = 1;\n+\t\t\tUNLEAK(branch);\n+\t\t} else {\n+\t\t\topts.new_branch = branchname;\n+\t\t\tif (guess_remote) {\n+\t\t\t\tstruct object_id oid;\n+\t\t\t\tconst char *remote =\n+\t\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n+\t\t\t\tif (remote)\n+\t\t\t\t\tbranch = remote;\n+\t\t\t}\n \t\t}\n+\t\tstrbuf_release(&ref);\n \t}\n \n \tif (ac == 2 && !opts.new_branch && !opts.detach) {\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..721b0e4c26 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n+test_expect_success '\"add\" auto-vivify checks out existing branch' '\n \ttest_commit c1 &&\n \ttest_commit c2 &&\n \tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n+\tgit worktree add precious &&\n \ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+\t(\n+\t\tcd precious &&\n+\t\ttest_cmp_rev precious HEAD\n+\t)\n+'\n+\n+test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.16.1.101.gde0f0111ea\n\n"},{"id":"338180","messageId":"20180205021202.GA17847@duynguyen.dek-tpc.internal","threadId":"47657","inReplyTo":"20180204221305.28300-2-t.gummerer@gmail.com","subject":"Re: [PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-05T02:12:02Z","receivedAt":"2018-02-05T02:12:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sun, Feb 04, 2018 at 10:13:03PM +0000, Thomas Gummerer wrote:\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> index 7cef5b120b..d1549e441d 100644\n> --- a/builtin/worktree.c\n> +++ b/builtin/worktree.c\n> @@ -303,7 +303,7 @@ static int add_worktree(const char *path, const char *refname,\n>  \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n>  \twrite_file(sb.buf, \"../..\");\n>  \n> -\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n> +\tfprintf(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n>  \n>  \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n>  \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n> @@ -320,10 +320,19 @@ static int add_worktree(const char *path, const char *refname,\n>  \tif (ret)\n>  \t\tgoto done;\n>  \n> +\tfprintf(stderr, _(\", setting HEAD to %s\"),\n\nAs a former translator, I'm not thrilled to see a sentence broken into\ntwo pieces like this. I'm not a Japanese translator, but I think this\nsentence is translated differently when the translator sees the whole\nline \"Preparing ..., setting ...\".\n\nSince the code between the first fprintf and this one should not take\nlong to execute, perhaps we can just delete the first printf and print\na whole [*] sentence here?\n\nI think the purpose of \"Preparing...\" in the first place is to show\nsomething when git is busy checkout out the worktree. As long as we\nprint it before git-reset, we should be good.\n\n> +\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> +\n> +\tstrbuf_reset(&sb);\n> +\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n> +\tif (sb.len > 0)\n> +\t\tfprintf(stderr, \" %s\", sb.buf);\n\n[*] Yes I know it's not \"whole\" because of this piece. But this one is\nmore or less a separate sentence already so it's probably ok.\n\nIs it a bit too long to print everything in one line though?\nCMIT_FMT_ONELINE could already fill 70 columns easily.\n\n> +\tfputc('\\n', stderr);\n> +\n>  \tif (opts->checkout) {\n>  \t\tcp.argv = NULL;\n>  \t\targv_array_clear(&cp.args);\n> -\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n> +\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n>  \t\tcp.env = child_env.argv;\n>  \t\tret = run_command(&cp);\n>  \t\tif (ret)\n> -- \n> 2.16.1.101.gde0f0111ea\n> \n"},{"id":"338181","messageId":"20180205021833.GB17847@duynguyen.dek-tpc.internal","threadId":"47657","inReplyTo":"20180204221305.28300-4-t.gummerer@gmail.com","subject":"Re: [PATCH v2 3/3] worktree: teach \"add\" to check out existing branches","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-05T02:18:33Z","receivedAt":"2018-02-05T02:23:28Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sun, Feb 04, 2018 at 10:13:05PM +0000, Thomas Gummerer wrote:\n> -\tif (opts->new_branch)\n> +\tif (opts->checkout_existing_branch)\n> +\t\tfprintf(stderr, _(\", checking out existing branch '%s'\"),\n> +\t\t\trefname);\n> +\telse if (opts->new_branch)\n>  \t\tfprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n\nI wonder if \"creating branch\" and \"checkout out branch\" are enough.\n\n> @@ -423,14 +427,25 @@ static int add(int ac, const char **av, const char *prefix)\n>  \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n>  \t\tint n;\n>  \t\tconst char *s = worktree_basename(path, &n);\n> -\t\topts.new_branch = xstrndup(s, n);\n> -\t\tif (guess_remote) {\n> -\t\t\tstruct object_id oid;\n> -\t\t\tconst char *remote =\n> -\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n> -\t\t\tif (remote)\n> -\t\t\t\tbranch = remote;\n> +\t\tconst char *branchname = xstrndup(s, n);\n> +\t\tstruct strbuf ref = STRBUF_INIT;\n> +\n> +\t\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n> +\t\t    ref_exists(ref.buf)) {\n> +\t\t\tbranch = branchname;\n> +\t\t\topts.checkout_existing_branch = 1;\n> +\t\t\tUNLEAK(branch);\n> +\t\t} else {\n> +\t\t\topts.new_branch = branchname;\n> +\t\t\tif (guess_remote) {\n> +\t\t\t\tstruct object_id oid;\n> +\t\t\t\tconst char *remote =\n> +\t\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n\nDeep indentation may be a sign that it's time to move all this code to\na separate function, maybe dwim_branch() or something.\n\n> +\t\t\t\tif (remote)\n> +\t\t\t\t\tbranch = remote;\n> +\t\t\t}\n>  \t\t}\n> +\t\tstrbuf_release(&ref);\n>  \t}\n>  \n>  \tif (ac == 2 && !opts.new_branch && !opts.detach) {\n"},{"id":"338245","messageId":"20180205201349.GD2130@hank","threadId":"47657","inReplyTo":"20180205021202.GA17847@duynguyen.dek-tpc.internal","subject":"Re: [PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-05T20:13:49Z","receivedAt":"2018-02-05T20:13:49Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 02/05, Duy Nguyen wrote:\n> On Sun, Feb 04, 2018 at 10:13:03PM +0000, Thomas Gummerer wrote:\n> > diff --git a/builtin/worktree.c b/builtin/worktree.c\n> > index 7cef5b120b..d1549e441d 100644\n> > --- a/builtin/worktree.c\n> > +++ b/builtin/worktree.c\n> > @@ -303,7 +303,7 @@ static int add_worktree(const char *path, const char *refname,\n> >  \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n> >  \twrite_file(sb.buf, \"../..\");\n> >  \n> > -\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n> > +\tfprintf(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n> >  \n> >  \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n> >  \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n> > @@ -320,10 +320,19 @@ static int add_worktree(const char *path, const char *refname,\n> >  \tif (ret)\n> >  \t\tgoto done;\n> >  \n> > +\tfprintf(stderr, _(\", setting HEAD to %s\"),\n> \n> As a former translator, I'm not thrilled to see a sentence broken into\n> two pieces like this. I'm not a Japanese translator, but I think this\n> sentence is translated differently when the translator sees the whole\n> line \"Preparing ..., setting ...\".\n\nGood point, I didn't think about the sentence structure other\nlanguages could require here. \n\n> Since the code between the first fprintf and this one should not take\n> long to execute, perhaps we can just delete the first printf and print\n> a whole [*] sentence here?\n> \n> I think the purpose of \"Preparing...\" in the first place is to show\n> something when git is busy checkout out the worktree. As long as we\n> print it before git-reset, we should be good.\n> \n> > +\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> > +\n> > +\tstrbuf_reset(&sb);\n> > +\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n> > +\tif (sb.len > 0)\n> > +\t\tfprintf(stderr, \" %s\", sb.buf);\n> \n> [*] Yes I know it's not \"whole\" because of this piece. But this one is\n> more or less a separate sentence already so it's probably ok.\n> \n> Is it a bit too long to print everything in one line though?\n> CMIT_FMT_ONELINE could already fill 70 columns easily.\n\nYeah, it does get a bit long.  Maybe just splitting the sentences here\nwould be the best solution, then we also won't have to worry about the\nsplit not being good for translation.  I'll do that.\n\n> > +\tfputc('\\n', stderr);\n> > +\n> >  \tif (opts->checkout) {\n> >  \t\tcp.argv = NULL;\n> >  \t\targv_array_clear(&cp.args);\n> > -\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n> > +\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n> >  \t\tcp.env = child_env.argv;\n> >  \t\tret = run_command(&cp);\n> >  \t\tif (ret)\n> > -- \n> > 2.16.1.101.gde0f0111ea\n> > \n"},{"id":"338246","messageId":"xmqqlgg79oqs.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"20180205021202.GA17847@duynguyen.dek-tpc.internal","subject":"Re: [PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-02-05T20:15:55Z","receivedAt":"2018-02-05T20:16:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> On Sun, Feb 04, 2018 at 10:13:03PM +0000, Thomas Gummerer wrote:\n>> diff --git a/builtin/worktree.c b/builtin/worktree.c\n>> index 7cef5b120b..d1549e441d 100644\n>> --- a/builtin/worktree.c\n>> +++ b/builtin/worktree.c\n>> @@ -303,7 +303,7 @@ static int add_worktree(const char *path, const char *refname,\n>>  \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n>>  \twrite_file(sb.buf, \"../..\");\n>>  \n>> -\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n>> +\tfprintf(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n>>  \n>>  \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n>>  \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n>> @@ -320,10 +320,19 @@ static int add_worktree(const char *path, const char *refname,\n>>  \tif (ret)\n>>  \t\tgoto done;\n>>  \n>> +\tfprintf(stderr, _(\", setting HEAD to %s\"),\n>\n> As a former translator, I'm not thrilled to see a sentence broken into\n> two pieces like this. I'm not a Japanese translator, but I think this\n> sentence is translated differently when the translator sees the whole\n> line \"Preparing ..., setting ...\".\n>\n> Since the code between the first fprintf and this one should not take\n> long to execute, perhaps we can just delete the first printf and print\n> a whole [*] sentence here?\n\nYeah, also it is a bit troubling that \"Preparing\" is an incomplete line,\nand when update-ref/symblic-ref call fails, will stay to be incomplete.\n\n> I think the purpose of \"Preparing...\" in the first place is to show\n> something when git is busy checkout out the worktree. As long as we\n> print it before git-reset, we should be good.\n>\n>> +\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n>> +\n>> +\tstrbuf_reset(&sb);\n>> +\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n>> +\tif (sb.len > 0)\n>> +\t\tfprintf(stderr, \" %s\", sb.buf);\n>\n> [*] Yes I know it's not \"whole\" because of this piece. But this one is\n> more or less a separate sentence already so it's probably ok.\n\nDoing all the additional fprintf/fputc at the same place (instead of\nacross update-ref/symbolic-ref) would make it easier to follow and\nalso allow it to make \"whole\" even with that piece.  Prepare the\nabbreviated commit->object.oid.hash and FMT_ONELINE in the same\nstrbuf and say that the HEAD is there.  I think it also makes sense\nto split it into two sentences, so from that point of view, just\ndropping the change in the \"Preparing\" hunk and then saying \"HEAD is\nnow at '9876fdea title of the commit'\" after update/symbolic-ref may\nalso be a good change.  That automatically removes the \"what hapepns\nto the rest of the incomplete line when run_command() fails?\" issue.\n\n> Is it a bit too long to print everything in one line though?\n> CMIT_FMT_ONELINE could already fill 70 columns easily.\n>\n>> +\tfputc('\\n', stderr);\n>> +\n>>  \tif (opts->checkout) {\n>>  \t\tcp.argv = NULL;\n>>  \t\targv_array_clear(&cp.args);\n>> -\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n>> +\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n>>  \t\tcp.env = child_env.argv;\n>>  \t\tret = run_command(&cp);\n>>  \t\tif (ret)\n>> -- \n>> 2.16.1.101.gde0f0111ea\n>> \n"},{"id":"338248","messageId":"xmqqh8qv9ojb.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"20180205021833.GB17847@duynguyen.dek-tpc.internal","subject":"Re: [PATCH v2 3/3] worktree: teach \"add\" to check out existing branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-02-05T20:20:24Z","receivedAt":"2018-02-05T20:20:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> On Sun, Feb 04, 2018 at 10:13:05PM +0000, Thomas Gummerer wrote:\n>> -\tif (opts->new_branch)\n>> +\tif (opts->checkout_existing_branch)\n>> +\t\tfprintf(stderr, _(\", checking out existing branch '%s'\"),\n>> +\t\t\trefname);\n>> +\telse if (opts->new_branch)\n>>  \t\tfprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n>\n> I wonder if \"creating branch\" and \"checkout out branch\" are enough.\n\nYeah, I think new/existing are redundant.  If these were shown at\nthe same time, then the extra adjectives would help differenciating\nthem visually, but they are never shown at the same time, so...\n"},{"id":"338249","messageId":"20180205202332.GE2130@hank","threadId":"47657","inReplyTo":"20180205021833.GB17847@duynguyen.dek-tpc.internal","subject":"Re: [PATCH v2 3/3] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-05T20:23:32Z","receivedAt":"2018-02-05T20:23:32Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 02/05, Duy Nguyen wrote:\n> On Sun, Feb 04, 2018 at 10:13:05PM +0000, Thomas Gummerer wrote:\n> > -\tif (opts->new_branch)\n> > +\tif (opts->checkout_existing_branch)\n> > +\t\tfprintf(stderr, _(\", checking out existing branch '%s'\"),\n> > +\t\t\trefname);\n> > +\telse if (opts->new_branch)\n> >  \t\tfprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n> \n> I wonder if \"creating branch\" and \"checkout out branch\" are enough.\n\nI thought printing the branch name might be a good idea just to show\nmore clearly what the dwim did.  Especially if we ever introduce new\nheuristics, for example to cater for the case you mentioned in an\nearlier email [1], I thought it might be helpful to also print the\nbranch name.  Especially because it makes it clear that the dwim the\nreporter of the github issue hoped for didn't kick in at this point.\n\nThat said, I don't really think the branchname is of much use for my\nusage of 'git worktree add', so I may be overestimating the need for\nit.  I'm happy to remove it if that's preferred.\n\n[1]: <CACsJy8D9LS7e=cVE3Fq2qOnxK5++nFg2vjuhkNtRO-Bx0X1j6w@mail.gmail.com>\n\n> > @@ -423,14 +427,25 @@ static int add(int ac, const char **av, const char *prefix)\n> >  \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n> >  \t\tint n;\n> >  \t\tconst char *s = worktree_basename(path, &n);\n> > -\t\topts.new_branch = xstrndup(s, n);\n> > -\t\tif (guess_remote) {\n> > -\t\t\tstruct object_id oid;\n> > -\t\t\tconst char *remote =\n> > -\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n> > -\t\t\tif (remote)\n> > -\t\t\t\tbranch = remote;\n> > +\t\tconst char *branchname = xstrndup(s, n);\n> > +\t\tstruct strbuf ref = STRBUF_INIT;\n> > +\n> > +\t\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n> > +\t\t    ref_exists(ref.buf)) {\n> > +\t\t\tbranch = branchname;\n> > +\t\t\topts.checkout_existing_branch = 1;\n> > +\t\t\tUNLEAK(branch);\n> > +\t\t} else {\n> > +\t\t\topts.new_branch = branchname;\n> > +\t\t\tif (guess_remote) {\n> > +\t\t\t\tstruct object_id oid;\n> > +\t\t\t\tconst char *remote =\n> > +\t\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n> \n> Deep indentation may be a sign that it's time to move all this code to\n> a separate function, maybe dwim_branch() or something.\n\nMakes sense, I'll factor it out.  Thanks!\n\n> > +\t\t\t\tif (remote)\n> > +\t\t\t\t\tbranch = remote;\n> > +\t\t\t}\n> >  \t\t}\n> > +\t\tstrbuf_release(&ref);\n> >  \t}\n> >  \n> >  \tif (ac == 2 && !opts.new_branch && !opts.detach) {\n"},{"id":"338501","messageId":"CACsJy8BEKYqW+Ne_WY2RBaSbb9OKcjREtrawStj=eJsVsia_Jw@mail.gmail.com","threadId":"47657","inReplyTo":"20180205202332.GE2130@hank","subject":"Re: [PATCH v2 3/3] worktree: teach \"add\" to check out existing branches","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-06T11:53:23Z","receivedAt":"2018-02-06T11:53:59Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Feb 6, 2018 at 3:23 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> On 02/05, Duy Nguyen wrote:\n>> On Sun, Feb 04, 2018 at 10:13:05PM +0000, Thomas Gummerer wrote:\n>> > -   if (opts->new_branch)\n>> > +   if (opts->checkout_existing_branch)\n>> > +           fprintf(stderr, _(\", checking out existing branch '%s'\"),\n>> > +                   refname);\n>> > +   else if (opts->new_branch)\n>> >             fprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n>>\n>> I wonder if \"creating branch\" and \"checkout out branch\" are enough.\n>\n> I thought printing the branch name might be a good idea just to show\n> more clearly what the dwim did.\n\nNo no printing branch name is definitely a good idea, especially when\nI think of one thing and type another. I shortened my example phrases\ntoo much. It should have been \"creating branch %s\" and \"checkout out\nbranch %s\"\n-- \nDuy\n"},{"id":"338594","messageId":"CAPig+cRLohiqR_Drh7P0q3XbvC22WLjNwH0YLZo3dqFzZZuAPw@mail.gmail.com","threadId":"47657","inReplyTo":"20180205021202.GA17847@duynguyen.dek-tpc.internal","subject":"Re: [PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-02-07T08:51:11Z","receivedAt":"2018-02-07T08:51:25Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Feb 4, 2018 at 9:12 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> As a former translator, I'm not thrilled to see a sentence broken into\n> two pieces like this. I'm not a Japanese translator, but I think this\n> sentence is translated differently when the translator sees the whole\n> line \"Preparing ..., setting ...\".\n>\n> I think the purpose of \"Preparing...\" in the first place is to show\n> something when git is busy checkout out the worktree. As long as we\n> print it before git-reset, we should be good.\n\nThe original message was \"Enter <worktree>\" which had the potential to\nconfuse someone into thinking the working directory had changed[1], so\nit was changed to \"Preparing...\". The reason for keeping that message\n(rather than dropping it outright) was to provide context to messages\nprinted after it, especially messages such as \"HEAD is now at...\"\nwhich might otherwise confuse the reader into thinking that HEAD in\nthe current worktree changed rather than HEAD in the new\nworktree[2,3].\n\n[1]: https://public-inbox.org/git/55A8F4B1.9060304@drmicha.warpmail.net/\n[2]: https://public-inbox.org/git/CAPig+cRSHwmmF9cCUbRrDCCW4kvg9PeOUxP5VQpSGfxzMxHWOQ@mail.gmail.com/\n[3]: https://public-inbox.org/git/CAPig+cSLs4-uKicVMBSKnEro_FYD722Hs1_U6qzTriM8Ciok2Q@mail.gmail.com/\n"},{"id":"338840","messageId":"20180209110437.GF2130@hank","threadId":"47657","inReplyTo":"CACsJy8BEKYqW+Ne_WY2RBaSbb9OKcjREtrawStj=eJsVsia_Jw@mail.gmail.com","subject":"Re: [PATCH v2 3/3] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-09T11:04:38Z","receivedAt":"2018-02-09T11:04:34Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 02/06, Duy Nguyen wrote:\n> On Tue, Feb 6, 2018 at 3:23 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > On 02/05, Duy Nguyen wrote:\n> >> On Sun, Feb 04, 2018 at 10:13:05PM +0000, Thomas Gummerer wrote:\n> >> > -   if (opts->new_branch)\n> >> > +   if (opts->checkout_existing_branch)\n> >> > +           fprintf(stderr, _(\", checking out existing branch '%s'\"),\n> >> > +                   refname);\n> >> > +   else if (opts->new_branch)\n> >> >             fprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n> >>\n> >> I wonder if \"creating branch\" and \"checkout out branch\" are enough.\n> >\n> > I thought printing the branch name might be a good idea just to show\n> > more clearly what the dwim did.\n> \n> No no printing branch name is definitely a good idea, especially when\n> I think of one thing and type another. I shortened my example phrases\n> too much. It should have been \"creating branch %s\" and \"checkout out\n> branch %s\"\n\nAh sorry I misunderstood.  Yeah I think that makes sense then :)\n\n> -- \n> Duy\n"},{"id":"338863","messageId":"20180209112727.GG2130@hank","threadId":"47657","inReplyTo":"CAPig+cRLohiqR_Drh7P0q3XbvC22WLjNwH0YLZo3dqFzZZuAPw@mail.gmail.com","subject":"Re: [PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-02-09T11:27:27Z","receivedAt":"2018-02-09T11:27:24Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 02/07, Eric Sunshine wrote:\n> On Sun, Feb 4, 2018 at 9:12 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> > As a former translator, I'm not thrilled to see a sentence broken into\n> > two pieces like this. I'm not a Japanese translator, but I think this\n> > sentence is translated differently when the translator sees the whole\n> > line \"Preparing ..., setting ...\".\n> >\n> > I think the purpose of \"Preparing...\" in the first place is to show\n> > something when git is busy checkout out the worktree. As long as we\n> > print it before git-reset, we should be good.\n> \n> The original message was \"Enter <worktree>\" which had the potential to\n> confuse someone into thinking the working directory had changed[1], so\n> it was changed to \"Preparing...\". The reason for keeping that message\n> (rather than dropping it outright) was to provide context to messages\n> printed after it, especially messages such as \"HEAD is now at...\"\n> which might otherwise confuse the reader into thinking that HEAD in\n> the current worktree changed rather than HEAD in the new\n> worktree[2,3].\n\nThanks for the background!  In that light, since we're already\ncustomizing the \"HEAD is now at...\" message, is it worth dropping the\nmessage now, maybe using something like \"Worktree HEAD is now at ...\",\nor something similar?\n\nThis would loose the information about the identifier of the worktree,\nbut from a coarse look at the man page it doesn't seem like we\nadvertise that widely (The only thing related to it I could find is\n\n    If the last path components in the working tree's path is unique among\n    working trees, it can be used to identify worktrees. For example if\n    you only have two working trees, at \"/abc/def/ghi\" and \"/abc/def/ggg\",\n    then \"ghi\" or \"def/ghi\" is enough to point to the former working tree.\n\nfor which we don't need to print the identifier anywhere.  We don't\nseem to mention the case where the last part is unique, and we add a\nnumber to make the identifier unique.\n\nSo given that maybe it would even be better to hide the part about the\nidentifier, as it seems more like an implementation detail than\nrelevant to the end user?\n\n> [1]: https://public-inbox.org/git/55A8F4B1.9060304@drmicha.warpmail.net/\n> [2]: https://public-inbox.org/git/CAPig+cRSHwmmF9cCUbRrDCCW4kvg9PeOUxP5VQpSGfxzMxHWOQ@mail.gmail.com/\n> [3]: https://public-inbox.org/git/CAPig+cSLs4-uKicVMBSKnEro_FYD722Hs1_U6qzTriM8Ciok2Q@mail.gmail.com/\n"},{"id":"338865","messageId":"CACsJy8Dp1j5GJtHGowK+Vk4KBBUtqOkTfx3U0PNN9DmKO1e-mA@mail.gmail.com","threadId":"47657","inReplyTo":"20180209112727.GG2130@hank","subject":"Re: [PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-09T12:08:22Z","receivedAt":"2018-02-09T12:09:01Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Feb 9, 2018 at 6:27 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> This would loose the information about the identifier of the worktree,\n> but from a coarse look at the man page it doesn't seem like we\n> advertise that widely\n>\n> ...\n>\n> So given that maybe it would even be better to hide the part about the\n> identifier, as it seems more like an implementation detail than\n> relevant to the end user?\n\nExactly. I'd rather hide it. I haven't found any good reason that a\nuser needs to know these IDs unless they poke into $GIT_DIR/worktrees,\nbut they should not need to.\n-- \nDuy\n"},{"id":"338982","messageId":"CACsJy8BOvU_z-uLrFmzFyryMXHNDfc_FUN_4i4NnVXWoShaBLQ@mail.gmail.com","threadId":"47657","inReplyTo":"CACsJy8Dp1j5GJtHGowK+Vk4KBBUtqOkTfx3U0PNN9DmKO1e-mA@mail.gmail.com","subject":"Re: [PATCH v2 1/3] worktree: improve message when creating a new worktree","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-10T11:20:56Z","receivedAt":"2018-02-10T11:21:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Feb 9, 2018 at 7:08 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> On Fri, Feb 9, 2018 at 6:27 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n>> This would loose the information about the identifier of the worktree,\n>> but from a coarse look at the man page it doesn't seem like we\n>> advertise that widely\n>>\n>> ...\n>>\n>> So given that maybe it would even be better to hide the part about the\n>> identifier, as it seems more like an implementation detail than\n>> relevant to the end user?\n>\n> Exactly. I'd rather hide it. I haven't found any good reason that a\n> user needs to know these IDs unless they poke into $GIT_DIR/worktrees,\n> but they should not need to.\n\nJust FYI. I mentioned elsewhere [1] the possibility of a new extended\nref syntax to refer to e.g. HEAD from a different worktree. Such\nsyntax may make use of this id (which also means we might need to give\nthe user control over these ids and not just always auto generate\nthem).\n\nBut that's for the future. If/When that thing comes, we can worry\nabout displaying id here then. For now I still think it's ok to hide\nit.\n\n[1] https://public-inbox.org/git/20180210095952.GA9035@ash/T/#u\n-- \nDuy\n"},{"id":"342052","messageId":"20180317220830.30963-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180204221305.28300-1-t.gummerer@gmail.com","subject":"[PATCH v3 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:08:26Z","receivedAt":"2018-03-17T22:05:45Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Previous rounds are at <20180121120208.12760-1-t.gummerer@gmail.com>\nand <20180204221305.28300-1-t.gummerer@gmail.com>.  Thanks Duy, Eric\nand Junio for the comments on the previous round.\n\nJunio: I know it is the rc period right now, but the topic is also\nalready queued in 'pu', so I wasn't sure if you prefer me submitting\nthis now, or after 2.17 is released.  I'm happy to resend this once\n2.17 is out if that makes it easier for you.\n\nThis round improves the end user facing messages, and factors out a\ndwim_branch function as suggested by Duy.\n\nInterdiff below:\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex ea420bb90b..b5d273751f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -304,8 +304,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -322,12 +320,12 @@ static int add_worktree(const char *path, const char *refname,\n \t\tgoto done;\n \n \tif (opts->checkout_existing_branch)\n-\t\tfprintf(stderr, _(\", checking out existing branch '%s'\"),\n+\t\tfprintf(stderr, _(\"checking out branch '%s'\"),\n \t\t\trefname);\n \telse if (opts->new_branch)\n-\t\tfprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n+\t\tfprintf(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n \n-\tfprintf(stderr, _(\", setting HEAD to %s\"),\n+\tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n \n \tstrbuf_reset(&sb);\n@@ -373,6 +371,32 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static const char *dwim_branch(const char *path, struct add_opts *opts)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\t*branch = branchname;\n+\t\topts->checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\topts->new_branch = branchname;\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(opts->new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -425,27 +449,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\tconst char *branchname = xstrndup(s, n);\n-\t\tstruct strbuf ref = STRBUF_INIT;\n-\n-\t\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n-\t\t    ref_exists(ref.buf)) {\n-\t\t\tbranch = branchname;\n-\t\t\topts.checkout_existing_branch = 1;\n-\t\t\tUNLEAK(branch);\n-\t\t} else {\n-\t\t\topts.new_branch = branchname;\n-\t\t\tif (guess_remote) {\n-\t\t\t\tstruct object_id oid;\n-\t\t\t\tconst char *remote =\n-\t\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n-\t\t\t\tif (remote)\n-\t\t\t\t\tbranch = remote;\n-\t\t\t}\n-\t\t}\n-\t\tstrbuf_release(&ref);\n+\t\tconst char *dwim_branchname = dwim_branch(path, &opts);\n+\t\tif (dwim_branchname)\n+\t\t\tbranch = dwim_branchname;\n \t}\n \n \tif (ac == 2 && !opts.new_branch && !opts.detach) {\n\nThomas Gummerer (4):\n  worktree: improve message when creating a new worktree\n  worktree: be clearer when \"add\" dwim-ery kicks in\n  worktree: factor out dwim_branch function\n  worktree: teach \"add\" to check out existing branches\n\n Documentation/git-worktree.txt |  9 +++--\n builtin/worktree.c             | 60 +++++++++++++++++++++++++---------\n t/t2025-worktree-add.sh        | 15 +++++++--\n 3 files changed, 64 insertions(+), 20 deletions(-)\n\n-- \n2.17.0.rc0.231.g781580f06\n"},{"id":"342053","messageId":"20180317220830.30963-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317220830.30963-1-t.gummerer@gmail.com","subject":"[PATCH v3 1/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:08:27Z","receivedAt":"2018-03-17T22:05:52Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following, when\n'--no-checkout' is not given:\n\n    Preparing foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nwhere the first line is written to stderr, and the second line coming\nfrom 'git reset --hard' is written to stdout, even though both lines are\nsupposed to tell the user what has happened.  In addition to someone not\nfamiliar with 'git worktree', this might seem as if the current HEAD was\nmodified, not the HEAD in the new working tree.\n\nIf the '--no-checkout' flag is given, the output of 'git worktree add'\nis just:\n\n    Preparing foo (identifier foo)\n\neven though the HEAD is set to a commit, which is just not checked out.\n\nThe identifier is also not particularly relevant for the user at the\nmoment, as it's only used internally to distinguish between different\nworktrees that have the same $(basename <path>).\n\nFix these inconsistencies, and no longer show the identifier by making\nthe 'git reset --hard' call quiet, and printing the message directly\nfrom the builtin command instead.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 13 ++++++++++---\n 1 file changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..e5d04f0b4b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -303,8 +303,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -320,10 +318,19 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n+\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n+\n+\tstrbuf_reset(&sb);\n+\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\tif (sb.len > 0)\n+\t\tfprintf(stderr, \" %s\", sb.buf);\n+\tfputc('\\n', stderr);\n+\n \tif (opts->checkout) {\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n-\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n+\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n \t\tcp.env = child_env.argv;\n \t\tret = run_command(&cp);\n \t\tif (ret)\n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342054","messageId":"20180317220830.30963-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317220830.30963-1-t.gummerer@gmail.com","subject":"[PATCH v3 2/4] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:08:28Z","receivedAt":"2018-03-17T22:05:56Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently there is no indication in the \"git worktree add\" output that\na new branch was created.  This would be especially useful information\nin the case where the dwim of \"git worktree add <path>\" kicks in, as the\nuser didn't explicitly ask for a new branch, but we create one from\nthem.\n\nPrint some additional output showing that a branch was created and the\nbranch name to help the user.\n\nThis will also be useful in the next commit, which introduces a new kind\nof dwim-ery of checking out the branch if it exists instead of refusing\nto create a new worktree in that case, and where it's nice to tell the\nuser which kind of dwim-ery kicked in.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex e5d04f0b4b..2266c132f9 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tif (opts->new_branch)\n+\t\tfprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n+\n \tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n \n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342055","messageId":"20180317220830.30963-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317220830.30963-1-t.gummerer@gmail.com","subject":"[PATCH v3 3/4] worktree: factor out dwim_branch function","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:08:29Z","receivedAt":"2018-03-17T22:06:00Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Factor out a dwim_branch function, which takes care of the dwim'ery in\n'git worktree add <path>'.  It's not too much code currently, but we're\nadding a new kind of dwim in a subsequent patch, at which point it makes\nmore sense to have it as a separate function.\n\nFactor it out now to reduce the patch noise in the next patch.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 27 +++++++++++++++++----------\n 1 file changed, 17 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 2266c132f9..52049b447a 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -367,6 +367,20 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static const char *dwim_branch(const char *path, struct add_opts *opts)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\topts->new_branch = xstrndup(s, n);\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(opts->new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -419,16 +433,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n-\t\t}\n+\t\tconst char *dwim_branchname = dwim_branch(path, &opts);\n+\t\tif (dwim_branchname)\n+\t\t\tbranch = dwim_branchname;\n \t}\n \n \tif (ac == 2 && !opts.new_branch && !opts.detach) {\n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342056","messageId":"20180317220830.30963-5-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317220830.30963-1-t.gummerer@gmail.com","subject":"[PATCH v3 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:08:30Z","receivedAt":"2018-03-17T22:06:04Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 22 +++++++++++++++++++---\n t/t2025-worktree-add.sh        | 15 ++++++++++++---\n 3 files changed, 38 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..98731b71a7 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, a worktree with a branch named after\n+`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` exists in the repository,\n+it will be checked out in the new worktree, if it's not checked out\n+anywhere else, otherwise the command will refuse to create the\n+worktree.\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 52049b447a..b5d273751f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -29,6 +29,7 @@ struct add_opts {\n \tint keep_locked;\n \tconst char *new_branch;\n \tint force_new_branch;\n+\tint checkout_existing_branch;\n };\n \n static int show_only;\n@@ -318,8 +319,11 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n-\tif (opts->new_branch)\n-\t\tfprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n+\tif (opts->checkout_existing_branch)\n+\t\tfprintf(stderr, _(\"checking out branch '%s'\"),\n+\t\t\trefname);\n+\telse if (opts->new_branch)\n+\t\tfprintf(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n \n \tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n@@ -371,7 +375,19 @@ static const char *dwim_branch(const char *path, struct add_opts *opts)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n-\topts->new_branch = xstrndup(s, n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\t*branch = branchname;\n+\t\topts->checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\topts->new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..721b0e4c26 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n+test_expect_success '\"add\" auto-vivify checks out existing branch' '\n \ttest_commit c1 &&\n \ttest_commit c2 &&\n \tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n+\tgit worktree add precious &&\n \ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+\t(\n+\t\tcd precious &&\n+\t\ttest_cmp_rev precious HEAD\n+\t)\n+'\n+\n+test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342058","messageId":"20180317222219.4940-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317220830.30963-1-t.gummerer@gmail.com","subject":"[PATCH v4 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:22:15Z","receivedAt":"2018-03-17T22:20:30Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Please ignore v3 of this series, I just noticed that I botched the\nlast commit :(  sorry about the noise.\n\nPrevious rounds (other than v3) are at <20180121120208.12760-1-t.gummerer@gmail.com>\nand <20180204221305.28300-1-t.gummerer@gmail.com>.  Thanks Duy, Eric\nand Junio for the comments on the previous round.\n\nThis round improves the end user facing messages, and factors out a\ndwim_branch function as suggested by Duy.\n\nInterdiff between this and v2 below:\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex ea420bb90b..df5c0427ba 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -304,8 +304,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -322,12 +320,12 @@ static int add_worktree(const char *path, const char *refname,\n \t\tgoto done;\n \n \tif (opts->checkout_existing_branch)\n-\t\tfprintf(stderr, _(\", checking out existing branch '%s'\"),\n+\t\tfprintf(stderr, _(\"checking out branch '%s'\"),\n \t\t\trefname);\n \telse if (opts->new_branch)\n-\t\tfprintf(stderr, _(\", creating new branch '%s'\"), opts->new_branch);\n+\t\tfprintf(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n \n-\tfprintf(stderr, _(\", setting HEAD to %s\"),\n+\tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n \n \tstrbuf_reset(&sb);\n@@ -373,6 +371,31 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static const char *dwim_branch(const char *path, struct add_opts *opts)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\topts->checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\topts->new_branch = branchname;\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(opts->new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -425,27 +448,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\tconst char *branchname = xstrndup(s, n);\n-\t\tstruct strbuf ref = STRBUF_INIT;\n-\n-\t\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n-\t\t    ref_exists(ref.buf)) {\n-\t\t\tbranch = branchname;\n-\t\t\topts.checkout_existing_branch = 1;\n-\t\t\tUNLEAK(branch);\n-\t\t} else {\n-\t\t\topts.new_branch = branchname;\n-\t\t\tif (guess_remote) {\n-\t\t\t\tstruct object_id oid;\n-\t\t\t\tconst char *remote =\n-\t\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n-\t\t\t\tif (remote)\n-\t\t\t\t\tbranch = remote;\n-\t\t\t}\n-\t\t}\n-\t\tstrbuf_release(&ref);\n+\t\tconst char *dwim_branchname = dwim_branch(path, &opts);\n+\t\tif (dwim_branchname)\n+\t\t\tbranch = dwim_branchname;\n \t}\n \n \tif (ac == 2 && !opts.new_branch && !opts.detach) {\n\nThomas Gummerer (4):\n  worktree: improve message when creating a new worktree\n  worktree: be clearer when \"add\" dwim-ery kicks in\n  worktree: factor out dwim_branch function\n  worktree: teach \"add\" to check out existing branches\n\n Documentation/git-worktree.txt |  9 ++++--\n builtin/worktree.c             | 58 ++++++++++++++++++++++++++--------\n t/t2025-worktree-add.sh        | 15 +++++++--\n 3 files changed, 64 insertions(+), 18 deletions(-)\n\n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342059","messageId":"20180317222219.4940-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-1-t.gummerer@gmail.com","subject":"[PATCH v4 1/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:22:16Z","receivedAt":"2018-03-17T22:20:32Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following, when\n'--no-checkout' is not given:\n\n    Preparing foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nwhere the first line is written to stderr, and the second line coming\nfrom 'git reset --hard' is written to stdout, even though both lines are\nsupposed to tell the user what has happened.  In addition to someone not\nfamiliar with 'git worktree', this might seem as if the current HEAD was\nmodified, not the HEAD in the new working tree.\n\nIf the '--no-checkout' flag is given, the output of 'git worktree add'\nis just:\n\n    Preparing foo (identifier foo)\n\neven though the HEAD is set to a commit, which is just not checked out.\n\nThe identifier is also not particularly relevant for the user at the\nmoment, as it's only used internally to distinguish between different\nworktrees that have the same $(basename <path>).\n\nFix these inconsistencies, and no longer show the identifier by making\nthe 'git reset --hard' call quiet, and printing the message directly\nfrom the builtin command instead.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 13 ++++++++++---\n 1 file changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..e5d04f0b4b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -303,8 +303,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -320,10 +318,19 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n+\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n+\n+\tstrbuf_reset(&sb);\n+\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\tif (sb.len > 0)\n+\t\tfprintf(stderr, \" %s\", sb.buf);\n+\tfputc('\\n', stderr);\n+\n \tif (opts->checkout) {\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n-\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n+\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n \t\tcp.env = child_env.argv;\n \t\tret = run_command(&cp);\n \t\tif (ret)\n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342060","messageId":"20180317222219.4940-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-1-t.gummerer@gmail.com","subject":"[PATCH v4 3/4] worktree: factor out dwim_branch function","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:22:18Z","receivedAt":"2018-03-17T22:20:37Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Factor out a dwim_branch function, which takes care of the dwim'ery in\n'git worktree add <path>'.  It's not too much code currently, but we're\nadding a new kind of dwim in a subsequent patch, at which point it makes\nmore sense to have it as a separate function.\n\nFactor it out now to reduce the patch noise in the next patch.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 27 +++++++++++++++++----------\n 1 file changed, 17 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 2266c132f9..52049b447a 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -367,6 +367,20 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static const char *dwim_branch(const char *path, struct add_opts *opts)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\topts->new_branch = xstrndup(s, n);\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(opts->new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -419,16 +433,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n-\t\t}\n+\t\tconst char *dwim_branchname = dwim_branch(path, &opts);\n+\t\tif (dwim_branchname)\n+\t\t\tbranch = dwim_branchname;\n \t}\n \n \tif (ac == 2 && !opts.new_branch && !opts.detach) {\n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342061","messageId":"20180317222219.4940-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-1-t.gummerer@gmail.com","subject":"[PATCH v4 2/4] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:22:17Z","receivedAt":"2018-03-17T22:20:40Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently there is no indication in the \"git worktree add\" output that\na new branch was created.  This would be especially useful information\nin the case where the dwim of \"git worktree add <path>\" kicks in, as the\nuser didn't explicitly ask for a new branch, but we create one from\nthem.\n\nPrint some additional output showing that a branch was created and the\nbranch name to help the user.\n\nThis will also be useful in the next commit, which introduces a new kind\nof dwim-ery of checking out the branch if it exists instead of refusing\nto create a new worktree in that case, and where it's nice to tell the\nuser which kind of dwim-ery kicked in.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex e5d04f0b4b..2266c132f9 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tif (opts->new_branch)\n+\t\tfprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n+\n \tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n \n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342062","messageId":"20180317222219.4940-5-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-1-t.gummerer@gmail.com","subject":"[PATCH v4 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-17T22:22:19Z","receivedAt":"2018-03-17T22:20:41Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 21 ++++++++++++++++++---\n t/t2025-worktree-add.sh        | 15 ++++++++++++---\n 3 files changed, 37 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..98731b71a7 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, a worktree with a branch named after\n+`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` exists in the repository,\n+it will be checked out in the new worktree, if it's not checked out\n+anywhere else, otherwise the command will refuse to create the\n+worktree.\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 52049b447a..df5c0427ba 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -29,6 +29,7 @@ struct add_opts {\n \tint keep_locked;\n \tconst char *new_branch;\n \tint force_new_branch;\n+\tint checkout_existing_branch;\n };\n \n static int show_only;\n@@ -318,8 +319,11 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n-\tif (opts->new_branch)\n-\t\tfprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n+\tif (opts->checkout_existing_branch)\n+\t\tfprintf(stderr, _(\"checking out branch '%s'\"),\n+\t\t\trefname);\n+\telse if (opts->new_branch)\n+\t\tfprintf(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n \n \tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n@@ -371,7 +375,18 @@ static const char *dwim_branch(const char *path, struct add_opts *opts)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n-\topts->new_branch = xstrndup(s, n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\topts->checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\topts->new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..721b0e4c26 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n+test_expect_success '\"add\" auto-vivify checks out existing branch' '\n \ttest_commit c1 &&\n \ttest_commit c2 &&\n \tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n+\tgit worktree add precious &&\n \ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+\t(\n+\t\tcd precious &&\n+\t\ttest_cmp_rev precious HEAD\n+\t)\n+'\n+\n+test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.17.0.rc0.231.g781580f06\n\n"},{"id":"342068","messageId":"xmqqfu4yxmb1.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"20180317220830.30963-1-t.gummerer@gmail.com","subject":"Re: [PATCH v3 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-03-18T00:24:50Z","receivedAt":"2018-03-18T00:24:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Gummerer <t.gummerer@gmail.com> writes:\n\n> Previous rounds are at <20180121120208.12760-1-t.gummerer@gmail.com>\n> and <20180204221305.28300-1-t.gummerer@gmail.com>.  Thanks Duy, Eric\n> and Junio for the comments on the previous round.\n>\n> Junio: I know it is the rc period right now, but the topic is also\n> already queued in 'pu', so I wasn't sure if you prefer me submitting\n> this now, or after 2.17 is released.  I'm happy to resend this once\n> 2.17 is out if that makes it easier for you.\n\nMail archives would not forget messages easily, so it is OK if you\nsent early.  \n\nYou just need to set expectations low enough, though ;-) Topics that\nare not in 'next' before -rc1 is tagged will not be in the upcoming\nrelease unless there is an extraordinary reason, and reviews,\nreplacing in 'pu', and advancing topics to 'next' will all get lower\npriority than keeping an eye on breakages in what is already in\n'master' until the final.\n\n"},{"id":"342205","messageId":"CACsJy8DvUB7Sv6m384ccgDPnMnFfD80W5EZ=Pbkj8cyhFO_OqA@mail.gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-2-t.gummerer@gmail.com","subject":"Re: [PATCH v4 1/4] worktree: improve message when creating a new worktree","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-19T17:11:39Z","receivedAt":"2018-03-19T17:12:25Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sat, Mar 17, 2018 at 11:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently 'git worktree add' produces output like the following, when\n> '--no-checkout' is not given:\n>\n>     Preparing foo (identifier foo)\n>     HEAD is now at 26da330922 <title>\n>\n> where the first line is written to stderr, and the second line coming\n> from 'git reset --hard' is written to stdout, even though both lines are\n> supposed to tell the user what has happened.  In addition to someone not\n> familiar with 'git worktree', this might seem as if the current HEAD was\n> modified, not the HEAD in the new working tree.\n>\n> If the '--no-checkout' flag is given, the output of 'git worktree add'\n> is just:\n>\n>     Preparing foo (identifier foo)\n>\n> even though the HEAD is set to a commit, which is just not checked out.\n>\n> The identifier is also not particularly relevant for the user at the\n> moment, as it's only used internally to distinguish between different\n> worktrees that have the same $(basename <path>).\n>\n> Fix these inconsistencies, and no longer show the identifier by making\n> the 'git reset --hard' call quiet, and printing the message directly\n> from the builtin command instead.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n>  builtin/worktree.c | 13 ++++++++++---\n>  1 file changed, 10 insertions(+), 3 deletions(-)\n>\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> index 7cef5b120b..e5d04f0b4b 100644\n> --- a/builtin/worktree.c\n> +++ b/builtin/worktree.c\n> @@ -303,8 +303,6 @@ static int add_worktree(const char *path, const char *refname,\n>         strbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n>         write_file(sb.buf, \"../..\");\n>\n> -       fprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n> -\n>         argv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n>         argv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n>         cp.git_cmd = 1;\n> @@ -320,10 +318,19 @@ static int add_worktree(const char *path, const char *refname,\n>         if (ret)\n>                 goto done;\n>\n> +       fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n\nWe use the term \"working tree\" for UI and documents. \"worktree\" is\nonly used in code comments and stuff.\n\n> +               find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> +\n> +       strbuf_reset(&sb);\n> +       pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n> +       if (sb.len > 0)\n> +               fprintf(stderr, \" %s\", sb.buf);\n> +       fputc('\\n', stderr);\n> +\n>         if (opts->checkout) {\n>                 cp.argv = NULL;\n>                 argv_array_clear(&cp.args);\n> -               argv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n> +               argv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n>                 cp.env = child_env.argv;\n>                 ret = run_command(&cp);\n>                 if (ret)\n> --\n> 2.17.0.rc0.231.g781580f06\n>\n-- \nDuy\n"},{"id":"342251","messageId":"xmqqpo40uebt.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"CACsJy8DvUB7Sv6m384ccgDPnMnFfD80W5EZ=Pbkj8cyhFO_OqA@mail.gmail.com","subject":"Re: [PATCH v4 1/4] worktree: improve message when creating a new worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-03-19T18:09:58Z","receivedAt":"2018-03-19T20:46:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n>> @@ -320,10 +318,19 @@ static int add_worktree(const char *path, const char *refname,\n>>         if (ret)\n>>                 goto done;\n>>\n>> +       fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n>\n> We use the term \"working tree\" for UI and documents. \"worktree\" is\n> only used in code comments and stuff.\n\nHmph, that is a bit different from what I recall.  \"working tree\" is\nthe phrase we have used and we still use to refer to those things\nthat are checked out (as opposed to the in-repo data).  We say\n\"worktree\" when we want to stress the fact that we are talking about\na single instance among possibly multiple instances of the \"working\ntree\" that are associated to a single repository.\n\nTechnically speaking, the traditional \"working tree\" is everything\nin the directory immediately above \".git/\" plus \".git/index\"; a\nsingle \"worktree\" consists of a bit more, as we have to count per\nworktree states like .git/rebase-apply/ and .git/refs/bisect/ as\npart of it.\n\nAnd from that point of view, HEAD is one of those per worktree\nstates, so...\n"},{"id":"342294","messageId":"CAPig+cT8i9L9kbhx=b0sG4_QYNdoEDPW-1xypM9xzBqPmqR__Q@mail.gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-2-t.gummerer@gmail.com","subject":"Re: [PATCH v4 1/4] worktree: improve message when creating a new worktree","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-20T06:37:05Z","receivedAt":"2018-03-20T06:37:15Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> [...]\n> Fix these inconsistencies, and no longer show the identifier by making\n> the 'git reset --hard' call quiet, and printing the message directly\n> from the builtin command instead.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -303,8 +303,6 @@ static int add_worktree(const char *path, const char *refname,\n>         strbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n>         write_file(sb.buf, \"../..\");\n>\n> -       fprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n\nA minor regression with this change is that error messages from\ngit-update-ref or git-symbolic-ref -- which could be emitted after\nthis point but before the new \"worktree HEAD is now at...\" message --\nare now somewhat orphaned. I'm not sure that it matters, though.\n\n>         argv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n>         argv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n>         cp.git_cmd = 1;\n> @@ -320,10 +318,19 @@ static int add_worktree(const char *path, const char *refname,\n> +       fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n> +               find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n\nI wonder if this should say \"new worktree HEAD is now at...\" to\nclearly indicate that it is talking about HEAD in the _new_ worktree,\nnot HEAD in the current worktree.\n\n> +       strbuf_reset(&sb);\n> +       pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n> +       if (sb.len > 0)\n> +               fprintf(stderr, \" %s\", sb.buf);\n> +       fputc('\\n', stderr);\n"},{"id":"342295","messageId":"CAPig+cSaA+N0jWfbWccH45kVzz-0g4hTkg-KwgwTTTPL8pixuw@mail.gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-3-t.gummerer@gmail.com","subject":"Re: [PATCH v4 2/4] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-20T06:40:01Z","receivedAt":"2018-03-20T06:40:07Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently there is no indication in the \"git worktree add\" output that\n> a new branch was created.  This would be especially useful information\n> in the case where the dwim of \"git worktree add <path>\" kicks in, as the\n> user didn't explicitly ask for a new branch, but we create one from\n> them.\n>\n> Print some additional output showing that a branch was created and the\n> branch name to help the user.\n\nGood idea.\n\n> This will also be useful in the next commit, which introduces a new kind\n> of dwim-ery of checking out the branch if it exists instead of refusing\n> to create a new worktree in that case, and where it's nice to tell the\n> user which kind of dwim-ery kicked in.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n"},{"id":"342296","messageId":"CAPig+cSsqqn+Wg6DEJRSge9mYqb1_jPXy5ORryrdA6+Omxne1A@mail.gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-3-t.gummerer@gmail.com","subject":"Re: [PATCH v4 2/4] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-20T07:26:49Z","receivedAt":"2018-03-20T07:26:55Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently there is no indication in the \"git worktree add\" output that\n> a new branch was created.  This would be especially useful information\n> in the case where the dwim of \"git worktree add <path>\" kicks in, as the\n> user didn't explicitly ask for a new branch, but we create one from\n> them.\n>\n> Print some additional output showing that a branch was created and the\n> branch name to help the user.\n> [...]\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n> +       if (opts->new_branch)\n> +               fprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n> +\n>         fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n>                 find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n\nThe \"creating\" message is missing a newline, which results in rather\nugly output:\n\n    creating new branch 'foo'worktree HEAD is now at ...\n"},{"id":"342297","messageId":"CAPig+cQPhXxVswMbD5HsUJpa9AHfet4zFb+MV3FT_-CuZP8+gw@mail.gmail.com","threadId":"47657","inReplyTo":"CAPig+cSsqqn+Wg6DEJRSge9mYqb1_jPXy5ORryrdA6+Omxne1A@mail.gmail.com","subject":"Re: [PATCH v4 2/4] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-20T07:32:02Z","receivedAt":"2018-03-20T07:32:08Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Mar 20, 2018 at 3:26 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n>> Currently there is no indication in the \"git worktree add\" output that\n>> a new branch was created.  This would be especially useful information\n>> in the case where the dwim of \"git worktree add <path>\" kicks in, as the\n>> user didn't explicitly ask for a new branch, but we create one from\n>> them.\n>>\n>> Print some additional output showing that a branch was created and the\n>> branch name to help the user.\n>> [...]\n>> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n>> ---\n>> diff --git a/builtin/worktree.c b/builtin/worktree.c\n>> @@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n>> +       if (opts->new_branch)\n>> +               fprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n>> +\n>>         fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n>>                 find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n>\n> The \"creating\" message is missing a newline, which results in rather\n> ugly output:\n>\n>     creating new branch 'foo'worktree HEAD is now at ...\n\nAlso, I believe that the agreement[1] was that this message should say\nmerely \"creating branch\", not \"creating _new_ branch\". And, indeed,\npatch 4/4 stealthily drops \"new\" from the message, but it really ought\nto be introduced with correct text in this patch, not fixed by 4/4.\n\n[1]: https://public-inbox.org/git/xmqqh8qv9ojb.fsf@gitster-ct.c.googlers.com/\n"},{"id":"342298","messageId":"CAPig+cToFeHniMmqhx8HZrtrzqyht=1a2zbx1yQar=WVt2yF1g@mail.gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-5-t.gummerer@gmail.com","subject":"Re: [PATCH v4 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-20T08:02:45Z","receivedAt":"2018-03-20T08:02:58Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> [...]\n> However we can do a little better than that, and check the branch out if\n> it is not checked out anywhere else.  This will help users who just want\n> to check an existing branch out into a new worktree, and save a few\n> keystrokes.\n> [...]\n> We will still 'die()' if the branch is checked out in another worktree,\n> unless the --force flag is passed.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\n> @@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n>  If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n> -then, as a convenience, a new branch based at HEAD is created automatically,\n> -as if `-b $(basename <path>)` was specified.\n> +then, as a convenience, a worktree with a branch named after\n> +`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n> +doesn't exist, a new branch based on HEAD is automatically created as\n> +if `-b <branch>` was given.  If `<branch>` exists in the repository,\n> +it will be checked out in the new worktree, if it's not checked out\n> +anywhere else, otherwise the command will refuse to create the\n> +worktree.\n\nShould this mention --force?\n\n    ... refuse to create the worktree (unless --force is used).\n\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -29,6 +29,7 @@ struct add_opts {\n>         int keep_locked;\n>         const char *new_branch;\n>         int force_new_branch;\n> +       int checkout_existing_branch;\n\nAs 'force_new_branch' and 'checkout_existing_branch' are mutually\nexclusive, I wonder if they should be combined into an enum to make it\neasier to reason about.\n\n> @@ -318,8 +319,11 @@ static int add_worktree(const char *path, const char *refname,\n> -       if (opts->new_branch)\n> -               fprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n> +       if (opts->checkout_existing_branch)\n> +               fprintf(stderr, _(\"checking out branch '%s'\"),\n> +                       refname);\n\nAs with \"creating branch\" in 2/4, \"checking out branch...\" here is\nmissing a newline.\n\n> +       else if (opts->new_branch)\n> +               fprintf(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n>\n>         fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n>                 find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> @@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n> -test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n> +test_expect_success '\"add\" auto-vivify checks out existing branch' '\n>         test_commit c1 &&\n>         test_commit c2 &&\n>         git branch precious HEAD~1 &&\n> -       test_must_fail git worktree add precious &&\n> +       git worktree add precious &&\n>         test_cmp_rev HEAD~1 precious &&\n> -       test_path_is_missing precious\n> +       (\n> +               cd precious &&\n> +               test_cmp_rev precious HEAD\n> +       )\n> +'\n\nThis test is no longer checking auto-vivification (\"bringing a new\nbranch to life automatically\"), but rather branch name inference, so\nthe title is now misleading. Perhaps retitle it to '\"add\" checks out\nexisting branch of dwim'd name' or something.\n\n(The name \"precious\" is also now misleading since it's no longer\nchecking that a precious branch does not get clobbered, however,\nchanging the name would make the diff unnecessarily noisy, so it's\nprobably okay as is.)\n\n> +test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n> +       git checkout -b test-branch &&\n> +       test_must_fail git worktree add test-branch &&\n> +       test_path_is_missing test-branch\n>  '\n\nShould we also have a corresponding test that this \"fail\" can be\noverridden by --force? (I realize that --force is tested elsewhere,\nbut only with an explicitly-provided branch name, whereas this dwims\nthe branch name.)\n"},{"id":"342841","messageId":"20180324203445.GI2224@hank","threadId":"47657","inReplyTo":"CAPig+cT8i9L9kbhx=b0sG4_QYNdoEDPW-1xypM9xzBqPmqR__Q@mail.gmail.com","subject":"Re: [PATCH v4 1/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-24T20:34:45Z","receivedAt":"2018-03-24T20:31:30Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 03/20, Eric Sunshine wrote:\n> On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > [...]\n> > Fix these inconsistencies, and no longer show the identifier by making\n> > the 'git reset --hard' call quiet, and printing the message directly\n> > from the builtin command instead.\n> >\n> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> > ---\n> > diff --git a/builtin/worktree.c b/builtin/worktree.c\n> > @@ -303,8 +303,6 @@ static int add_worktree(const char *path, const char *refname,\n> >         strbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n> >         write_file(sb.buf, \"../..\");\n> >\n> > -       fprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n> \n> A minor regression with this change is that error messages from\n> git-update-ref or git-symbolic-ref -- which could be emitted after\n> this point but before the new \"worktree HEAD is now at...\" message --\n> are now somewhat orphaned. I'm not sure that it matters, though.\n\nIf those commands fail, we would now not print the \"worktree HEAD is\nnow at...\" message, but go directly to \"done\", and clean up the\nworking tree.\n\nSo while we no longer emit the \"Preparing worktree\" header, the user\nshould still be aware that they are creating a new worktree, and that\nthe error happened while creating a new worktree.  From a (admittedly\nvery quick) look the error messages would all make sense in this\ncontext, without an additional message.\n\nPrinting the \"worktree HEAD is now at ...\" message before that\nwouldn't make much sense, as we may not even have a new working tree\nat the end.  We could add the message back, but that would also put us\nback at three lines of output.  I think I prefer the more concise\nversion here in the normal case, and I think we can live with the\nslight regression.  But if others have a strong preference for the\ncurrent way I'm happy to add that message back.\n\n> >         argv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n> >         argv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n> >         cp.git_cmd = 1;\n> > @@ -320,10 +318,19 @@ static int add_worktree(const char *path, const char *refname,\n> > +       fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n> > +               find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> \n> I wonder if this should say \"new worktree HEAD is now at...\" to\n> clearly indicate that it is talking about HEAD in the _new_ worktree,\n> not HEAD in the current worktree.\n\nYeah I aggree that's nicer.  Will change.\n\n> > +       strbuf_reset(&sb);\n> > +       pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n> > +       if (sb.len > 0)\n> > +               fprintf(stderr, \" %s\", sb.buf);\n> > +       fputc('\\n', stderr);\n"},{"id":"342842","messageId":"20180324203527.GJ2224@hank","threadId":"47657","inReplyTo":"CAPig+cQPhXxVswMbD5HsUJpa9AHfet4zFb+MV3FT_-CuZP8+gw@mail.gmail.com","subject":"Re: [PATCH v4 2/4] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-24T20:35:27Z","receivedAt":"2018-03-24T20:32:11Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 03/20, Eric Sunshine wrote:\n> On Tue, Mar 20, 2018 at 3:26 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> > On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> >> Currently there is no indication in the \"git worktree add\" output that\n> >> a new branch was created.  This would be especially useful information\n> >> in the case where the dwim of \"git worktree add <path>\" kicks in, as the\n> >> user didn't explicitly ask for a new branch, but we create one from\n> >> them.\n> >>\n> >> Print some additional output showing that a branch was created and the\n> >> branch name to help the user.\n> >> [...]\n> >> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> >> ---\n> >> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> >> @@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n> >> +       if (opts->new_branch)\n> >> +               fprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n> >> +\n> >>         fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n> >>                 find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> >\n> > The \"creating\" message is missing a newline, which results in rather\n> > ugly output:\n> >\n> >     creating new branch 'foo'worktree HEAD is now at ...\n> \n> Also, I believe that the agreement[1] was that this message should say\n> merely \"creating branch\", not \"creating _new_ branch\". And, indeed,\n> patch 4/4 stealthily drops \"new\" from the message, but it really ought\n> to be introduced with correct text in this patch, not fixed by 4/4.\n\nAh yeah thanks for catching those, will fix.\n\n> [1]: https://public-inbox.org/git/xmqqh8qv9ojb.fsf@gitster-ct.c.googlers.com/\n"},{"id":"342853","messageId":"20180324210020.GK2224@hank","threadId":"47657","inReplyTo":"CAPig+cToFeHniMmqhx8HZrtrzqyht=1a2zbx1yQar=WVt2yF1g@mail.gmail.com","subject":"Re: [PATCH v4 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-24T21:00:20Z","receivedAt":"2018-03-24T20:57:04Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 03/20, Eric Sunshine wrote:\n> On Sat, Mar 17, 2018 at 6:22 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > [...]\n> > However we can do a little better than that, and check the branch out if\n> > it is not checked out anywhere else.  This will help users who just want\n> > to check an existing branch out into a new worktree, and save a few\n> > keystrokes.\n> > [...]\n> > We will still 'die()' if the branch is checked out in another worktree,\n> > unless the --force flag is passed.\n> >\n> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> > ---\n> > diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\n> > @@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n> >  If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n> > -then, as a convenience, a new branch based at HEAD is created automatically,\n> > -as if `-b $(basename <path>)` was specified.\n> > +then, as a convenience, a worktree with a branch named after\n> > +`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n> > +doesn't exist, a new branch based on HEAD is automatically created as\n> > +if `-b <branch>` was given.  If `<branch>` exists in the repository,\n> > +it will be checked out in the new worktree, if it's not checked out\n> > +anywhere else, otherwise the command will refuse to create the\n> > +worktree.\n> \n> Should this mention --force?\n> \n>     ... refuse to create the worktree (unless --force is used).\n\nYeah, will add.\n\n> > diff --git a/builtin/worktree.c b/builtin/worktree.c\n> > @@ -29,6 +29,7 @@ struct add_opts {\n> >         int keep_locked;\n> >         const char *new_branch;\n> >         int force_new_branch;\n> > +       int checkout_existing_branch;\n> \n> As 'force_new_branch' and 'checkout_existing_branch' are mutually\n> exclusive, I wonder if they should be combined into an enum to make it\n> easier to reason about.\n\nI gave this a try, but I'm not sure the end result is nicer.  The\nproblem is that 'new_branch' and 'force_new_branch' both are mutually\nexclusive with 'checkout_existing_branch', but 'force_new_branch' is a\n\"superset\" of 'new_branch'.\n\nI can't seem to think of a nice way to encode that, especially not\nwithout duplicating information we're already carrying in\n'new_branch'.  Looking at the code however I see that\n'force_new_branch' is already only duplicating information that we\nalready have in a variable in the same function.  I think just\nremoving that duplication and keeping the 'checkout_existing_branch'\nvariable in the 'add_opts' would make most sense.\n\n> > @@ -318,8 +319,11 @@ static int add_worktree(const char *path, const char *refname,\n> > -       if (opts->new_branch)\n> > -               fprintf(stderr, _(\"creating new branch '%s'\"), opts->new_branch);\n> > +       if (opts->checkout_existing_branch)\n> > +               fprintf(stderr, _(\"checking out branch '%s'\"),\n> > +                       refname);\n> \n> As with \"creating branch\" in 2/4, \"checking out branch...\" here is\n> missing a newline.\n\nThanks will add.\n\n> > +       else if (opts->new_branch)\n> > +               fprintf(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n> >\n> >         fprintf(stderr, _(\"worktree HEAD is now at %s\"),\n> >                 find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> > diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> > @@ -198,13 +198,22 @@ test_expect_success '\"add\" with <branch> omitted' '\n> > -test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n> > +test_expect_success '\"add\" auto-vivify checks out existing branch' '\n> >         test_commit c1 &&\n> >         test_commit c2 &&\n> >         git branch precious HEAD~1 &&\n> > -       test_must_fail git worktree add precious &&\n> > +       git worktree add precious &&\n> >         test_cmp_rev HEAD~1 precious &&\n> > -       test_path_is_missing precious\n> > +       (\n> > +               cd precious &&\n> > +               test_cmp_rev precious HEAD\n> > +       )\n> > +'\n> \n> This test is no longer checking auto-vivification (\"bringing a new\n> branch to life automatically\"), but rather branch name inference, so\n> the title is now misleading. Perhaps retitle it to '\"add\" checks out\n> existing branch of dwim'd name' or something.\n> \n> (The name \"precious\" is also now misleading since it's no longer\n> checking that a precious branch does not get clobbered, however,\n> changing the name would make the diff unnecessarily noisy, so it's\n> probably okay as is.)\n\nGood point.  I can add an additional patch with that rename, so the\nchanges here stay more obvious, but the end result would still end up\nless confusing.\n\n> > +test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n> > +       git checkout -b test-branch &&\n> > +       test_must_fail git worktree add test-branch &&\n> > +       test_path_is_missing test-branch\n> >  '\n> \n> Should we also have a corresponding test that this \"fail\" can be\n> overridden by --force? (I realize that --force is tested elsewhere,\n> but only with an explicitly-provided branch name, whereas this dwims\n> the branch name.)\n\nYes, will add a test.  Thanks for your review!\n"},{"id":"342884","messageId":"20180325134947.25828-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180317222219.4940-1-t.gummerer@gmail.com","subject":"[PATCH v5 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-25T13:49:41Z","receivedAt":"2018-03-25T13:46:34Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Thanks Eric for the review of the previous round and Duy and Junio for\nadditional comments.\n\nPrevious rounds are at <20180121120208.12760-1-t.gummerer@gmail.com>,\n<20180204221305.28300-1-t.gummerer@gmail.com>,\n<20180317220830.30963-1-t.gummerer@gmail.com> and\n<20180317222219.4940-1-t.gummerer@gmail.com>.\n\nThis round should address all of Eric's comments from the previous round.\n\nAs explained in more detail in a reply to the review comment directly,\nI did not add an enum to 'struct add_opts', for 'force_new_branch' and\n'checkout_existing_branch', but instead removed 'force_new_branch'\nfrom the struct as it's not required.\n\nThe rest of the updates are mainly in the user facing messages,\ndocumentation and one added test.\n\nInterdiff below:\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 98731b71a7..eaa6bf713f 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -67,7 +67,7 @@ doesn't exist, a new branch based on HEAD is automatically created as\n if `-b <branch>` was given.  If `<branch>` exists in the repository,\n it will be checked out in the new worktree, if it's not checked out\n anywhere else, otherwise the command will refuse to create the\n-worktree.\n+worktree (unless `--force` is used).\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex df5c0427ba..895838b943 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -28,7 +28,6 @@ struct add_opts {\n \tint checkout;\n \tint keep_locked;\n \tconst char *new_branch;\n-\tint force_new_branch;\n \tint checkout_existing_branch;\n };\n \n@@ -320,12 +319,12 @@ static int add_worktree(const char *path, const char *refname,\n \t\tgoto done;\n \n \tif (opts->checkout_existing_branch)\n-\t\tfprintf(stderr, _(\"checking out branch '%s'\"),\n-\t\t\trefname);\n+\t\tfprintf_ln(stderr, _(\"checking out branch '%s'\"),\n+\t\t\t   refname);\n \telse if (opts->new_branch)\n-\t\tfprintf(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n+\t\tfprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n \n-\tfprintf(stderr, _(\"worktree HEAD is now at %s\"),\n+\tfprintf(stderr, _(\"new worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n \n \tstrbuf_reset(&sb);\n@@ -434,8 +433,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (!strcmp(branch, \"-\"))\n \t\tbranch = \"@{-1}\";\n \n-\topts.force_new_branch = !!new_branch_force;\n-\tif (opts.force_new_branch) {\n+\tif (new_branch_force) {\n \t\tstruct strbuf symref = STRBUF_INIT;\n \n \t\topts.new_branch = new_branch_force;\n@@ -472,7 +470,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n-\t\tif (opts.force_new_branch)\n+\t\tif (new_branch_force)\n \t\t\targv_array_push(&cp.args, \"--force\");\n \t\targv_array_push(&cp.args, opts.new_branch);\n \t\targv_array_push(&cp.args, branch);\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 721b0e4c26..fb99f4c46f 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,15 +198,15 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify checks out existing branch' '\n+test_expect_success '\"add\" checks out existing branch of dwimd name' '\n \ttest_commit c1 &&\n \ttest_commit c2 &&\n-\tgit branch precious HEAD~1 &&\n-\tgit worktree add precious &&\n-\ttest_cmp_rev HEAD~1 precious &&\n+\tgit branch dwim HEAD~1 &&\n+\tgit worktree add dwim &&\n+\ttest_cmp_rev HEAD~1 dwim &&\n \t(\n-\t\tcd precious &&\n-\t\ttest_cmp_rev precious HEAD\n+\t\tcd dwim &&\n+\t\ttest_cmp_rev dwim HEAD\n \t)\n '\n \n@@ -216,6 +216,10 @@ test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n \ttest_path_is_missing test-branch\n '\n \n+test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n+\tgit worktree add --force test-branch\n+'\n+\n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n \tgit worktree add --detach mish/mash &&\n \ttest_must_fail git rev-parse mash -- &&\n\nThomas Gummerer (6):\n  worktree: improve message when creating a new worktree\n  worktree: be clearer when \"add\" dwim-ery kicks in\n  worktree: remove force_new_branch from struct add_opts\n  worktree: factor out dwim_branch function\n  worktree: teach \"add\" to check out existing branches\n  t2025: rename now outdated branch name\n\n Documentation/git-worktree.txt |  9 ++++--\n builtin/worktree.c             | 64 +++++++++++++++++++++++++++++++-----------\n t/t2025-worktree-add.sh        | 23 +++++++++++----\n 3 files changed, 72 insertions(+), 24 deletions(-)\n\n-- \n2.16.1.77.g8685934aa2\n\n"},{"id":"342885","messageId":"20180325134947.25828-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"[PATCH v5 1/6] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-25T13:49:42Z","receivedAt":"2018-03-25T13:46:37Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following, when\n'--no-checkout' is not given:\n\n    Preparing foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nwhere the first line is written to stderr, and the second line coming\nfrom 'git reset --hard' is written to stdout, even though both lines are\nsupposed to tell the user what has happened.  In addition to someone not\nfamiliar with 'git worktree', this might seem as if the current HEAD was\nmodified, not the HEAD in the new working tree.\n\nIf the '--no-checkout' flag is given, the output of 'git worktree add'\nis just:\n\n    Preparing foo (identifier foo)\n\neven though the HEAD is set to a commit, which is just not checked out.\n\nThe identifier is also not particularly relevant for the user at the\nmoment, as it's only used internally to distinguish between different\nworktrees that have the same $(basename <path>).\n\nFix these inconsistencies, and no longer show the identifier by making\nthe 'git reset --hard' call quiet, and printing the message directly\nfrom the builtin command instead.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 13 ++++++++++---\n 1 file changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..535734cc7f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -303,8 +303,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -320,10 +318,19 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tfprintf(stderr, _(\"new worktree HEAD is now at %s\"),\n+\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n+\n+\tstrbuf_reset(&sb);\n+\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\tif (sb.len > 0)\n+\t\tfprintf(stderr, \" %s\", sb.buf);\n+\tfputc('\\n', stderr);\n+\n \tif (opts->checkout) {\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n-\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n+\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n \t\tcp.env = child_env.argv;\n \t\tret = run_command(&cp);\n \t\tif (ret)\n-- \n2.16.1.77.g8685934aa2\n\n"},{"id":"342886","messageId":"20180325134947.25828-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"[PATCH v5 2/6] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-25T13:49:43Z","receivedAt":"2018-03-25T13:46:41Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently there is no indication in the \"git worktree add\" output that\na new branch was created.  This would be especially useful information\nin the case where the dwim of \"git worktree add <path>\" kicks in, as the\nuser didn't explicitly ask for a new branch, but we create one from\nthem.\n\nPrint some additional output showing that a branch was created and the\nbranch name to help the user.\n\nThis will also be useful in the next commit, which introduces a new kind\nof dwim-ery of checking out the branch if it exists instead of refusing\nto create a new worktree in that case, and where it's nice to tell the\nuser which kind of dwim-ery kicked in.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 535734cc7f..a082230b6c 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tif (opts->new_branch)\n+\t\tfprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n+\n \tfprintf(stderr, _(\"new worktree HEAD is now at %s\"),\n \t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n \n-- \n2.16.1.77.g8685934aa2\n\n"},{"id":"342887","messageId":"20180325134947.25828-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"[PATCH v5 3/6] worktree: remove force_new_branch from struct add_opts","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-25T13:49:44Z","receivedAt":"2018-03-25T13:46:44Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"The 'force_new_branch' flag in 'struct add_opts' is only used inside the\nadd function, where we already have the same information stored in the\n'new_branch_force' variable.  Avoid that unnecessary duplication.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 6 ++----\n 1 file changed, 2 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex a082230b6c..1e4a919a00 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -28,7 +28,6 @@ struct add_opts {\n \tint checkout;\n \tint keep_locked;\n \tconst char *new_branch;\n-\tint force_new_branch;\n };\n \n static int show_only;\n@@ -405,8 +404,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (!strcmp(branch, \"-\"))\n \t\tbranch = \"@{-1}\";\n \n-\topts.force_new_branch = !!new_branch_force;\n-\tif (opts.force_new_branch) {\n+\tif (new_branch_force) {\n \t\tstruct strbuf symref = STRBUF_INIT;\n \n \t\topts.new_branch = new_branch_force;\n@@ -450,7 +448,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n-\t\tif (opts.force_new_branch)\n+\t\tif (new_branch_force)\n \t\t\targv_array_push(&cp.args, \"--force\");\n \t\targv_array_push(&cp.args, opts.new_branch);\n \t\targv_array_push(&cp.args, branch);\n-- \n2.16.1.77.g8685934aa2\n\n"},{"id":"342888","messageId":"20180325134947.25828-5-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"[PATCH v5 4/6] worktree: factor out dwim_branch function","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-25T13:49:45Z","receivedAt":"2018-03-25T13:46:46Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Factor out a dwim_branch function, which takes care of the dwim'ery in\n'git worktree add <path>'.  It's not too much code currently, but we're\nadding a new kind of dwim in a subsequent patch, at which point it makes\nmore sense to have it as a separate function.\n\nFactor it out now to reduce the patch noise in the next patch.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 27 +++++++++++++++++----------\n 1 file changed, 17 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 1e4a919a00..c296c3eacb 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -366,6 +366,20 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static const char *dwim_branch(const char *path, struct add_opts *opts)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\topts->new_branch = xstrndup(s, n);\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(opts->new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -417,16 +431,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !opts.new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n-\t\t}\n+\t\tconst char *dwim_branchname = dwim_branch(path, &opts);\n+\t\tif (dwim_branchname)\n+\t\t\tbranch = dwim_branchname;\n \t}\n \n \tif (ac == 2 && !opts.new_branch && !opts.detach) {\n-- \n2.16.1.77.g8685934aa2\n\n"},{"id":"342889","messageId":"20180325134947.25828-6-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"[PATCH v5 5/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-25T13:49:46Z","receivedAt":"2018-03-25T13:46:48Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 19 +++++++++++++++++--\n t/t2025-worktree-add.sh        | 19 ++++++++++++++++---\n 3 files changed, 40 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..eaa6bf713f 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, a worktree with a branch named after\n+`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` exists in the repository,\n+it will be checked out in the new worktree, if it's not checked out\n+anywhere else, otherwise the command will refuse to create the\n+worktree (unless `--force` is used).\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex c296c3eacb..895838b943 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -28,6 +28,7 @@ struct add_opts {\n \tint checkout;\n \tint keep_locked;\n \tconst char *new_branch;\n+\tint checkout_existing_branch;\n };\n \n static int show_only;\n@@ -317,7 +318,10 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n-\tif (opts->new_branch)\n+\tif (opts->checkout_existing_branch)\n+\t\tfprintf_ln(stderr, _(\"checking out branch '%s'\"),\n+\t\t\t   refname);\n+\telse if (opts->new_branch)\n \t\tfprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n \n \tfprintf(stderr, _(\"new worktree HEAD is now at %s\"),\n@@ -370,7 +374,18 @@ static const char *dwim_branch(const char *path, struct add_opts *opts)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n-\topts->new_branch = xstrndup(s, n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\topts->checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\topts->new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..ae602cf20e 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,26 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n+test_expect_success '\"add\" checks out existing branch of dwimd name' '\n \ttest_commit c1 &&\n \ttest_commit c2 &&\n \tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n+\tgit worktree add precious &&\n \ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+\t(\n+\t\tcd precious &&\n+\t\ttest_cmp_rev precious HEAD\n+\t)\n+'\n+\n+test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n+'\n+\n+test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n+\tgit worktree add --force test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.16.1.77.g8685934aa2\n\n"},{"id":"342890","messageId":"20180325134947.25828-7-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"[PATCH v5 6/6] t2025: rename now outdated branch name","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-25T13:49:47Z","receivedAt":"2018-03-25T13:46:50Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Before the previous commit, the branch named precious was used to check\nthat 'git worktree' wouldn't clobber the branch.  While 'git worktree'\nstill shouldn't (and doesn't) modify the branch, that's no longer the\nmain thing the test is checking.\n\nRename the branch to avoid making future readers wonder why this\nparticular branch is more \"precious\" than others.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n t/t2025-worktree-add.sh | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex ae602cf20e..fb99f4c46f 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -201,12 +201,12 @@ test_expect_success '\"add\" with <branch> omitted' '\n test_expect_success '\"add\" checks out existing branch of dwimd name' '\n \ttest_commit c1 &&\n \ttest_commit c2 &&\n-\tgit branch precious HEAD~1 &&\n-\tgit worktree add precious &&\n-\ttest_cmp_rev HEAD~1 precious &&\n+\tgit branch dwim HEAD~1 &&\n+\tgit worktree add dwim &&\n+\ttest_cmp_rev HEAD~1 dwim &&\n \t(\n-\t\tcd precious &&\n-\t\ttest_cmp_rev precious HEAD\n+\t\tcd dwim &&\n+\t\ttest_cmp_rev dwim HEAD\n \t)\n '\n \n-- \n2.16.1.77.g8685934aa2\n\n"},{"id":"343111","messageId":"CAPig+cSS2T-CweGtfO1vm=cskS91hLCHBoOhDuoqHAzg=27WbA@mail.gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"Re: [PATCH v5 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-27T08:58:19Z","receivedAt":"2018-03-27T08:58:26Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Thanks Eric for the review of the previous round and Duy and Junio for\n> additional comments.\n> This round should address all of Eric's comments from the previous round.\n\nThanks, it appears to cover my review comments from the previous\nround. I do have some additional comments on this round (which I could\nhave raised with the previous round if I had thought of them at the\ntime).\n\n> As explained in more detail in a reply to the review comment directly,\n> I did not add an enum to 'struct add_opts', for 'force_new_branch' and\n> 'checkout_existing_branch', but instead removed 'force_new_branch'\n> from the struct as it's not required.\n\nMakes sense. In fact, I had thoughts along these lines during your\nprevious dwim-ery series. See my comments on patch 3/6.\n\n> The rest of the updates are mainly in the user facing messages,\n> documentation and one added test.\n> Interdiff below:\n\nThe interdiff looks sane. Unfortunately, due to UI regressions, I'm\nhaving second thoughts about whether this series is going in the right\ndirection. See my comments on patch 2/6.\n"},{"id":"343112","messageId":"CAPig+cSNYdJwBS1me+bkELDmrPHgDZJDwjA=o=O4CzQBT=jpzQ@mail.gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-3-t.gummerer@gmail.com","subject":"Re: [PATCH v5 2/6] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-27T08:59:51Z","receivedAt":"2018-03-27T08:59:59Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently there is no indication in the \"git worktree add\" output that\n> a new branch was created.  This would be especially useful information\n> in the case where the dwim of \"git worktree add <path>\" kicks in, as the\n> user didn't explicitly ask for a new branch, but we create one from\n> them.\n\nFailed to notice this last time around: s/from/for/\n\nPerhaps Junio can tweak it when queuing.\n\n> Print some additional output showing that a branch was created and the\n> branch name to help the user.\n>\n> This will also be useful in the next commit, which introduces a new kind\n\nIt's no longer the _next_ commit which does this. Perhaps say instead\n\"a subsequent commit\". (Again, perhaps Junio can tweak it since it's\nnot worth a re-roll.)\n\n> of dwim-ery of checking out the branch if it exists instead of refusing\n> to create a new worktree in that case, and where it's nice to tell the\n> user which kind of dwim-ery kicked in.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n> +       if (opts->new_branch)\n> +               fprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n\nI didn't think of this before, but what happens with the original\ndwim-ery you added which checks out a remote branch matching the\nworktree name if no such local branch exists? I was wondering if we'd\nwant to see a distinct and more informative message in that case, such\nas \"creating branch '%s' from remote '%s'\" or something. However, I\nsee that we're already getting a message:\n\n    Branch 'foo' set up to track remote branch 'foo' from 'origin'.\n    creating branch 'foo'\n    new worktree HEAD is now at d3adb33f boople\n\nwhich is a bit weird since tracking appears to be set up before the\nbranch itself is created. I thought that this was another UI\nregression of the sort I mentioned in [1], however, the messages were\nout of order even before the current patch series:\n\n    Branch 'foo' set up to track remote branch 'foo' from 'origin'.\n    Preparing foo (identifier foo)\n    Checking out files: 100% (9999/9999), done.\n    HEAD is now at d3adb33f boople\n\nThis highlights another regression introduced by this series. Patch\n1/6 suppresses the \"Checking out files:\" message, which is a bit\nunfortunate for decent sized worktrees. I'm not sure I'm entirely\nhappy about that loss. Thoughts?\n\n[1]: https://public-inbox.org/git/CAPig+cT8i9L9kbhx=b0sG4_QYNdoEDPW-1xypM9xzBqPmqR__Q@mail.gmail.com/\n\n>         fprintf(stderr, _(\"new worktree HEAD is now at %s\"),\n>                 find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n"},{"id":"343113","messageId":"CAPig+cQQUbBihLeBRemLHnx42E9b_qUt-mKgDyRRy0-UQTYBKw@mail.gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-4-t.gummerer@gmail.com","subject":"Re: [PATCH v5 3/6] worktree: remove force_new_branch from struct add_opts","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-27T09:00:32Z","receivedAt":"2018-03-27T09:00:38Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> The 'force_new_branch' flag in 'struct add_opts' is only used inside the\n> add function, where we already have the same information stored in the\n> 'new_branch_force' variable.  Avoid that unnecessary duplication.\n\nWhen I was reviewing your original dwim-ery series (inferring 'foo'\nfrom 'origin/foo'), I noticed that 'struct add_opts' had accumulated a\nnumber of unnecessary members over time, including this one. My plan\nwas to submit a patch removing all those pointless members after your\ndwim-ery series settled, however, I never got around to it.\n\nThis patch might be a good opportunity for doing that cleanup\nwholesale, removing all unneeded members rather than just the one. (If\nso, you'd probably want to move to this patch to the front of the\nseries as cleanup before the meatier changes.) Anyhow, it's just a\nthought; feel free to respond with \"it's outside the scope of this\nseries\" if you're not interested in doing it.\n\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n"},{"id":"343114","messageId":"CAPig+cSYxGrhz2RDmHFXaEWC687BSiGb12cq8pZN_XYPGi7ejQ@mail.gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-5-t.gummerer@gmail.com","subject":"Re: [PATCH v5 4/6] worktree: factor out dwim_branch function","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-27T09:01:19Z","receivedAt":"2018-03-27T09:01:36Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Factor out a dwim_branch function, which takes care of the dwim'ery in\n> 'git worktree add <path>'.  It's not too much code currently, but we're\n> adding a new kind of dwim in a subsequent patch, at which point it makes\n> more sense to have it as a separate function.\n> [...]\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -417,16 +431,9 @@ static int add(int ac, const char **av, const char *prefix)\n>         if (ac < 2 && !opts.new_branch && !opts.detach) {\n> -               int n;\n> -               const char *s = worktree_basename(path, &n);\n> -               opts.new_branch = xstrndup(s, n);\n> -               if (guess_remote) {\n> -                       struct object_id oid;\n> -                       const char *remote =\n> -                               unique_tracking_name(opts.new_branch, &oid);\n> -                       if (remote)\n> -                               branch = remote;\n> -               }\n> +               const char *dwim_branchname = dwim_branch(path, &opts);\n> +               if (dwim_branchname)\n> +                       branch = dwim_branchname;\n\nI don't care strongly but the name 'dwim_branchname' is awfully long\nin a context where it's assigned the result of a call to\ndwim_branch(). In this tiny code block, a short and sweet name 's'\nwould be easy to grok; there'd be no confusion.\n\nAnyhow, it's subjective and not at all worth a re-roll.\n"},{"id":"343115","messageId":"CAPig+cTmGvkGkcdH45mRO6uwEK2UyR1FQ_fiD=2wgz8Pt_WeOg@mail.gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-6-t.gummerer@gmail.com","subject":"Re: [PATCH v5 5/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-27T09:04:16Z","receivedAt":"2018-03-27T09:04:24Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently 'git worktree add <path>' creates a new branch named after the\n> basename of the path by default.  If a branch with that name already\n> exists, the command refuses to do anything, unless the '--force' option\n> is given.\n>\n> However we can do a little better than that, and check the branch out if\n> it is not checked out anywhere else.  This will help users who just want\n> to check an existing branch out into a new worktree, and save a few\n> keystrokes.\n> [...]\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -317,7 +318,10 @@ static int add_worktree(const char *path, const char *refname,\n> -       if (opts->new_branch)\n> +       if (opts->checkout_existing_branch)\n> +               fprintf_ln(stderr, _(\"checking out branch '%s'\"),\n> +                          refname);\n\nThis fprintf_ln() can easily fit on one line; no need to wrap\n'refname' to the next one.\n\nNot worth a re-roll, though.\n\n> +       else if (opts->new_branch)\n>                 fprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n> diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> @@ -198,13 +198,26 @@ test_expect_success '\"add\" with <branch> omitted' '\n> -test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n> +test_expect_success '\"add\" checks out existing branch of dwimd name' '\n>         test_commit c1 &&\n>         test_commit c2 &&\n>         git branch precious HEAD~1 &&\n> -       test_must_fail git worktree add precious &&\n> +       git worktree add precious &&\n>         test_cmp_rev HEAD~1 precious &&\n> -       test_path_is_missing precious\n> +       (\n> +               cd precious &&\n> +               test_cmp_rev precious HEAD\n> +       )\n> +'\n\nLooking at this more closely, once it stops being a \"don't clobber\nprecious branch\" test, it's doing more than it needs to do, thus is\nconfusing for future readers. The setup -- creating two commits and\nmaking \"precious\" point one commit back -- was very intentional and\nallowed the test to verify not only that the worktree wasn't created\nbut that \"precious\" didn't change to reference a different commit.\nHowever, _none_ of this matters once it becomes a dwim'ing test; the\nunnecessary code is confusing since it doesn't make sense in the\ncontext of dwim'ing. I _think_ the entire test can collapse to:\n\n    git branch existing &&\n    git worktree add existing &&\n    (\n        cd existing &&\n        test_cmp_rev existing HEAD\n    )\n\nIn other words, this patch should drop the \"precious\" test altogether\nand just introduce a new dwim'ing test (and drop patch 6/6).\n\nI do think that with the potential confusion to future readers, this\ndoes deserve a re-roll.\n\n> +test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n> +       git checkout -b test-branch &&\n> +       test_must_fail git worktree add test-branch &&\n> +       test_path_is_missing test-branch\n> +'\n> +\n> +test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n> +       git worktree add --force test-branch\n>  '\n"},{"id":"343422","messageId":"20180330135314.GA2629@hank","threadId":"47657","inReplyTo":"CAPig+cSNYdJwBS1me+bkELDmrPHgDZJDwjA=o=O4CzQBT=jpzQ@mail.gmail.com","subject":"Re: [PATCH v5 2/6] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-30T13:53:14Z","receivedAt":"2018-03-30T13:49:54Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 03/27, Eric Sunshine wrote:\n> On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > Currently there is no indication in the \"git worktree add\" output that\n> > a new branch was created.  This would be especially useful information\n> > in the case where the dwim of \"git worktree add <path>\" kicks in, as the\n> > user didn't explicitly ask for a new branch, but we create one from\n> > them.\n> \n> Failed to notice this last time around: s/from/for/\n> \n> Perhaps Junio can tweak it when queuing.\n> \n> > Print some additional output showing that a branch was created and the\n> > branch name to help the user.\n> >\n> > This will also be useful in the next commit, which introduces a new kind\n> \n> It's no longer the _next_ commit which does this. Perhaps say instead\n> \"a subsequent commit\". (Again, perhaps Junio can tweak it since it's\n> not worth a re-roll.)\n\nRight, will fix.\n\n> > of dwim-ery of checking out the branch if it exists instead of refusing\n> > to create a new worktree in that case, and where it's nice to tell the\n> > user which kind of dwim-ery kicked in.\n> >\n> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> > ---\n> > diff --git a/builtin/worktree.c b/builtin/worktree.c\n> > @@ -318,6 +318,9 @@ static int add_worktree(const char *path, const char *refname,\n> > +       if (opts->new_branch)\n> > +               fprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n> \n> I didn't think of this before, but what happens with the original\n> dwim-ery you added which checks out a remote branch matching the\n> worktree name if no such local branch exists? I was wondering if we'd\n> want to see a distinct and more informative message in that case, such\n> as \"creating branch '%s' from remote '%s'\" or something. However, I\n> see that we're already getting a message:\n> \n>     Branch 'foo' set up to track remote branch 'foo' from 'origin'.\n>     creating branch 'foo'\n>     new worktree HEAD is now at d3adb33f boople\n> \n> which is a bit weird since tracking appears to be set up before the\n> branch itself is created. I thought that this was another UI\n> regression of the sort I mentioned in [1], however, the messages were\n> out of order even before the current patch series:\n\nYeah I agree this is a bit odd.  I did think about this, and the main\nreason why I didn't change this by passing the '--quiet' flag to 'git\nbranch' which we call in the 'add()' function is to keep the\ninformation about the remote tracking.\n\nLooking at where this information actually comes from, there's\nmultiple different ways we'd have to distinguish to print this\ninformation properly.\n\nNow that I put some more thought into this, I think there are a couple\nof ways to solve this, the easiest and cleanest of which would\nprobably be to run 'git branch' through 'pipe_command', save the\noutput and print it after the \"creating branch 'foo'\" message. \n\n>     Branch 'foo' set up to track remote branch 'foo' from 'origin'.\n>     Preparing foo (identifier foo)\n>     Checking out files: 100% (9999/9999), done.\n>     HEAD is now at d3adb33f boople\n> \n> This highlights another regression introduced by this series. Patch\n> 1/6 suppresses the \"Checking out files:\" message, which is a bit\n> unfortunate for decent sized worktrees. I'm not sure I'm entirely\n> happy about that loss. Thoughts?\n\nTbh I never really noticed the \"Checking out files\" output, because\nthe repositories I used day to day are usually of a smaller size,\nwhere checking out the files takes less than a second, so I would\nnever even notice this output.\n\nBut while I don't care about it, others may, so I think it would be\nbetter to preserve this output.  Maybe the best way to do that would\nbe to not use 'run_command' to run 'git reset --hard', but to instead\nreplace that with the internal functions.\n\nI haven't actually looked at how hard this would be, but I'm guessing\nthis may be the best option to avoid this UI regression.  I'll play\nwith this some more and see what I can come up with, and send a\nre-roll hopefully in a few days.\n\nThanks for your review!\n\n> [1]: https://public-inbox.org/git/CAPig+cT8i9L9kbhx=b0sG4_QYNdoEDPW-1xypM9xzBqPmqR__Q@mail.gmail.com/\n> \n> >         fprintf(stderr, _(\"new worktree HEAD is now at %s\"),\n> >                 find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n"},{"id":"343423","messageId":"20180330135537.GB2629@hank","threadId":"47657","inReplyTo":"CAPig+cQQUbBihLeBRemLHnx42E9b_qUt-mKgDyRRy0-UQTYBKw@mail.gmail.com","subject":"Re: [PATCH v5 3/6] worktree: remove force_new_branch from struct add_opts","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-30T13:55:37Z","receivedAt":"2018-03-30T13:52:16Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 03/27, Eric Sunshine wrote:\n> On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > The 'force_new_branch' flag in 'struct add_opts' is only used inside the\n> > add function, where we already have the same information stored in the\n> > 'new_branch_force' variable.  Avoid that unnecessary duplication.\n> \n> When I was reviewing your original dwim-ery series (inferring 'foo'\n> from 'origin/foo'), I noticed that 'struct add_opts' had accumulated a\n> number of unnecessary members over time, including this one. My plan\n> was to submit a patch removing all those pointless members after your\n> dwim-ery series settled, however, I never got around to it.\n\nAh right, I didn't look at them in detail, so I failed to notice that.\nWhile I'm already in the area I may as well do that, thanks for the\nsuggestion!\n\n> This patch might be a good opportunity for doing that cleanup\n> wholesale, removing all unneeded members rather than just the one. (If\n> so, you'd probably want to move to this patch to the front of the\n> series as cleanup before the meatier changes.) Anyhow, it's just a\n> thought; feel free to respond with \"it's outside the scope of this\n> series\" if you're not interested in doing it.\n> \n> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n"},{"id":"343425","messageId":"20180330140415.GC2629@hank","threadId":"47657","inReplyTo":"CAPig+cTmGvkGkcdH45mRO6uwEK2UyR1FQ_fiD=2wgz8Pt_WeOg@mail.gmail.com","subject":"Re: [PATCH v5 5/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-30T14:04:15Z","receivedAt":"2018-03-30T14:00:54Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 03/27, Eric Sunshine wrote:\n> On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > Currently 'git worktree add <path>' creates a new branch named after the\n> > basename of the path by default.  If a branch with that name already\n> > exists, the command refuses to do anything, unless the '--force' option\n> > is given.\n> >\n> > However we can do a little better than that, and check the branch out if\n> > it is not checked out anywhere else.  This will help users who just want\n> > to check an existing branch out into a new worktree, and save a few\n> > keystrokes.\n> > [...]\n> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> > ---\n> > diff --git a/builtin/worktree.c b/builtin/worktree.c\n> > @@ -317,7 +318,10 @@ static int add_worktree(const char *path, const char *refname,\n> > -       if (opts->new_branch)\n> > +       if (opts->checkout_existing_branch)\n> > +               fprintf_ln(stderr, _(\"checking out branch '%s'\"),\n> > +                          refname);\n> \n> This fprintf_ln() can easily fit on one line; no need to wrap\n> 'refname' to the next one.\n> \n> Not worth a re-roll, though.\n> \n> > +       else if (opts->new_branch)\n> >                 fprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n> > diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> > @@ -198,13 +198,26 @@ test_expect_success '\"add\" with <branch> omitted' '\n> > -test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n> > +test_expect_success '\"add\" checks out existing branch of dwimd name' '\n> >         test_commit c1 &&\n> >         test_commit c2 &&\n> >         git branch precious HEAD~1 &&\n> > -       test_must_fail git worktree add precious &&\n> > +       git worktree add precious &&\n> >         test_cmp_rev HEAD~1 precious &&\n> > -       test_path_is_missing precious\n> > +       (\n> > +               cd precious &&\n> > +               test_cmp_rev precious HEAD\n> > +       )\n> > +'\n> \n> Looking at this more closely, once it stops being a \"don't clobber\n> precious branch\" test, it's doing more than it needs to do, thus is\n> confusing for future readers. The setup -- creating two commits and\n> making \"precious\" point one commit back -- was very intentional and\n> allowed the test to verify not only that the worktree wasn't created\n> but that \"precious\" didn't change to reference a different commit.\n> However, _none_ of this matters once it becomes a dwim'ing test; the\n> unnecessary code is confusing since it doesn't make sense in the\n> context of dwim'ing. I _think_ the entire test can collapse to:\n> \n>     git branch existing &&\n>     git worktree add existing &&\n>     (\n>         cd existing &&\n>         test_cmp_rev existing HEAD\n>     )\n> \n> In other words, this patch should drop the \"precious\" test altogether\n> and just introduce a new dwim'ing test (and drop patch 6/6).\n> \n> I do think that with the potential confusion to future readers, this\n> does deserve a re-roll.\n\nHmm I do think that it's important to have the branch we create the\nnew working tree from different from the branch of the main working\ntree, to make sure we don't accidentally overwrite an existing branch,\nand to show that the new branch is checked out.\n\nMaybe I'm overly paranoid though?\n\n> > +test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n> > +       git checkout -b test-branch &&\n> > +       test_must_fail git worktree add test-branch &&\n> > +       test_path_is_missing test-branch\n> > +'\n> > +\n> > +test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n> > +       git worktree add --force test-branch\n> >  '\n"},{"id":"343427","messageId":"20180330140839.GD2629@hank","threadId":"47657","inReplyTo":"CAPig+cSS2T-CweGtfO1vm=cskS91hLCHBoOhDuoqHAzg=27WbA@mail.gmail.com","subject":"Re: [PATCH v5 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-30T14:08:39Z","receivedAt":"2018-03-30T14:05:17Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 03/27, Eric Sunshine wrote:\n> On Sun, Mar 25, 2018 at 9:49 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > Thanks Eric for the review of the previous round and Duy and Junio for\n> > additional comments.\n> > This round should address all of Eric's comments from the previous round.\n> \n> Thanks, it appears to cover my review comments from the previous\n> round. I do have some additional comments on this round (which I could\n> have raised with the previous round if I had thought of them at the\n> time).\n> \n> > As explained in more detail in a reply to the review comment directly,\n> > I did not add an enum to 'struct add_opts', for 'force_new_branch' and\n> > 'checkout_existing_branch', but instead removed 'force_new_branch'\n> > from the struct as it's not required.\n> \n> Makes sense. In fact, I had thoughts along these lines during your\n> previous dwim-ery series. See my comments on patch 3/6.\n> \n> > The rest of the updates are mainly in the user facing messages,\n> > documentation and one added test.\n> > Interdiff below:\n> \n> The interdiff looks sane. Unfortunately, due to UI regressions, I'm\n> having second thoughts about whether this series is going in the right\n> direction. See my comments on patch 2/6.\n\nThanks for your reviews of this series!  As I mentioned in the reply\nthere I'm going to see whether or not I can fix those regressions\n(hopefully I can :)), and send a re-roll.\n"},{"id":"343528","messageId":"20180331151804.30380-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180325134947.25828-1-t.gummerer@gmail.com","subject":"[PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-31T15:17:58Z","receivedAt":"2018-03-31T15:14:53Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Thanks Eric for the review of the last round.\n\nPrevious rounds are at <20180121120208.12760-1-t.gummerer@gmail.com>,\n<20180204221305.28300-1-t.gummerer@gmail.com>,\n<20180317220830.30963-1-t.gummerer@gmail.com>,\n<20180317222219.4940-1-t.gummerer@gmail.com> and\n20180325134947.25828-1-t.gummerer@gmail.com.\n\nThis round should fix all the UI issues Eric found in the last round.\n\nThe changes I made in a bit more detail:\n\n- in addition to removing the 'force_new_branch' flag from 'struct\n  add_opts', also remove the 'new_branch' member, which is local to\n  the 'add()' function.  The other four members are needed in the\n  'worktree_add()' function, so I left them there.   This patch is now\n  the first patch in the series.\n\n- added a new commit introducing a new hidden --show-new-head-line\n  flag in 'git reset'.  This is used to suppress the \"HEAD is now at\n  ...\"  line that 'git reset --hard' usually prints, so we can replace\n  it with our own \"New worktree HEAD is now at ...\" line instead,\n  while keeping the progress indicator for larger repositories.\n\n  I guess this may be the most controversial bit at this point, as\n  we'd be adding an option for internal use only.  Not sure how we\n  feel about that. But short of going back to the old output format, I\n  don't see a good option to make this work otherwise.  I tried\n  re-using internal functions for this, but until we have 'struct\n  repository' everywhere, that's going to be quite hard.\n\n- Print the \"Creating branch ...\" and \"Checking out branch ...\"\n  messages earlier in the process.  This is mainly to avoid the out of\n  order \"Branch '...' now set up to track ...\" message.\n\n- Various commit message and style cleanups\n\nNote that these fixes are quite differently executed than I had\nimagined them in the reply to the review comments, as things didn't\nwork as I had imagined.  The UI problems should be fixed now\nnonetheless :)\n\nSome examples of the new UI behaviour here for reference:\n\n - guess-remote mode\n\n    $ git worktree add --guess-remote ../next\n    Creating branch 'next'\n    Branch 'next' set up to track remote branch 'next' from 'origin'.\n    New worktree HEAD is now at caa68db14 Merge branch 'sb/packfiles-in-repository' into next\n\n - original dwim (create a branch based on the current HEAD)\n\n    $ git worktree add ../test\n    Creating branch 'test'\n    New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - new dwim (check out existing branch)\n\n    $ git worktree add ../test\n    Checking out branch 'test'\n    New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - no new branch created\n \n    $ git worktree add ../test2 origin/master\n    New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - large repository (with original dwim)\n\n    $ g worktree add ../test\n    Creating branch 'test'\n    Checking out files: 100% (62915/62915), done.\n    New worktree HEAD is now at c2a9838452a4 Merge tag 'for-4.16/dm-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm\n\nCompare this to the old UI (new dwim omitted, as there's no old\nversion of that):\n\n - guess-remote mode\n\n    $ git worktree add --guess-remote ../next\n    Branch 'next' set up to track remote branch 'next' from 'origin'.\n    Preparing ../next (identifier next)\n    HEAD is now at caa68db14 Merge branch 'sb/packfiles-in-repository' into next\n\n - original dwim (create a branch based on the current HEAD)\n\n    $ git worktree add ../test\n    Preparing ../test (identifier test)\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - no new branch created\n\n    $ git worktree add ../test2 origin/master\n    Preparing ../test2 (identifier test2)\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - large repository\n\n    $ git worktree add ../test\n    Preparing ../test (identifier test)\n    Checking out files: 100% (62915/62915), done.\n    HEAD is now at c2a9838452a4 Merge tag 'for-4.16/dm-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm\n\nThe one thing we are loosing is a context line before \"Checking out\nfiles:\", if no new branch is created.  Personally I feel like that's\nacceptable, as the user just used the 'git worktree add' command, so\nit should be intuitive where those files are being checked out.\n\nWe could also print \"Preparing worktree <path>\" as a line in the\nbeginning (without mentioning the identifier, so we can print it in\nthe 'add()' function), but I don't feel like that's worth spending the\nextra screen estate.  I don't feel strongly about that though, so if\nsomeone has a moderately strong preference for that line being there,\nI'm happy to add it.\n\nInterdiff below:\n\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex e15f595799..54b2576449 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -288,6 +288,7 @@ static int git_reset_config(const char *var, const char *value, void *cb)\n int cmd_reset(int argc, const char **argv, const char *prefix)\n {\n \tint reset_type = NONE, update_ref_status = 0, quiet = 0;\n+\tint show_new_head_line = 1;\n \tint patch_mode = 0, unborn;\n \tconst char *rev;\n \tstruct object_id oid;\n@@ -310,6 +311,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL('p', \"patch\", &patch_mode, N_(\"select hunks interactively\")),\n \t\tOPT_BOOL('N', \"intent-to-add\", &intent_to_add,\n \t\t\t\tN_(\"record only the fact that removed paths will be added later\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"show-new-head-line\", &show_new_head_line, N_(\"show information on the new HEAD\")),\n \t\tOPT_END()\n \t};\n \n@@ -403,7 +405,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\t * switched to, saving the previous head in ORIG_HEAD before. */\n \t\tupdate_ref_status = reset_refs(rev, &oid);\n \n-\t\tif (reset_type == HARD && !update_ref_status && !quiet)\n+\t\tif (reset_type == HARD && !update_ref_status && !quiet &&\n+\t\t    show_new_head_line)\n \t\t\tprint_new_head_line(lookup_commit_reference(&oid));\n \t}\n \tif (!pathspec.nr)\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 895838b943..511d0aa370 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -27,8 +27,6 @@ struct add_opts {\n \tint detach;\n \tint checkout;\n \tint keep_locked;\n-\tconst char *new_branch;\n-\tint checkout_existing_branch;\n };\n \n static int show_only;\n@@ -318,31 +316,26 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n-\tif (opts->checkout_existing_branch)\n-\t\tfprintf_ln(stderr, _(\"checking out branch '%s'\"),\n-\t\t\t   refname);\n-\telse if (opts->new_branch)\n-\t\tfprintf_ln(stderr, _(\"creating branch '%s'\"), opts->new_branch);\n-\n-\tfprintf(stderr, _(\"new worktree HEAD is now at %s\"),\n-\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n-\n-\tstrbuf_reset(&sb);\n-\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n-\tif (sb.len > 0)\n-\t\tfprintf(stderr, \" %s\", sb.buf);\n-\tfputc('\\n', stderr);\n-\n \tif (opts->checkout) {\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n-\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", \"--quiet\", NULL);\n+\t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n+\t\targv_array_push(&cp.args, \"--no-show-new-head-line\");\n \t\tcp.env = child_env.argv;\n \t\tret = run_command(&cp);\n \t\tif (ret)\n \t\t\tgoto done;\n \t}\n \n+\tfprintf(stderr, _(\"New worktree HEAD is now at %s\"),\n+\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n+\n+\tstrbuf_reset(&sb);\n+\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\tif (sb.len > 0)\n+\t\tfprintf(stderr, \" %s\", sb.buf);\n+\tfputc('\\n', stderr);\n+\n \tis_junk = 0;\n \tFREE_AND_NULL(junk_work_tree);\n \tFREE_AND_NULL(junk_git_dir);\n@@ -370,7 +363,8 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n-static const char *dwim_branch(const char *path, struct add_opts *opts)\n+static const char *dwim_branch(const char *path, const char **new_branch,\n+\t\t\t       int *checkout_existing_branch)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n@@ -379,17 +373,17 @@ static const char *dwim_branch(const char *path, struct add_opts *opts)\n \n \tif (!strbuf_check_branch_ref(&ref, branchname) &&\n \t    ref_exists(ref.buf)) {\n-\t\topts->checkout_existing_branch = 1;\n+\t\t*checkout_existing_branch = 1;\n \t\tstrbuf_release(&ref);\n \t\tUNLEAK(branchname);\n \t\treturn branchname;\n \t}\n \n-\topts->new_branch = branchname;\n+\t*new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\n-\t\t\tunique_tracking_name(opts->new_branch, &oid);\n+\t\t\tunique_tracking_name(*new_branch, &oid);\n \t\treturn remote;\n \t}\n \treturn NULL;\n@@ -401,10 +395,12 @@ static int add(int ac, const char **av, const char *prefix)\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n \tconst char *branch;\n+\tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n+\tint checkout_existing_branch = 0;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&opts.force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n-\t\tOPT_STRING('b', NULL, &opts.new_branch, N_(\"branch\"),\n+\t\tOPT_STRING('b', NULL, &new_branch, N_(\"branch\"),\n \t\t\t   N_(\"create a new branch\")),\n \t\tOPT_STRING('B', NULL, &new_branch_force, N_(\"branch\"),\n \t\t\t   N_(\"create or reset a branch\")),\n@@ -422,7 +418,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tmemset(&opts, 0, sizeof(opts));\n \topts.checkout = 1;\n \tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n-\tif (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1)\n+\tif (!!opts.detach + !!new_branch + !!new_branch_force > 1)\n \t\tdie(_(\"-b, -B, and --detach are mutually exclusive\"));\n \tif (ac < 1 || ac > 2)\n \t\tusage_with_options(worktree_usage, options);\n@@ -436,22 +432,23 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (new_branch_force) {\n \t\tstruct strbuf symref = STRBUF_INIT;\n \n-\t\topts.new_branch = new_branch_force;\n+\t\tnew_branch = new_branch_force;\n \n \t\tif (!opts.force &&\n-\t\t    !strbuf_check_branch_ref(&symref, opts.new_branch) &&\n+\t\t    !strbuf_check_branch_ref(&symref, new_branch) &&\n \t\t    ref_exists(symref.buf))\n \t\t\tdie_if_checked_out(symref.buf, 0);\n \t\tstrbuf_release(&symref);\n \t}\n \n-\tif (ac < 2 && !opts.new_branch && !opts.detach) {\n-\t\tconst char *dwim_branchname = dwim_branch(path, &opts);\n-\t\tif (dwim_branchname)\n-\t\t\tbranch = dwim_branchname;\n+\tif (ac < 2 && !new_branch && !opts.detach) {\n+\t\tconst char *s = dwim_branch(path, &new_branch,\n+\t\t\t\t\t    &checkout_existing_branch);\n+\t\tif (s)\n+\t\t\tbranch = s;\n \t}\n \n-\tif (ac == 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac == 2 && !new_branch && !opts.detach) {\n \t\tstruct object_id oid;\n \t\tstruct commit *commit;\n \t\tconst char *remote;\n@@ -460,25 +457,29 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tif (!commit) {\n \t\t\tremote = unique_tracking_name(branch, &oid);\n \t\t\tif (remote) {\n-\t\t\t\topts.new_branch = branch;\n+\t\t\t\tnew_branch = branch;\n \t\t\t\tbranch = remote;\n \t\t\t}\n \t\t}\n \t}\n \n-\tif (opts.new_branch) {\n+\tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\n+\t\tfprintf_ln(stderr, _(\"Creating branch '%s'\"), new_branch);\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n \t\tif (new_branch_force)\n \t\t\targv_array_push(&cp.args, \"--force\");\n-\t\targv_array_push(&cp.args, opts.new_branch);\n+\t\targv_array_push(&cp.args, new_branch);\n \t\targv_array_push(&cp.args, branch);\n \t\tif (opt_track)\n \t\t\targv_array_push(&cp.args, opt_track);\n \t\tif (run_command(&cp))\n \t\t\treturn -1;\n-\t\tbranch = opts.new_branch;\n+\t\tbranch = new_branch;\n+\t} else if (checkout_existing_branch) {\n+\t\t  fprintf_ln(stderr, _(\"Checking out branch '%s'\"), branch);\n \t} else if (opt_track) {\n \t\tdie(_(\"--[no-]track can only be used if a new branch is created\"));\n \t}\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex fb99f4c46f..f72cb0eb0b 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -199,8 +199,6 @@ test_expect_success '\"add\" with <branch> omitted' '\n '\n \n test_expect_success '\"add\" checks out existing branch of dwimd name' '\n-\ttest_commit c1 &&\n-\ttest_commit c2 &&\n \tgit branch dwim HEAD~1 &&\n \tgit worktree add dwim &&\n \ttest_cmp_rev HEAD~1 dwim &&\n@@ -210,7 +208,7 @@ test_expect_success '\"add\" checks out existing branch of dwimd name' '\n \t)\n '\n \n-test_expect_success '\"add\" auto-vivify fails with checked out branch' '\n+test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n \tgit checkout -b test-branch &&\n \ttest_must_fail git worktree add test-branch &&\n \ttest_path_is_missing test-branch\ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex 95653a08ca..a160f78aba 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -568,4 +568,9 @@ test_expect_success 'reset --mixed sets up work tree' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'reset --no-show-new-head-line suppresses \"HEAD is now at\" output' '\n+\tgit reset --hard --no-show-new-head-line HEAD >actual &&\n+\t! grep \"HEAD is now at\" <actual\n+'\n+\n test_done\n\nThomas Gummerer (6):\n  worktree: remove extra members from struct add_opts\n  reset: introduce show-new-head-line option\n  worktree: improve message when creating a new worktree\n  worktree: be clearer when \"add\" dwim-ery kicks in\n  worktree: factor out dwim_branch function\n  worktree: teach \"add\" to check out existing branches\n\n Documentation/git-worktree.txt |  9 ++++-\n builtin/reset.c                |  5 ++-\n builtin/worktree.c             | 85 ++++++++++++++++++++++++++++--------------\n t/t2025-worktree-add.sh        | 25 +++++++++----\n t/t7102-reset.sh               |  5 +++\n 5 files changed, 92 insertions(+), 37 deletions(-)\n\n-- \n2.16.1.78.g383dce0c66\n\n"},{"id":"343529","messageId":"20180331151804.30380-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"[PATCH v6 1/6] worktree: remove extra members from struct add_opts","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-31T15:17:59Z","receivedAt":"2018-03-31T15:14:56Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"There are two members of 'struct add_opts', which are only used inside\nthe 'add()' function, but being part of 'struct add_opts' they are\nneedlessly also passed to the 'add_worktree' function.\n\nMake them local to the 'add()' function to make it clearer where they\nare used.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 32 +++++++++++++++-----------------\n 1 file changed, 15 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..4d96a21a45 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -27,8 +27,6 @@ struct add_opts {\n \tint detach;\n \tint checkout;\n \tint keep_locked;\n-\tconst char *new_branch;\n-\tint force_new_branch;\n };\n \n static int show_only;\n@@ -363,10 +361,11 @@ static int add(int ac, const char **av, const char *prefix)\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n \tconst char *branch;\n+\tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&opts.force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n-\t\tOPT_STRING('b', NULL, &opts.new_branch, N_(\"branch\"),\n+\t\tOPT_STRING('b', NULL, &new_branch, N_(\"branch\"),\n \t\t\t   N_(\"create a new branch\")),\n \t\tOPT_STRING('B', NULL, &new_branch_force, N_(\"branch\"),\n \t\t\t   N_(\"create or reset a branch\")),\n@@ -384,7 +383,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tmemset(&opts, 0, sizeof(opts));\n \topts.checkout = 1;\n \tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n-\tif (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1)\n+\tif (!!opts.detach + !!new_branch + !!new_branch_force > 1)\n \t\tdie(_(\"-b, -B, and --detach are mutually exclusive\"));\n \tif (ac < 1 || ac > 2)\n \t\tusage_with_options(worktree_usage, options);\n@@ -395,33 +394,32 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (!strcmp(branch, \"-\"))\n \t\tbranch = \"@{-1}\";\n \n-\topts.force_new_branch = !!new_branch_force;\n-\tif (opts.force_new_branch) {\n+\tif (new_branch_force) {\n \t\tstruct strbuf symref = STRBUF_INIT;\n \n-\t\topts.new_branch = new_branch_force;\n+\t\tnew_branch = new_branch_force;\n \n \t\tif (!opts.force &&\n-\t\t    !strbuf_check_branch_ref(&symref, opts.new_branch) &&\n+\t\t    !strbuf_check_branch_ref(&symref, new_branch) &&\n \t\t    ref_exists(symref.buf))\n \t\t\tdie_if_checked_out(symref.buf, 0);\n \t\tstrbuf_release(&symref);\n \t}\n \n-\tif (ac < 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac < 2 && !new_branch && !opts.detach) {\n \t\tint n;\n \t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n+\t\tnew_branch = xstrndup(s, n);\n \t\tif (guess_remote) {\n \t\t\tstruct object_id oid;\n \t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n+\t\t\t\tunique_tracking_name(new_branch, &oid);\n \t\t\tif (remote)\n \t\t\t\tbranch = remote;\n \t\t}\n \t}\n \n-\tif (ac == 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac == 2 && !new_branch && !opts.detach) {\n \t\tstruct object_id oid;\n \t\tstruct commit *commit;\n \t\tconst char *remote;\n@@ -430,25 +428,25 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tif (!commit) {\n \t\t\tremote = unique_tracking_name(branch, &oid);\n \t\t\tif (remote) {\n-\t\t\t\topts.new_branch = branch;\n+\t\t\t\tnew_branch = branch;\n \t\t\t\tbranch = remote;\n \t\t\t}\n \t\t}\n \t}\n \n-\tif (opts.new_branch) {\n+\tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n-\t\tif (opts.force_new_branch)\n+\t\tif (new_branch_force)\n \t\t\targv_array_push(&cp.args, \"--force\");\n-\t\targv_array_push(&cp.args, opts.new_branch);\n+\t\targv_array_push(&cp.args, new_branch);\n \t\targv_array_push(&cp.args, branch);\n \t\tif (opt_track)\n \t\t\targv_array_push(&cp.args, opt_track);\n \t\tif (run_command(&cp))\n \t\t\treturn -1;\n-\t\tbranch = opts.new_branch;\n+\t\tbranch = new_branch;\n \t} else if (opt_track) {\n \t\tdie(_(\"--[no-]track can only be used if a new branch is created\"));\n \t}\n-- \n2.16.1.78.ga2082135d8\n\n"},{"id":"343530","messageId":"20180331151804.30380-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"[PATCH v6 3/6] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-31T15:18:01Z","receivedAt":"2018-03-31T15:14:57Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following, when\n'--no-checkout' is not given:\n\n    Preparing foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nwhere the first line is written to stderr, and the second line coming\nfrom 'git reset --hard' is written to stdout, even though both lines are\nsupposed to tell the user what has happened.  In addition to someone not\nfamiliar with 'git worktree', this might seem as if the current HEAD was\nmodified, not the HEAD in the new working tree.\n\nIf the '--no-checkout' flag is given, the output of 'git worktree add'\nis just:\n\n    Preparing foo (identifier foo)\n\neven though the HEAD is set to a commit, which is just not checked out.\n\nThe identifier is also not particularly relevant for the user at the\nmoment, as it's only used internally to distinguish between different\nworktrees that have the same $(basename <path>).\n\nFix these inconsistencies, and no longer show the identifier by making\nthe 'git reset --hard' call not print the \"HEAD is now at ...\" line\nusing the newly introduced flag from the previous commit, and printing\nthe message directly from the builtin command instead.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 12 ++++++++++--\n 1 file changed, 10 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 4d96a21a45..cc94325886 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -301,8 +301,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -322,12 +320,22 @@ static int add_worktree(const char *path, const char *refname,\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n \t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n+\t\targv_array_push(&cp.args, \"--no-show-new-head-line\");\n \t\tcp.env = child_env.argv;\n \t\tret = run_command(&cp);\n \t\tif (ret)\n \t\t\tgoto done;\n \t}\n \n+\tfprintf(stderr, _(\"New worktree HEAD is now at %s\"),\n+\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n+\n+\tstrbuf_reset(&sb);\n+\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\tif (sb.len > 0)\n+\t\tfprintf(stderr, \" %s\", sb.buf);\n+\tfputc('\\n', stderr);\n+\n \tis_junk = 0;\n \tFREE_AND_NULL(junk_work_tree);\n \tFREE_AND_NULL(junk_git_dir);\n-- \n2.16.1.78.ga2082135d8\n\n"},{"id":"343531","messageId":"20180331151804.30380-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"[PATCH v6 2/6] reset: introduce show-new-head-line option","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-31T15:18:00Z","receivedAt":"2018-03-31T15:14:59Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Introduce a new --show-new-head-line command line option, that\ndetermines whether the \"HEAD is now at ...\" message is printed or not.\nIt is enabled by default to preserve the current behaviour.\n\nIt will be used in a subsequent commit to disable printing the \"HEAD is\nnow at ...\" line in 'git worktree add', so it can be replaced with a\ncustom one, that explains the behaviour better.\n\nWe cannot just pass the --quite flag from 'git worktree add', as that\nwould also hide progress output when checking out large working trees,\nwhich is undesirable.\n\nAs this option is only for internal use, which we probably don't want\nto advertise to our users, at least until there's a need for it, make\nit a hidden flag.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/reset.c  | 5 ++++-\n t/t7102-reset.sh | 5 +++++\n 2 files changed, 9 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex e15f595799..54b2576449 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -288,6 +288,7 @@ static int git_reset_config(const char *var, const char *value, void *cb)\n int cmd_reset(int argc, const char **argv, const char *prefix)\n {\n \tint reset_type = NONE, update_ref_status = 0, quiet = 0;\n+\tint show_new_head_line = 1;\n \tint patch_mode = 0, unborn;\n \tconst char *rev;\n \tstruct object_id oid;\n@@ -310,6 +311,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL('p', \"patch\", &patch_mode, N_(\"select hunks interactively\")),\n \t\tOPT_BOOL('N', \"intent-to-add\", &intent_to_add,\n \t\t\t\tN_(\"record only the fact that removed paths will be added later\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"show-new-head-line\", &show_new_head_line, N_(\"show information on the new HEAD\")),\n \t\tOPT_END()\n \t};\n \n@@ -403,7 +405,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\t * switched to, saving the previous head in ORIG_HEAD before. */\n \t\tupdate_ref_status = reset_refs(rev, &oid);\n \n-\t\tif (reset_type == HARD && !update_ref_status && !quiet)\n+\t\tif (reset_type == HARD && !update_ref_status && !quiet &&\n+\t\t    show_new_head_line)\n \t\t\tprint_new_head_line(lookup_commit_reference(&oid));\n \t}\n \tif (!pathspec.nr)\ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex 95653a08ca..a160f78aba 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -568,4 +568,9 @@ test_expect_success 'reset --mixed sets up work tree' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'reset --no-show-new-head-line suppresses \"HEAD is now at\" output' '\n+\tgit reset --hard --no-show-new-head-line HEAD >actual &&\n+\t! grep \"HEAD is now at\" <actual\n+'\n+\n test_done\n-- \n2.16.1.78.ga2082135d8\n\n"},{"id":"343532","messageId":"20180331151804.30380-7-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"[PATCH v6 6/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-31T15:18:04Z","receivedAt":"2018-03-31T15:15:02Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 22 +++++++++++++++++++---\n t/t2025-worktree-add.sh        | 25 ++++++++++++++++++-------\n 3 files changed, 44 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..eaa6bf713f 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, a worktree with a branch named after\n+`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` exists in the repository,\n+it will be checked out in the new worktree, if it's not checked out\n+anywhere else, otherwise the command will refuse to create the\n+worktree (unless `--force` is used).\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 47189d50dd..511d0aa370 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -363,11 +363,23 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n-static const char *dwim_branch(const char *path, const char **new_branch)\n+static const char *dwim_branch(const char *path, const char **new_branch,\n+\t\t\t       int *checkout_existing_branch)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n-\t*new_branch = xstrndup(s, n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\t*checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\t*new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\n@@ -385,6 +397,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tconst char *branch;\n \tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n+\tint checkout_existing_branch = 0;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&opts.force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n \t\tOPT_STRING('b', NULL, &new_branch, N_(\"branch\"),\n@@ -429,7 +442,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tconst char *s = dwim_branch(path, &new_branch);\n+\t\tconst char *s = dwim_branch(path, &new_branch,\n+\t\t\t\t\t    &checkout_existing_branch);\n \t\tif (s)\n \t\t\tbranch = s;\n \t}\n@@ -464,6 +478,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tif (run_command(&cp))\n \t\t\treturn -1;\n \t\tbranch = new_branch;\n+\t} else if (checkout_existing_branch) {\n+\t\t  fprintf_ln(stderr, _(\"Checking out branch '%s'\"), branch);\n \t} else if (opt_track) {\n \t\tdie(_(\"--[no-]track can only be used if a new branch is created\"));\n \t}\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..f72cb0eb0b 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,24 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n-\ttest_commit c1 &&\n-\ttest_commit c2 &&\n-\tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n-\ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+test_expect_success '\"add\" checks out existing branch of dwimd name' '\n+\tgit branch dwim HEAD~1 &&\n+\tgit worktree add dwim &&\n+\ttest_cmp_rev HEAD~1 dwim &&\n+\t(\n+\t\tcd dwim &&\n+\t\ttest_cmp_rev dwim HEAD\n+\t)\n+'\n+\n+test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n+'\n+\n+test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n+\tgit worktree add --force test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.16.1.78.ga2082135d8\n\n"},{"id":"343533","messageId":"20180331151804.30380-5-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"[PATCH v6 4/6] worktree: be clearer when \"add\" dwim-ery kicks in","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-31T15:18:02Z","receivedAt":"2018-03-31T15:15:07Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently there is no indication in the \"git worktree add\" output that\na new branch was created.  This would be especially useful information\nin the case where the dwim of \"git worktree add <path>\" kicks in, as the\nuser didn't explicitly ask for a new branch, but we create one for them.\n\nPrint some additional output showing that a branch was created and the\nbranch name to help the user.\n\nThis will also be useful in a subsequent commit, which introduces a new\nkind of dwim-ery of checking out the branch if it exists instead of\nrefusing to create a new worktree in that case, and where it's nice to\ntell the user which kind of dwim-ery kicked in.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex cc94325886..f686ee1440 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -444,6 +444,8 @@ static int add(int ac, const char **av, const char *prefix)\n \n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\n+\t\tfprintf_ln(stderr, _(\"Creating branch '%s'\"), new_branch);\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n \t\tif (new_branch_force)\n-- \n2.16.1.78.ga2082135d8\n\n"},{"id":"343534","messageId":"20180331151804.30380-6-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"[PATCH v6 5/6] worktree: factor out dwim_branch function","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-03-31T15:18:03Z","receivedAt":"2018-03-31T15:15:08Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Factor out a dwim_branch function, which takes care of the dwim'ery in\n'git worktree add <path>'.  It's not too much code currently, but we're\nadding a new kind of dwim in a subsequent patch, at which point it makes\nmore sense to have it as a separate function.\n\nFactor it out now to reduce the patch noise in the next patch.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 27 +++++++++++++++++----------\n 1 file changed, 17 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex f686ee1440..47189d50dd 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -363,6 +363,20 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static const char *dwim_branch(const char *path, const char **new_branch)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\t*new_branch = xstrndup(s, n);\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(*new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -415,16 +429,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\tnew_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n-\t\t}\n+\t\tconst char *s = dwim_branch(path, &new_branch);\n+\t\tif (s)\n+\t\t\tbranch = s;\n \t}\n \n \tif (ac == 2 && !new_branch && !opts.detach) {\n-- \n2.16.1.78.ga2082135d8\n\n"},{"id":"343552","messageId":"20180401131138.GE2629@hank","threadId":"47657","inReplyTo":"20180331151804.30380-7-t.gummerer@gmail.com","subject":"[PATCH v6 6.5/6] fixup! worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-01T13:11:38Z","receivedAt":"2018-04-01T13:08:20Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n\nSo while playing with it a bit more I found one case where the new UI\nis not ideal and a bit confusing.  Namely when the new check out dwim\nkicks in, but there is already a file/directory at the path we're\ngiving to 'git worktree add'.\n\nIn that case something like the following would be printed:\n\n    $ g worktree add ../next\n    Checking out branch 'next'\n    fatal: '../next' already exists\n\nInstead I think we'd just want the error without the \"Checking out\nbranch\" message, which is what this fixup here does.\n\nOne thing that gets a bit strange is that the \"Checking out branch\"\nmessage and the \"Creating branch\" messages are printed from different\nplaces.  But without doing quite some refactoring I don't think\nthere's a good way to do that, and I think having the UI do the right\nthing is more important.\n\nOne thing I also noticed is that if a branch is created by 'git\nworktree add', but we fail, we never clean up that branch again, which\nI'm not sure is ideal.  As a pre-existing problem I'd like to keep\nfixing that out of the scope of this series though (at least after\nthis series the user would get some output showing that this happened,\neven when the branch is not set up to track a remote), so I'd like to\nkeep fixing that out of the scope of this series.\n\nJunio: could you please squash this in in 6/6 while queuing?  I'd\nprefer not to re-send the whole series just for fixing this up, but\nobviously can if that makes your life easier :)\n\nThanks!\n\n builtin/worktree.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 511d0aa370..ccc2e63e0f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -27,6 +27,7 @@ struct add_opts {\n \tint detach;\n \tint checkout;\n \tint keep_locked;\n+\tint checkout_existing_branch;\n };\n \n static int show_only;\n@@ -316,6 +317,8 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n+\tif (opts->checkout_existing_branch)\n+\t\t  fprintf_ln(stderr, _(\"Checking out branch '%s'\"), refname);\n \tif (opts->checkout) {\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n@@ -397,7 +400,6 @@ static int add(int ac, const char **av, const char *prefix)\n \tconst char *branch;\n \tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n-\tint checkout_existing_branch = 0;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&opts.force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n \t\tOPT_STRING('b', NULL, &new_branch, N_(\"branch\"),\n@@ -443,7 +445,7 @@ static int add(int ac, const char **av, const char *prefix)\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n \t\tconst char *s = dwim_branch(path, &new_branch,\n-\t\t\t\t\t    &checkout_existing_branch);\n+\t\t\t\t\t    &opts.checkout_existing_branch);\n \t\tif (s)\n \t\t\tbranch = s;\n \t}\n@@ -478,8 +480,6 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tif (run_command(&cp))\n \t\t\treturn -1;\n \t\tbranch = new_branch;\n-\t} else if (checkout_existing_branch) {\n-\t\t  fprintf_ln(stderr, _(\"Checking out branch '%s'\"), branch);\n \t} else if (opt_track) {\n \t\tdie(_(\"--[no-]track can only be used if a new branch is created\"));\n \t}\n-- \n2.16.1.78.g71f731ae26.dirty\n\n"},{"id":"343607","messageId":"xmqqwoxpxsfv.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"20180331151804.30380-3-t.gummerer@gmail.com","subject":"Re: [PATCH v6 2/6] reset: introduce show-new-head-line option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-02T20:29:56Z","receivedAt":"2018-04-02T20:30:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Gummerer <t.gummerer@gmail.com> writes:\n\n> Introduce a new --show-new-head-line command line option, that\n> determines whether the \"HEAD is now at ...\" message is printed or not.\n> It is enabled by default to preserve the current behaviour.\n>\n> It will be used in a subsequent commit to disable printing the \"HEAD is\n> now at ...\" line in 'git worktree add', so it can be replaced with a\n> custom one, that explains the behaviour better.\n>\n> We cannot just pass the --quite flag from 'git worktree add', as that\n> would also hide progress output when checking out large working trees,\n> which is undesirable.\n>\n> As this option is only for internal use, which we probably don't want\n> to advertise to our users, at least until there's a need for it, make\n> it a hidden flag.\n\nAs a temporary hack, adding something like this may be OK, but in\nthe longer run, I think we should (at least) consider refactoring\n\"reset --hard\" codepath to a freestanding and silent helper function\nso that both cmd_reset() and add_worktree() can call it and report\nthe outcome in their own phrasing.\n\nAnd I support the decision not to advertise this as a new feature or\nan option by implementing it as hidden-bool.\n\nThis is completely offtopic tangent, but I wonder how hidden-bool or\nhidden options[] element in general interacts with the recent\naddition of helping command line completion.  Are we already doing\nthe right thing?\n"},{"id":"343608","messageId":"xmqqsh8dxs86.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"20180331151804.30380-3-t.gummerer@gmail.com","subject":"Re: [PATCH v6 2/6] reset: introduce show-new-head-line option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-02T20:34:33Z","receivedAt":"2018-04-02T20:34:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Gummerer <t.gummerer@gmail.com> writes:\n\n> +test_expect_success 'reset --no-show-new-head-line suppresses \"HEAD is now at\" output' '\n> +\tgit reset --hard --no-show-new-head-line HEAD >actual &&\n> +\t! grep \"HEAD is now at\" <actual\n> +'\n\nAs builtin/reset.c::print_new_head_line() does this:\n\n\tprintf(_(\"HEAD is now at %s\"), hex);\n\nthis needs to use \"test_i18ngrep !\" instead, no?\n\n"},{"id":"343625","messageId":"20180402220741.GG2629@hank","threadId":"47657","inReplyTo":"xmqqwoxpxsfv.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v6 2/6] reset: introduce show-new-head-line option","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-02T22:07:41Z","receivedAt":"2018-04-02T21:04:18Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/02, Junio C Hamano wrote:\n> Thomas Gummerer <t.gummerer@gmail.com> writes:\n> \n> > Introduce a new --show-new-head-line command line option, that\n> > determines whether the \"HEAD is now at ...\" message is printed or not.\n> > It is enabled by default to preserve the current behaviour.\n> >\n> > It will be used in a subsequent commit to disable printing the \"HEAD is\n> > now at ...\" line in 'git worktree add', so it can be replaced with a\n> > custom one, that explains the behaviour better.\n> >\n> > We cannot just pass the --quite flag from 'git worktree add', as that\n> > would also hide progress output when checking out large working trees,\n> > which is undesirable.\n> >\n> > As this option is only for internal use, which we probably don't want\n> > to advertise to our users, at least until there's a need for it, make\n> > it a hidden flag.\n> \n> As a temporary hack, adding something like this may be OK, but in\n> the longer run, I think we should (at least) consider refactoring\n> \"reset --hard\" codepath to a freestanding and silent helper function\n> so that both cmd_reset() and add_worktree() can call it and report\n> the outcome in their own phrasing.\n\nI agree that refactoring this would have been nicer.  The biggest\nobstacle there is that the 'git reset' needs to run with a different\n\"GIT_DIR\" and \"GIT_WORK_TREE\", which is not easy to accomplish in the\ncurrent code.\n\nIt does seem like something that would be much easier once we have\n'struct repository' being passed through everywhere.  I'd rather wait\na bit more for the 'struct repository' series to land, which will\nhopefully make the refactoring easier (although I didn't have time to\nfollow the series closely).\n\n> And I support the decision not to advertise this as a new feature or\n> an option by implementing it as hidden-bool.\n> \n> This is completely offtopic tangent, but I wonder how hidden-bool or\n> hidden options[] element in general interacts with the recent\n> addition of helping command line completion.  Are we already doing\n> the right thing?\n"},{"id":"343627","messageId":"20180402220952.GH2629@hank","threadId":"47657","inReplyTo":"xmqqsh8dxs86.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v6 2/6] reset: introduce show-new-head-line option","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-02T22:09:52Z","receivedAt":"2018-04-02T21:06:29Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/02, Junio C Hamano wrote:\n> Thomas Gummerer <t.gummerer@gmail.com> writes:\n> \n> > +test_expect_success 'reset --no-show-new-head-line suppresses \"HEAD is now at\" output' '\n> > +\tgit reset --hard --no-show-new-head-line HEAD >actual &&\n> > +\t! grep \"HEAD is now at\" <actual\n> > +'\n> \n> As builtin/reset.c::print_new_head_line() does this:\n> \n> \tprintf(_(\"HEAD is now at %s\"), hex);\n> \n> this needs to use \"test_i18ngrep !\" instead, no?\n\nAh yes you're right.  Thanks for catching this.\n"},{"id":"343629","messageId":"20180402222016.GI2629@hank","threadId":"47657","inReplyTo":"xmqqwoxpxsfv.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v6 2/6] reset: introduce show-new-head-line option","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-02T22:20:16Z","receivedAt":"2018-04-02T21:16:52Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/02, Junio C Hamano wrote:\n> This is completely offtopic tangent, but I wonder how hidden-bool or\n> hidden options[] element in general interacts with the recent\n> addition of helping command line completion.  Are we already doing\n> the right thing?\n\nI had a quick look at this, and it looks like we're doing the right\nthing here.  The following snipped from the 'show_gitcomp' function in\nparse-options.c:\n\n\n>\tfor (; opts->type != OPTION_END; opts++) {\n>\t\tconst char *suffix = \"\";\n>\n>\t\tif (!opts->long_name)\n>\t\t\tcontinue;\n>\t\tif (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))\n>\t\t\tcontinue;\n\nSo if the PARSE_OPT_HIDDEN flag is given, we skip printing the option,\nwhich seems like the right thing to do.\n"},{"id":"344087","messageId":"CAPig+cQ8VzDycUMo-QOexNDBgQGEGj2BPmPa-Y0vhGCt_brbhg@mail.gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-08T09:08:52Z","receivedAt":"2018-04-08T09:08:58Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 31, 2018 at 11:17 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> This round should fix all the UI issues Eric found in the last round.\n> The changes I made in a bit more detail:\n>\n> - added a new commit introducing a new hidden --show-new-head-line\n>   flag in 'git reset'.  This is used to suppress the \"HEAD is now at\n>   ...\"  line that 'git reset --hard' usually prints, so we can replace\n>   it with our own \"New worktree HEAD is now at ...\" line instead,\n>   while keeping the progress indicator for larger repositories.\n\nAs with Junio, I'm fine with this hidden option (for now), however, I\nthink you can take this a step further. Rather than having a (hidden)\ngit-reset option which suppresses \"HEAD is now at...\", instead have a\n(hidden) option which augments the message. For example,\n--new-head-desc=\"New worktree\" would make it output \"New worktree HEAD\nis now at...\". Changes to builtin/reset.c to support this would hardly\nbe larger than the changes you already made.\n\nThe major benefit is that patch 3/6 no longer has to duplicate the\ncode from builtin/reset.c:print_new_head_line() just to print its own\n\"New worktree HEAD is now at...\" message. (As for the argument that\n\"git worktree add\" must duplicate that code because it wants the\nmessage on stderr, whereas git-reset prints it to stdout, I don't see\nwhy git-worktree puts those messages to stderr in the first place. As\nfar as I can tell, it would be equally valid to print them to stdout.)\n\n> Some examples of the new UI behaviour here for reference:\n>\n>  - guess-remote mode\n>\n>     $ git worktree add --guess-remote ../next\n>     Creating branch 'next'\n>     Branch 'next' set up to track remote branch 'next' from 'origin'.\n>     New worktree HEAD is now at caa68db14 Merge branch 'sb/packfiles-in-repository' into next\n>\n>  - original dwim (create a branch based on the current HEAD)\n>\n>     $ git worktree add ../test\n>     Creating branch 'test'\n>     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n>\n>  - new dwim (check out existing branch)\n>\n>     $ git worktree add ../test\n>     Checking out branch 'test'\n>     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n>\n>  - no new branch created\n>\n>     $ git worktree add ../test2 origin/master\n>     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\nI like the \"creating\" or \"checking out\" messages we now get for all\nthe DWIM cases. I wonder if it would make sense to print \"Checkout out\nblah...\" for this case too. It's certainly not necessary since the\nuser specified <commit-ish> explicitly, but it would make the UI even\nmore consistent, and address your subsequent comment about missing\ncontext above the \"Checking out files: ...%\" line for this case.\nThoughts?\n\n> Compare this to the old UI (new dwim omitted, as there's no old\n> version of that):\n\nThanks for contrasting the new with the old. The new output is nicer\nand more helpful.\n\n> The one thing we are loosing is a context line before \"Checking out\n> files:\", if no new branch is created.  Personally I feel like that's\n> acceptable, as the user just used the 'git worktree add' command, so\n> it should be intuitive where those files are being checked out.\n"},{"id":"344088","messageId":"CAPig+cQmEHx1N1Q9in6K8n3AyUMCk1V7JyAoeXrQVNQDQdxZ0w@mail.gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-4-t.gummerer@gmail.com","subject":"Re: [PATCH v6 3/6] worktree: improve message when creating a new worktree","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-08T09:27:55Z","receivedAt":"2018-04-08T09:28:01Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 31, 2018 at 11:18 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> [...]\n> Fix these inconsistencies, and no longer show the identifier by making\n> the 'git reset --hard' call not print the \"HEAD is now at ...\" line\n> using the newly introduced flag from the previous commit, and printing\n> the message directly from the builtin command instead.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -322,12 +320,22 @@ static int add_worktree(const char *path, const char *refname,\n>                 argv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n> +               argv_array_push(&cp.args, \"--no-show-new-head-line\");\n>                 cp.env = child_env.argv;\n>                 ret = run_command(&cp);\n>                 if (ret)\n>                         goto done;\n>         }\n>\n> +       fprintf(stderr, _(\"New worktree HEAD is now at %s\"),\n> +               find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n> +\n> +       strbuf_reset(&sb);\n> +       pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n> +       if (sb.len > 0)\n> +               fprintf(stderr, \" %s\", sb.buf);\n> +       fputc('\\n', stderr);\n> +\n>         is_junk = 0;\n>         FREE_AND_NULL(junk_work_tree);\n>         FREE_AND_NULL(junk_git_dir);\n\nGenerally speaking, code such as this probably ought to be inserted\noutside of the is_junk={1,0} context in order to keep that critical\nsection as small as possible. However, as mentioned in my response to\nthe v6 cover letter[1], I think this chunk of new code can just go\naway entirely if git-reset is made to print the customized message on\ngit-worktree's behalf.\n\n[1]: https://public-inbox.org/git/CAPig+cQ8VzDycUMo-QOexNDBgQGEGj2BPmPa-Y0vhGCt_brbhg@mail.gmail.com/\n"},{"id":"344093","messageId":"CAPig+cSRa=HQkBKXoNNf2tW+c_j5mPKu2NHTUGXxyd6qsLzcnQ@mail.gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-7-t.gummerer@gmail.com","subject":"Re: [PATCH v6 6/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-08T10:09:49Z","receivedAt":"2018-04-08T10:09:56Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 31, 2018 at 11:18 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> [...]\n> However we can do a little better than that, and check the branch out if\n> it is not checked out anywhere else.  This will help users who just want\n> to check an existing branch out into a new worktree, and save a few\n> keystrokes.\n> [...]\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\n> @@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n>  If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n> +then, as a convenience, a worktree with a branch named after\n> +`$(basename <path>)` (call it `<branch>`) is created.\n\nI had a hard time digesting this. I _think_ it wants to say:\n\n    If `<commit-ish>` is omitted and neither `-b` nor `-B` nor\n    `--detach` is used, then, as a convenience, the new worktree is\n    associated with a branch (call it `<branch>`) named after\n    `$(basename <path>)`.\n\n>  If `<branch>`\n> +doesn't exist, a new branch based on HEAD is automatically created as\n> +if `-b <branch>` was given.  If `<branch>` exists in the repository,\n\nMaybe: s/exists in the repository/does exist/\nOr: s/.../is a local branch/\n\nThough, the latter may be getting too pedantic.\n\n> +it will be checked out in the new worktree, if it's not checked out\n> +anywhere else, otherwise the command will refuse to create the\n> +worktree (unless `--force` is used).\n> diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> @@ -198,13 +198,24 @@ test_expect_success '\"add\" with <branch> omitted' '\n> +test_expect_success '\"add\" checks out existing branch of dwimd name' '\n> +       git branch dwim HEAD~1 &&\n> +       git worktree add dwim &&\n> +       test_cmp_rev HEAD~1 dwim &&\n> +       (\n> +               cd dwim &&\n> +               test_cmp_rev dwim HEAD\n\nNit: Argument order of the two test_cmp_rev() invocations differs.\n\n> +       )\n> +'\n> +\n> +test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n> +       git checkout -b test-branch &&\n> +       test_must_fail git worktree add test-branch &&\n> +       test_path_is_missing test-branch\n> +'\n> +\n> +test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n> +       git worktree add --force test-branch\n>  '\n\nMaybe make this last test slightly more robust by having it \"git\ncheckout test-branch\" before \"git worktree add ...\" to protect against\nsomeone inserting a new test (which checks out some other branch)\nbetween these two. Probably not worth a re-roll.\n"},{"id":"344108","messageId":"20180408142417.GJ2629@hank","threadId":"47657","inReplyTo":"CAPig+cQ8VzDycUMo-QOexNDBgQGEGj2BPmPa-Y0vhGCt_brbhg@mail.gmail.com","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-08T14:24:17Z","receivedAt":"2018-04-08T14:24:21Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/08, Eric Sunshine wrote:\n> On Sat, Mar 31, 2018 at 11:17 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > This round should fix all the UI issues Eric found in the last round.\n> > The changes I made in a bit more detail:\n> >\n> > - added a new commit introducing a new hidden --show-new-head-line\n> >   flag in 'git reset'.  This is used to suppress the \"HEAD is now at\n> >   ...\"  line that 'git reset --hard' usually prints, so we can replace\n> >   it with our own \"New worktree HEAD is now at ...\" line instead,\n> >   while keeping the progress indicator for larger repositories.\n> \n> As with Junio, I'm fine with this hidden option (for now), however, I\n> think you can take this a step further. Rather than having a (hidden)\n> git-reset option which suppresses \"HEAD is now at...\", instead have a\n> (hidden) option which augments the message. For example,\n> --new-head-desc=\"New worktree\" would make it output \"New worktree HEAD\n> is now at...\". Changes to builtin/reset.c to support this would hardly\n> be larger than the changes you already made.\n> \n> The major benefit is that patch 3/6 no longer has to duplicate the\n> code from builtin/reset.c:print_new_head_line() just to print its own\n> \"New worktree HEAD is now at...\" message. (As for the argument that\n> \"git worktree add\" must duplicate that code because it wants the\n> message on stderr, whereas git-reset prints it to stdout, I don't see\n> why git-worktree puts those messages to stderr in the first place. As\n> far as I can tell, it would be equally valid to print them to stdout.)\n\nI didn't think of that, but I think that's nicer indeed.  Will change.\nThis will also be nicer when we're in a position to remove the hidden\noption and do all of this with internal functions.  Then we can just\nre-use the new function that also takes a prefix at that point (after\nmoving the function to 'libgit.a' of course.\n\n> > Some examples of the new UI behaviour here for reference:\n> >\n> >  - guess-remote mode\n> >\n> >     $ git worktree add --guess-remote ../next\n> >     Creating branch 'next'\n> >     Branch 'next' set up to track remote branch 'next' from 'origin'.\n> >     New worktree HEAD is now at caa68db14 Merge branch 'sb/packfiles-in-repository' into next\n> >\n> >  - original dwim (create a branch based on the current HEAD)\n> >\n> >     $ git worktree add ../test\n> >     Creating branch 'test'\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> >\n> >  - new dwim (check out existing branch)\n> >\n> >     $ git worktree add ../test\n> >     Checking out branch 'test'\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> >\n> >  - no new branch created\n> >\n> >     $ git worktree add ../test2 origin/master\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> \n> I like the \"creating\" or \"checking out\" messages we now get for all\n> the DWIM cases. I wonder if it would make sense to print \"Checkout out\n> blah...\" for this case too. It's certainly not necessary since the\n> user specified <commit-ish> explicitly, but it would make the UI even\n> more consistent, and address your subsequent comment about missing\n> context above the \"Checking out files: ...%\" line for this case.\n> Thoughts?\n\nLet me think through some of the cases here, of 'git worktre add\n<path> <commit-ish>' with various flags and what the UI would be with\nthat added:\n\n  - no flags:\n\n    $ git worktree add ../test origin/master\n    Checking out 'origin/master'\n    Checking out files: ...%\n    New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n  - -b branch:\n\n    $ git worktree add -b test ../test origin/master\n    Creating branch 'test'\n    Checking out 'origin/master'\n    Checking out files: ...%\n    New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n    Would we want to omit the \"Checking out ...\" here?  I'm leaning\n    towards yes, but dunno?\n\n  - --no-checkout\n\n    $ git worktree add --no-checkout test ../test origin/master\n    New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n  - Original dwim with --detach flag\n\n    $ git worktree add --detach ../test\n    Checking out 'c2a499e6c'\n    Checking out files: ...%\n    New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\nLooking at this, I'm not sure what's best here.  I'm not sure I'm a\nfan of the duplicate \"Checking out \" message (I assume that's what you\nmeant above, or did you mean just \"Checkout ...\"?)\n\nI als don't think it gives too much context compared to just \"Checking\nout files: ...%\".  I think it gives a bit more context when that\nmessage is not displayed at all, as it shows whether files are checked\nout or not, but if we do that, when we create a new branch, the amount\nof output we'd display is getting a bit long, to the point where I\nsuspect users would just not read it anymore.\n\nSo I personally don't feel like this is worth it, even though it may\ngive some context in some cases.  But I'm also far from an expert in\nUI design, so if you (or others) feel this would be nicer I'm happy to\nimplement it :)\n\n> > Compare this to the old UI (new dwim omitted, as there's no old\n> > version of that):\n> \n> Thanks for contrasting the new with the old. The new output is nicer\n> and more helpful.\n> \n> > The one thing we are loosing is a context line before \"Checking out\n> > files:\", if no new branch is created.  Personally I feel like that's\n> > acceptable, as the user just used the 'git worktree add' command, so\n> > it should be intuitive where those files are being checked out.\n"},{"id":"344109","messageId":"20180408143034.GK2629@hank","threadId":"47657","inReplyTo":"CAPig+cSRa=HQkBKXoNNf2tW+c_j5mPKu2NHTUGXxyd6qsLzcnQ@mail.gmail.com","subject":"Re: [PATCH v6 6/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-08T14:30:34Z","receivedAt":"2018-04-08T14:30:37Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/08, Eric Sunshine wrote:\n> On Sat, Mar 31, 2018 at 11:18 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > [...]\n> > However we can do a little better than that, and check the branch out if\n> > it is not checked out anywhere else.  This will help users who just want\n> > to check an existing branch out into a new worktree, and save a few\n> > keystrokes.\n> > [...]\n> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> > ---\n> > diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\n> > @@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n> >  If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n> > +then, as a convenience, a worktree with a branch named after\n> > +`$(basename <path>)` (call it `<branch>`) is created.\n> \n> I had a hard time digesting this. I _think_ it wants to say:\n> \n>     If `<commit-ish>` is omitted and neither `-b` nor `-B` nor\n>     `--detach` is used, then, as a convenience, the new worktree is\n>     associated with a branch (call it `<branch>`) named after\n>     `$(basename <path>)`.\n\nYeah, this is what it wants to say, and what you have sounds much\nnicer, will change.\n\n> >  If `<branch>`\n> > +doesn't exist, a new branch based on HEAD is automatically created as\n> > +if `-b <branch>` was given.  If `<branch>` exists in the repository,\n> \n> Maybe: s/exists in the repository/does exist/\n> Or: s/.../is a local branch/\n> \n> Though, the latter may be getting too pedantic.\n> \n> > +it will be checked out in the new worktree, if it's not checked out\n> > +anywhere else, otherwise the command will refuse to create the\n> > +worktree (unless `--force` is used).\n> > diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> > @@ -198,13 +198,24 @@ test_expect_success '\"add\" with <branch> omitted' '\n> > +test_expect_success '\"add\" checks out existing branch of dwimd name' '\n> > +       git branch dwim HEAD~1 &&\n> > +       git worktree add dwim &&\n> > +       test_cmp_rev HEAD~1 dwim &&\n> > +       (\n> > +               cd dwim &&\n> > +               test_cmp_rev dwim HEAD\n> \n> Nit: Argument order of the two test_cmp_rev() invocations differs.\n> \n> > +       )\n> > +'\n> > +\n> > +test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n> > +       git checkout -b test-branch &&\n> > +       test_must_fail git worktree add test-branch &&\n> > +       test_path_is_missing test-branch\n> > +'\n> > +\n> > +test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n> > +       git worktree add --force test-branch\n> >  '\n> \n> Maybe make this last test slightly more robust by having it \"git\n> checkout test-branch\" before \"git worktree add ...\" to protect against\n> someone inserting a new test (which checks out some other branch)\n> between these two. Probably not worth a re-roll.\n\nAs I'll have to re-roll anyway for the other suggestions, I'll change\nthis as well.\n\nThanks for your review!\n"},{"id":"344135","messageId":"CAPig+cRYgLwLZnXeOc2VWBmh8j_AxSGmf2x-DJ1kAbY3BzsAPQ@mail.gmail.com","threadId":"47657","inReplyTo":"20180401131138.GE2629@hank","subject":"Re: [PATCH v6 6.5/6] fixup! worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-09T00:23:31Z","receivedAt":"2018-04-09T00:23:39Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Apr 1, 2018 at 9:11 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> So while playing with it a bit more I found one case where the new UI\n> is not ideal and a bit confusing.  Namely when the new check out dwim\n> kicks in, but there is already a file/directory at the path we're\n> giving to 'git worktree add'.\n>\n> In that case something like the following would be printed:\n>\n>     $ g worktree add ../next\n>     Checking out branch 'next'\n>     fatal: '../next' already exists\n>\n> Instead I think we'd just want the error without the \"Checking out\n> branch\" message, which is what this fixup here does.\n\nDoesn't the same UI \"problem\" exist when it creates a new branch?\n\n    $ git worktree add ../dwim\n    Creating branch 'dwim'\n    fatal: '../dwim' already exists\n\nAs you mention below, we don't (yet) clean up the newly-created branch\nupon failure, so we can't suppress the \"Creating branch\" message as\nyou suppress the \"Checking out branch\" message above (since the user\nneeds to know that the new branch exists).\n\nThis is making me wonder if \"Checking out branch\" is perhaps the wrong\nterminology. What if it said something like this instead:\n\n    $ git worktree add ../next\n    Preparing worktree (branch 'next' <= 'origin/next')\n    fatal: '../next' already exists\n\n    $ git worktree add ../gobble\n    Preparing worktree (new branch 'gobble')\n    fatal: '../gobble' already exists\n\nThis way, we don't need the special case added by this \"fixup!\" patch.\n(I'm not wedded to the \"Preparing\" message but just used it as an\nexample; better suggestions welcome.)\n\n> One thing that gets a bit strange is that the \"Checking out branch\"\n> message and the \"Creating branch\" messages are printed from different\n> places.  But without doing quite some refactoring I don't think\n> there's a good way to do that, and I think having the UI do the right\n> thing is more important.\n\nThe implementation is getting rather ugly, though, especially with\nthese messages being printed by different bits of code like this.\nworktree.c:add_worktree() was supposed to be the low-level worker; it\nwasn't intended for it to take on UI duties like this \"fixup!\" makes\nit do. UI should be handled by worktree.c:add().\n\nTaking the above \"Preparing...\" idea into consideration, then it\nshould be possible to sidestep this implementation ugliness, I would\nthink.\n\n> One thing I also noticed is that if a branch is created by 'git\n> worktree add', but we fail, we never clean up that branch again, which\n> I'm not sure is ideal.  As a pre-existing problem I'd like to keep\n> fixing that out of the scope of this series though (at least after\n> this series the user would get some output showing that this happened,\n> even when the branch is not set up to track a remote), so I'd like to\n> keep fixing that out of the scope of this series.\n\nNice idea, but outside the scope of this series, as you mention.\n\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -27,6 +27,7 @@ struct add_opts {\n>         int keep_locked;\n> +       int checkout_existing_branch;\n>  };\n> @@ -316,6 +317,8 @@ static int add_worktree(const char *path, const char *refname,\n> +       if (opts->checkout_existing_branch)\n> +                 fprintf_ln(stderr, _(\"Checking out branch '%s'\"), refname);\n>         if (opts->checkout) {\n\nI'd have expected to see the \"if (opts->checkout_existing_branch)\nfprintf_ln(...)\" inside the following \"if (opts->checkout)\"\nconditional, though, as noted above, I'm not entirely happy about\nworktree.c:add_worktree() taking on UI duties.\n\n>                 cp.argv = NULL;\n>                 argv_array_clear(&cp.args);\n"},{"id":"344136","messageId":"CAPig+cSGxMgEwqXDb4-_AWbdvm5=x-dgwi4mKqDbNfex2KDm0Q@mail.gmail.com","threadId":"47657","inReplyTo":"20180408142417.GJ2629@hank","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-09T00:38:12Z","receivedAt":"2018-04-09T00:38:18Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Apr 8, 2018 at 10:24 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> On 04/08, Eric Sunshine wrote:\n>> On Sat, Mar 31, 2018 at 11:17 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Let me think through some of the cases here, of 'git worktre add\n> <path> <commit-ish>' with various flags and what the UI would be with\n> that added:\n>\n>   - no flags:\n>\n>     $ git worktree add ../test origin/master\n>     Checking out 'origin/master'\n>     Checking out files: ...%\n>     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n>\n>   - -b branch:\n>\n>     $ git worktree add -b test ../test origin/master\n>     Creating branch 'test'\n>     Checking out 'origin/master'\n\nDid you mean \"Checking out 'test'\"?\n\n>     Checking out files: ...%\n>     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n>\n>     Would we want to omit the \"Checking out ...\" here?  I'm leaning\n>     towards yes, but dunno?\n\nTo which \"Checking out\" message do you refer, the one showing the\nbranch name or the one showing the checkout progress?\n\nI'd probably agree that showing both \"Creating\" and \"Checkout out\" is\noverkill. However, see my response[1] to your \"fixup!\" patch in which\nI explore the idea that unifying \"Checking out 'branch' and \"Creating\nbranch\" messages may be a good idea and get us out of some UI jams\nwhich seem to be cropping up.\n\n[1]: https://public-inbox.org/git/20180325134947.25828-1-t.gummerer@gmail.com/T/#m5d38b0c6427609e8c36aa6af83d518791c1e1581\n\n>   - Original dwim with --detach flag\n>\n>     $ git worktree add --detach ../test\n>     Checking out 'c2a499e6c'\n>     Checking out files: ...%\n>     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n>\n> Looking at this, I'm not sure what's best here.  I'm not sure I'm a\n> fan of the duplicate \"Checking out \" message (I assume that's what you\n> meant above, or did you mean just \"Checkout ...\"?)\n\nTaking [1] into account, this might become something like:\n\n    $ git worktree add --detach ../test\n    Preparing worktree (detached HEAD c2a499e6c)\n    Checking out files: ...%\n    New worktree HEAD is now at c2a499e6c Gobbledygook\n\n> I als don't think it gives too much context compared to just \"Checking\n> out files: ...%\".  I think it gives a bit more context when that\n> message is not displayed at all, as it shows whether files are checked\n> out or not, but if we do that, when we create a new branch, the amount\n> of output we'd display is getting a bit long, to the point where I\n> suspect users would just not read it anymore.\n>\n> So I personally don't feel like this is worth it, even though it may\n> give some context in some cases.\n\nFair enough observation. The idea suggested in [1] may keep output to\na reasonable amount.\n"},{"id":"344226","messageId":"20180409193007.GL2629@hank","threadId":"47657","inReplyTo":"CAPig+cQ8VzDycUMo-QOexNDBgQGEGj2BPmPa-Y0vhGCt_brbhg@mail.gmail.com","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-09T19:30:07Z","receivedAt":"2018-04-09T19:30:26Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/08, Eric Sunshine wrote:\n> On Sat, Mar 31, 2018 at 11:17 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > This round should fix all the UI issues Eric found in the last round.\n> > The changes I made in a bit more detail:\n> >\n> > - added a new commit introducing a new hidden --show-new-head-line\n> >   flag in 'git reset'.  This is used to suppress the \"HEAD is now at\n> >   ...\"  line that 'git reset --hard' usually prints, so we can replace\n> >   it with our own \"New worktree HEAD is now at ...\" line instead,\n> >   while keeping the progress indicator for larger repositories.\n> \n> As with Junio, I'm fine with this hidden option (for now), however, I\n> think you can take this a step further. Rather than having a (hidden)\n> git-reset option which suppresses \"HEAD is now at...\", instead have a\n> (hidden) option which augments the message. For example,\n> --new-head-desc=\"New worktree\" would make it output \"New worktree HEAD\n> is now at...\". Changes to builtin/reset.c to support this would hardly\n> be larger than the changes you already made.\n\nSomething else I just noticed that may make this a worse solution is\nthat this breaks the sentence in two pieces for translators.  I guess\nwe could somehow get the \"New worktree\" part of the option translated,\nbut that still means that if some language would require to move parts\nof the sentence around that would be less than ideal for translation.\n\nDuy pointed this out to me in an earlier patch series, and I think we\nshould probably not make life harder (or impossible) for translators\nif we can avoid it.\n\nWould factoring out what we have in 'print_new_head_line()' into some\ncommon code, maybe in 'pretty.c', and still doing the printing from\nhere be a reasonable tradeoff?\n\nI think this could potentially even be re-used in other places,\nalthough again I'd like to keep that for a followup series to avoid\nscope creep in this one.\n\n> The major benefit is that patch 3/6 no longer has to duplicate the\n> code from builtin/reset.c:print_new_head_line() just to print its own\n> \"New worktree HEAD is now at...\" message. (As for the argument that\n> \"git worktree add\" must duplicate that code because it wants the\n> message on stderr, whereas git-reset prints it to stdout, I don't see\n> why git-worktree puts those messages to stderr in the first place. As\n> far as I can tell, it would be equally valid to print them to stdout.)\n> \n> > Some examples of the new UI behaviour here for reference:\n> >\n> >  - guess-remote mode\n> >\n> >     $ git worktree add --guess-remote ../next\n> >     Creating branch 'next'\n> >     Branch 'next' set up to track remote branch 'next' from 'origin'.\n> >     New worktree HEAD is now at caa68db14 Merge branch 'sb/packfiles-in-repository' into next\n> >\n> >  - original dwim (create a branch based on the current HEAD)\n> >\n> >     $ git worktree add ../test\n> >     Creating branch 'test'\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> >\n> >  - new dwim (check out existing branch)\n> >\n> >     $ git worktree add ../test\n> >     Checking out branch 'test'\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> >\n> >  - no new branch created\n> >\n> >     $ git worktree add ../test2 origin/master\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> \n> I like the \"creating\" or \"checking out\" messages we now get for all\n> the DWIM cases. I wonder if it would make sense to print \"Checkout out\n> blah...\" for this case too. It's certainly not necessary since the\n> user specified <commit-ish> explicitly, but it would make the UI even\n> more consistent, and address your subsequent comment about missing\n> context above the \"Checking out files: ...%\" line for this case.\n> Thoughts?\n> \n> > Compare this to the old UI (new dwim omitted, as there's no old\n> > version of that):\n> \n> Thanks for contrasting the new with the old. The new output is nicer\n> and more helpful.\n> \n> > The one thing we are loosing is a context line before \"Checking out\n> > files:\", if no new branch is created.  Personally I feel like that's\n> > acceptable, as the user just used the 'git worktree add' command, so\n> > it should be intuitive where those files are being checked out.\n"},{"id":"344228","messageId":"20180409194405.GM2629@hank","threadId":"47657","inReplyTo":"CAPig+cRYgLwLZnXeOc2VWBmh8j_AxSGmf2x-DJ1kAbY3BzsAPQ@mail.gmail.com","subject":"Re: [PATCH v6 6.5/6] fixup! worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-09T19:44:05Z","receivedAt":"2018-04-09T19:44:12Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/08, Eric Sunshine wrote:\n> On Sun, Apr 1, 2018 at 9:11 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > So while playing with it a bit more I found one case where the new UI\n> > is not ideal and a bit confusing.  Namely when the new check out dwim\n> > kicks in, but there is already a file/directory at the path we're\n> > giving to 'git worktree add'.\n> >\n> > In that case something like the following would be printed:\n> >\n> >     $ g worktree add ../next\n> >     Checking out branch 'next'\n> >     fatal: '../next' already exists\n> >\n> > Instead I think we'd just want the error without the \"Checking out\n> > branch\" message, which is what this fixup here does.\n> \n> Doesn't the same UI \"problem\" exist when it creates a new branch?\n> \n>     $ git worktree add ../dwim\n>     Creating branch 'dwim'\n>     fatal: '../dwim' already exists\n> \n> As you mention below, we don't (yet) clean up the newly-created branch\n> upon failure, so we can't suppress the \"Creating branch\" message as\n> you suppress the \"Checking out branch\" message above (since the user\n> needs to know that the new branch exists).\n> \n> This is making me wonder if \"Checking out branch\" is perhaps the wrong\n> terminology. What if it said something like this instead:\n> \n>     $ git worktree add ../next\n>     Preparing worktree (branch 'next' <= 'origin/next')\n>     fatal: '../next' already exists\n> \n>     $ git worktree add ../gobble\n>     Preparing worktree (new branch 'gobble')\n>     fatal: '../gobble' already exists\n> \n> This way, we don't need the special case added by this \"fixup!\" patch.\n> (I'm not wedded to the \"Preparing\" message but just used it as an\n> example; better suggestions welcome.)\n\nYeah, I think this looks like another improvement of what I currently\nhave.  I'm not sure about the \"(branch 'next' <= 'origin/next')\"\nmessage though, as it doesn't cover all the ways the branch could be\nset up for tracking the remote branch, e.g. tracking by rebasing, when\n'branch.autosetuprebase' is set up.\n\nBut how about just \"Preparing worktree (new branch 'next')\", and then\nkeeping the message from 'git branch' about setting up the remote\ntracking branch?\n\n> > One thing that gets a bit strange is that the \"Checking out branch\"\n> > message and the \"Creating branch\" messages are printed from different\n> > places.  But without doing quite some refactoring I don't think\n> > there's a good way to do that, and I think having the UI do the right\n> > thing is more important.\n> \n> The implementation is getting rather ugly, though, especially with\n> these messages being printed by different bits of code like this.\n> worktree.c:add_worktree() was supposed to be the low-level worker; it\n> wasn't intended for it to take on UI duties like this \"fixup!\" makes\n> it do. UI should be handled by worktree.c:add().\n> \n> Taking the abonve \"Preparing...\" idea into consideration, then it\n> should be possible to sidestep this implementation ugliness, I would\n> think.\n> \n> > One thing I also noticed is that if a branch is created by 'git\n> > worktree add', but we fail, we never clean up that branch again, which\n> > I'm not sure is ideal.  As a pre-existing problem I'd like to keep\n> > fixing that out of the scope of this series though (at least after\n> > this series the user would get some output showing that this happened,\n> > even when the branch is not set up to track a remote), so I'd like to\n> > keep fixing that out of the scope of this series.\n> \n> Nice idea, but outside the scope of this series, as you mention.\n> \n> > diff --git a/builtin/worktree.c b/builtin/worktree.c\n> > @@ -27,6 +27,7 @@ struct add_opts {\n> >         int keep_locked;\n> > +       int checkout_existing_branch;\n> >  };\n> > @@ -316,6 +317,8 @@ static int add_worktree(const char *path, const char *refname,\n> > +       if (opts->checkout_existing_branch)\n> > +                 fprintf_ln(stderr, _(\"Checking out branch '%s'\"), refname);\n> >         if (opts->checkout) {\n> \n> I'd have expected to see the \"if (opts->checkout_existing_branch)\n> fprintf_ln(...)\" inside the following \"if (opts->checkout)\"\n> conditional, though, as noted above, I'm not entirely happy about\n> worktree.c:add_worktree() taking on UI duties.\n\nFair enough.  I didn't quite like the code either.  I think what you\nhave above would be much nicer, and I'll implement that in the\nre-roll.\n\n> >                 cp.argv = NULL;\n> >                 argv_array_clear(&cp.args);\n"},{"id":"344229","messageId":"20180409194723.GN2629@hank","threadId":"47657","inReplyTo":"CAPig+cSGxMgEwqXDb4-_AWbdvm5=x-dgwi4mKqDbNfex2KDm0Q@mail.gmail.com","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-09T19:47:23Z","receivedAt":"2018-04-09T19:47:27Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/08, Eric Sunshine wrote:\n> On Sun, Apr 8, 2018 at 10:24 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > On 04/08, Eric Sunshine wrote:\n> >> On Sat, Mar 31, 2018 at 11:17 AM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > Let me think through some of the cases here, of 'git worktre add\n> > <path> <commit-ish>' with various flags and what the UI would be with\n> > that added:\n> >\n> >   - no flags:\n> >\n> >     $ git worktree add ../test origin/master\n> >     Checking out 'origin/master'\n> >     Checking out files: ...%\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> >\n> >   - -b branch:\n> >\n> >     $ git worktree add -b test ../test origin/master\n> >     Creating branch 'test'\n> >     Checking out 'origin/master'\n> \n> Did you mean \"Checking out 'test'\"?\n> \n> >     Checking out files: ...%\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> >\n> >     Would we want to omit the \"Checking out ...\" here?  I'm leaning\n> >     towards yes, but dunno?\n> \n> To which \"Checking out\" message do you refer, the one showing the\n> branch name or the one showing the checkout progress?\n> \n> I'd probably agree that showing both \"Creating\" and \"Checkout out\" is\n> overkill. However, see my response[1] to your \"fixup!\" patch in which\n> I explore the idea that unifying \"Checking out 'branch' and \"Creating\n> branch\" messages may be a good idea and get us out of some UI jams\n> which seem to be cropping up.\n> \n> [1]: https://public-inbox.org/git/20180325134947.25828-1-t.gummerer@gmail.com/T/#m5d38b0c6427609e8c36aa6af83d518791c1e1581\n> \n> >   - Original dwim with --detach flag\n> >\n> >     $ git worktree add --detach ../test\n> >     Checking out 'c2a499e6c'\n> >     Checking out files: ...%\n> >     New worktree HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n> >\n> > Looking at this, I'm not sure what's best here.  I'm not sure I'm a\n> > fan of the duplicate \"Checking out \" message (I assume that's what you\n> > meant above, or did you mean just \"Checkout ...\"?)\n> \n> Taking [1] into account, this might become something like:\n> \n>     $ git worktree add --detach ../test\n>     Preparing worktree (detached HEAD c2a499e6c)\n>     Checking out files: ...%\n>     New worktree HEAD is now at c2a499e6c Gobbledygook\n\nThe more I look at this solution, the more I like it.  I'll try to\nimplement this to see if there's anything I'm not thinking of right\nnow, but I think I'll take the suggestion and send a re-roll with it\nimplemented. \n\n> > I als don't think it gives too much context compared to just \"Checking\n> > out files: ...%\".  I think it gives a bit more context when that\n> > message is not displayed at all, as it shows whether files are checked\n> > out or not, but if we do that, when we create a new branch, the amount\n> > of output we'd display is getting a bit long, to the point where I\n> > suspect users would just not read it anymore.\n> >\n> > So I personally don't feel like this is worth it, even though it may\n> > give some context in some cases.\n> \n> Fair enough observation. The idea suggested in [1] may keep output to\n> a reasonable amount.\n"},{"id":"344248","messageId":"CAPig+cTa8pwL9xveCnxtdT1zFBTmqUecqYL5Du9B6cTGAWR_dQ@mail.gmail.com","threadId":"47657","inReplyTo":"20180409194405.GM2629@hank","subject":"Re: [PATCH v6 6.5/6] fixup! worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-09T21:35:39Z","receivedAt":"2018-04-09T21:35:45Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Apr 9, 2018 at 3:44 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> On 04/08, Eric Sunshine wrote:\n>> This is making me wonder if \"Checking out branch\" is perhaps the wrong\n>> terminology. What if it said something like this instead:\n>>\n>>     $ git worktree add ../next\n>>     Preparing worktree (branch 'next' <= 'origin/next')\n>>     fatal: '../next' already exists\n>>\n>> This way, we don't need the special case added by this \"fixup!\" patch.\n>> (I'm not wedded to the \"Preparing\" message but just used it as an\n>> example; better suggestions welcome.)\n>\n> Yeah, I think this looks like another improvement of what I currently\n> have.  I'm not sure about the \"(branch 'next' <= 'origin/next')\"\n> message though, as it doesn't cover all the ways the branch could be\n> set up for tracking the remote branch, e.g. tracking by rebasing, when\n> 'branch.autosetuprebase' is set up.\n>\n> But how about just \"Preparing worktree (new branch 'next')\", and then\n> keeping the message from 'git branch' about setting up the remote\n> tracking branch?\n\nFair enough. Extra annotation (such as \"'foo' <= 'bar'\" or whatever)\ncan always be added later if someone wants it.\n"},{"id":"344250","messageId":"CAPig+cRXsir3siZ5eArk6k1mF9kaDfFe1mL+T9faR6dxSUez7w@mail.gmail.com","threadId":"47657","inReplyTo":"20180409193007.GL2629@hank","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-09T22:06:05Z","receivedAt":"2018-04-09T22:06:12Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Apr 9, 2018 at 3:30 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> On 04/08, Eric Sunshine wrote:\n>> As with Junio, I'm fine with this hidden option (for now), however, I\n>> think you can take this a step further. Rather than having a (hidden)\n>> git-reset option which suppresses \"HEAD is now at...\", instead have a\n>> (hidden) option which augments the message. For example,\n>> --new-head-desc=\"New worktree\" would make it output \"New worktree HEAD\n>> is now at...\". Changes to builtin/reset.c to support this would hardly\n>> be larger than the changes you already made.\n>\n> Something else I just noticed that may make this a worse solution is\n> that this breaks the sentence in two pieces for translators.  I guess\n> we could somehow get the \"New worktree\" part of the option translated,\n> but that still means that if some language would require to move parts\n> of the sentence around that would be less than ideal for translation.\n\nGood point.\n\nOne solution would be to have the new hidden option replace the string\nentirely: --new-head-msg=\"New worktree HEAD is now at %s\", which would\nallow translators to deal with the entire sentence. Even clearer would\nbe to drop \"now\", as in \"New worktree HEAD is at %s\". (Default in\nreset.c would still be \"HEAD is now at %s\", of course.)\n\nAnother solution would be not to augment the \"HEAD is now at...\"\nmessage at all. I realize that that augmentation was one of the\noriginal motivations for this patch series, but with the upcoming\nrestoration of the \"Preparing worktree\" message:\n\n    Preparing worktree (_branch disposition_)\n    HEAD is now at ...\n\nit seems clear enough (at least to me) from the context introduced by\nthe \"Preparing...\" message that \"HEAD is now at...\" refers to HEAD in\nthe worktree. (But that's just my opinion.)\n\n> Would factoring out what we have in 'print_new_head_line()' into some\n> common code, maybe in 'pretty.c', and still doing the printing from\n> here be a reasonable tradeoff?\n\nIsn't that getting uglier again? Not only would you have to publish\nthat function, but you'd still need the hidden git-reset\n--show-new-head-line option.\n\nAlso, you'd end up calling that function from within low-level worker\nworktree.c:add_worktree(), thus making it take on UI duties, which\nwould be nice to avoid if possible. (Unfortunately, the alternate idea\nof having worktree.c:add() handle this UI task doesn't quite work\nsince add_worktree() doesn't return sufficient information for add()\nto know whether or not it should print \"HEAD is now at...\"; however,\nadd_worktree() could be augmented to return more information.)\n\nSo, I don't presently have a good answer. I'm partial to the idea of\nnot augmenting \"HEAD is now at...\", partly because context makes it\nrelatively clear that it applies to the new worktree and partly\nbecause it's simpler (less implementation work for you) to leave it as\nis. If that choice isn't desirable, then next best would be for\n--new-head-msg= to replace the entire \"HEAD is now at...\" string\nrather than augmenting it.\n"},{"id":"344482","messageId":"20180411200955.GO2629@hank","threadId":"47657","inReplyTo":"CAPig+cRXsir3siZ5eArk6k1mF9kaDfFe1mL+T9faR6dxSUez7w@mail.gmail.com","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-11T20:09:55Z","receivedAt":"2018-04-11T20:10:05Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/09, Eric Sunshine wrote:\n> On Mon, Apr 9, 2018 at 3:30 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > On 04/08, Eric Sunshine wrote:\n> >> As with Junio, I'm fine with this hidden option (for now), however, I\n> >> think you can take this a step further. Rather than having a (hidden)\n> >> git-reset option which suppresses \"HEAD is now at...\", instead have a\n> >> (hidden) option which augments the message. For example,\n> >> --new-head-desc=\"New worktree\" would make it output \"New worktree HEAD\n> >> is now at...\". Changes to builtin/reset.c to support this would hardly\n> >> be larger than the changes you already made.\n> >\n> > Something else I just noticed that may make this a worse solution is\n> > that this breaks the sentence in two pieces for translators.  I guess\n> > we could somehow get the \"New worktree\" part of the option translated,\n> > but that still means that if some language would require to move parts\n> > of the sentence around that would be less than ideal for translation.\n> \n> Good point.\n> \n> One solution would be to have the new hidden option replace the string\n> entirely: --new-head-msg=\"New worktree HEAD is now at %s\", which would\n> allow translators to deal with the entire sentence. Even clearer would\n> be to drop \"now\", as in \"New worktree HEAD is at %s\". (Default in\n> reset.c would still be \"HEAD is now at %s\", of course.)\n> \n> Another solution would be not to augment the \"HEAD is now at...\"\n> message at all. I realize that that augmentation was one of the\n> original motivations for this patch series, but with the upcoming\n> restoration of the \"Preparing worktree\" message:\n\nMy original motivation of the series was to just make the new dwim\nwork :)  Because that's adding some magic, the secondary motivation\nbecame improving the UI, to help users see which dwim was used.  I\nfelt like this was going to be one of those improvements, especially\nafter we get rid of the \"Preparing ...\" line.\n\nI do however like your suggestion of the \"Preparing worktree (_branch\ndisposition_)\", as that doesn't add more lines to the output, while\nstill giving a good indication of what exactly is happening.  At that\npoint just showing \"HEAD is now at ...\" is fine by me, and doesn't\nrequire adding the hidden flag to 'git reset'.  So I'm happy just\ndropping the change in the message here, which will simplify things.\n\nThanks for the suggestion!\n\n>     Preparing worktree (_branch disposition_)\n>     HEAD is now at ...\n> \n> it seems clear enough (at least to me) from the context introduced by\n> the \"Preparing...\" message that \"HEAD is now at...\" refers to HEAD in\n> the worktree. (But that's just my opinion.)\n> \n> > Would factoring out what we have in 'print_new_head_line()' into some\n> > common code, maybe in 'pretty.c', and still doing the printing from\n> > here be a reasonable tradeoff?\n> \n> Isn't that getting uglier again? Not only would you have to publish\n> that function, but you'd still need the hidden git-reset\n> --show-new-head-line option.\n> \n> Also, you'd end up calling that function from within low-level worker\n> worktree.c:add_worktree(), thus making it take on UI duties, which\n> would be nice to avoid if possible. (Unfortunately, the alternate idea\n> of having worktree.c:add() handle this UI task doesn't quite work\n> since add_worktree() doesn't return sufficient information for add()\n> to know whether or not it should print \"HEAD is now at...\"; however,\n> add_worktree() could be augmented to return more information.)\n> \n> So, I don't presently have a good answer. I'm partial to the idea of\n> not augmenting \"HEAD is now at...\", partly because context makes it\n> relatively clear that it applies to the new worktree and partly\n> because it's simpler (less implementation work for you) to leave it as\n> is. If that choice isn't desirable, then next best would be for\n> --new-head-msg= to replace the entire \"HEAD is now at...\" string\n> rather than augmenting it.\n"},{"id":"344492","messageId":"CAPig+cTP6cJNmeXXbdRm3PTuq49+g9jNM-DvCJ472QrBC1CO4A@mail.gmail.com","threadId":"47657","inReplyTo":"20180411200955.GO2629@hank","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-11T20:48:09Z","receivedAt":"2018-04-11T20:48:15Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Apr 11, 2018 at 4:09 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> On 04/09, Eric Sunshine wrote:\n>> Another solution would be not to augment the \"HEAD is now at...\"\n>> message at all. I realize that that augmentation was one of the\n>> original motivations for this patch series, but with the upcoming\n>> restoration of the \"Preparing worktree\" message:\n>\n> My original motivation of the series was to just make the new dwim\n> work :)  Because that's adding some magic, the secondary motivation\n> became improving the UI, to help users see which dwim was used.  I\n> felt like this was going to be one of those improvements, especially\n> after we get rid of the \"Preparing ...\" line.\n>\n> I do however like your suggestion of the \"Preparing worktree (_branch\n> disposition_)\", as that doesn't add more lines to the output, while\n> still giving a good indication of what exactly is happening.  At that\n> point just showing \"HEAD is now at ...\" is fine by me, and doesn't\n> require adding the hidden flag to 'git reset'.  So I'm happy just\n> dropping the change in the message here, which will simplify things.\n\nNice. This sounds like a good plan for moving forward.\n"},{"id":"344493","messageId":"20180411205015.GP2629@hank","threadId":"47657","inReplyTo":"20180411200955.GO2629@hank","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-11T20:50:15Z","receivedAt":"2018-04-11T20:50:16Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/11, Thomas Gummerer wrote:\n> On 04/09, Eric Sunshine wrote:\n> > On Mon, Apr 9, 2018 at 3:30 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > > On 04/08, Eric Sunshine wrote:\n> > >> As with Junio, I'm fine with this hidden option (for now), however, I\n> > >> think you can take this a step further. Rather than having a (hidden)\n> > >> git-reset option which suppresses \"HEAD is now at...\", instead have a\n> > >> (hidden) option which augments the message. For example,\n> > >> --new-head-desc=\"New worktree\" would make it output \"New worktree HEAD\n> > >> is now at...\". Changes to builtin/reset.c to support this would hardly\n> > >> be larger than the changes you already made.\n> > >\n> > > Something else I just noticed that may make this a worse solution is\n> > > that this breaks the sentence in two pieces for translators.  I guess\n> > > we could somehow get the \"New worktree\" part of the option translated,\n> > > but that still means that if some language would require to move parts\n> > > of the sentence around that would be less than ideal for translation.\n> > \n> > Good point.\n> > \n> > One solution would be to have the new hidden option replace the string\n> > entirely: --new-head-msg=\"New worktree HEAD is now at %s\", which would\n> > allow translators to deal with the entire sentence. Even clearer would\n> > be to drop \"now\", as in \"New worktree HEAD is at %s\". (Default in\n> > reset.c would still be \"HEAD is now at %s\", of course.)\n> > \n> > Another solution would be not to augment the \"HEAD is now at...\"\n> > message at all. I realize that that augmentation was one of the\n> > original motivations for this patch series, but with the upcoming\n> > restoration of the \"Preparing worktree\" message:\n> \n> My original motivation of the series was to just make the new dwim\n> work :)  Because that's adding some magic, the secondary motivation\n> became improving the UI, to help users see which dwim was used.  I\n> felt like this was going to be one of those improvements, especially\n> after we get rid of the \"Preparing ...\" line.\n> \n> I do however like your suggestion of the \"Preparing worktree (_branch\n> disposition_)\", as that doesn't add more lines to the output, while\n> still giving a good indication of what exactly is happening.  At that\n> point just showing \"HEAD is now at ...\" is fine by me, and doesn't\n> require adding the hidden flag to 'git reset'.  So I'm happy just\n> dropping the change in the message here, which will simplify things.\n\nAnd just as I'm re-reading my commit messages, I guess there was one\nmore motivation for printing the \"HEAD is now at ...\" line ourselves:\n\n    If the '--no-checkout' flag is given, the output of 'git worktree add'\n    is just:\n    \n        Preparing foo (identifier foo)\n    \n    even though the HEAD is set to a commit, which is just not checked out.\n\nI think I can live with that for now, I personally don't use\n'--no-checkout', and we could fix this at some point in the future if\nwe desire to do so.  I think we can consider that out of scope for\nthis patch series, as its main goal is to introduce the new dwim.\n\n> Thanks for the suggestion!\n"},{"id":"344499","messageId":"CAPig+cSs1+Uxmguf7A11kZNvOagJDiSZHyETotMkcLJnbn+dNw@mail.gmail.com","threadId":"47657","inReplyTo":"20180411205015.GP2629@hank","subject":"Re: [PATCH v6 0/6] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-11T21:14:54Z","receivedAt":"2018-04-11T21:15:02Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Apr 11, 2018 at 4:50 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> And just as I'm re-reading my commit messages, I guess there was one\n> more motivation for printing the \"HEAD is now at ...\" line ourselves:\n>\n>     If the '--no-checkout' flag is given, the output of 'git worktree add'\n>     is just:\n>\n>         Preparing foo (identifier foo)\n>\n>     even though the HEAD is set to a commit, which is just not checked out.\n>\n> I think I can live with that for now, I personally don't use\n> '--no-checkout', and we could fix this at some point in the future if\n> we desire to do so.  I think we can consider that out of scope for\n> this patch series, as its main goal is to introduce the new dwim.\n\nSounds reasonable, especially since the proposed \"Preparing worktree\n(_branch description_)\" provides similarly useful feedback.\n"},{"id":"344749","messageId":"20180415202917.4360-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180331151804.30380-1-t.gummerer@gmail.com","subject":"[PATCH v7 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-15T20:29:13Z","receivedAt":"2018-04-15T20:29:24Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Thanks Eric for the review and all of the suggestions in the last\nround.\n\nPrevious rounds are at <20180121120208.12760-1-t.gummerer@gmail.com>,\n<20180204221305.28300-1-t.gummerer@gmail.com>,\n<20180317220830.30963-1-t.gummerer@gmail.com>,\n<20180317222219.4940-1-t.gummerer@gmail.com>,\n<20180325134947.25828-1-t.gummerer@gmail.com> and\n<20180331151804.30380-1-t.gummerer@gmail.com>.\n\nThe main change once again in this series is the user interface.  It\nfeels like we went in a complete circle here now, as this iteration is\nbringing the \"Preparing ...\" line back (although in a slightly\ndifferent form than the original), and is moving away from printing\nit's own \"HEAD is now at...\" line again.  This also means we don't\nneed the new hidden option to 'git reset' anymore, which is nice.\n\nI do like the new UI more than what we had in the last round (which I\nalready liked more than the original UI) :)\n\nOther than those changes, it also includes Eric's suggestion for a\nbetter wording in the documentation, fixes the argument order to\ntest_cmd_rev in a test, and makes a test more robust.\n\nTo demonstrate the UI updates, let's compare the new UI and the old UI\nagain.  This is the same commands as used for the demonstration in the\nlast iteration, so please have a look at <20180331151804.30380-1-t.gummerer@gmail.com> \nfor an example of what it looked like after the last round.\n\nNew UI:\n\n - guess-remote mode\n\n    $ git worktree add --guess-remote ../next\n    Preparing worktree (new branch 'next')\n    Branch 'next' set up to track remote branch 'next' from 'origin'.\n    HEAD is now at caa68db14 Merge branch 'sb/packfiles-in-repository' into next\n\n - original dwim (create a branch based on the current HEAD)\n\n    $ git worktree add ../test\n    Preparing worktree (new branch 'test')\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - new dwim (check out existing branch)\n\n    $ git worktree add ../test\n    Preparing worktree (checking out 'test')\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - detached HEAD\n\n    $ git worktree add ../test2 origin/master\n    Preparing worktree (detached HEAD c2a499e6c)\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - resetting existing branch\n\n    $ git worktree add -B next ../test3 origin/master\n    Preparing worktree (resetting branch 'next' (was at caa68db14))\n    Branch 'next' set up to track remote branch 'master' from 'origin'.\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n    This output is new in this round and wasn't previously discussed.\n    While working on the \"Preparing ...\" line I noticed this, and\n    thought it would be a good idea.  I feel like this fits in the\n    scope of the series quite well, as it's improving the UI, but I'm\n    happy to split it out if that's preferred.\n\n    It may also be worth displaying the title of the commit here, but\n    at that point the line would get a bit long, so dunno.\n\n - large repository (with original dwim)\n\n    $ git worktree add ../test\n    Preparing worktree (new branch 'test')\n    Checking out files: 100% (62915/62915), done.\n    HEAD is now at c2a9838452a4 Merge tag 'for-4.16/dm-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm\n\n - error when directory already exists\n\n    $ git worktree add ../test\n    Preparing worktree (checking out 'test')\n    fatal: '../test' already exists\n\nCompare this to the old UI (new dwim omitted, as there's no old\nversion of that):\n\n - guess-remote mode\n\n    $ git worktree add --guess-remote ../next\n    Branch 'next' set up to track remote branch 'next' from 'origin'.\n    Preparing ../next (identifier next)\n    HEAD is now at caa68db14 Merge branch 'sb/packfiles-in-repository' into next\n\n - original dwim (create a branch based on the current HEAD)\n\n    $ git worktree add ../test\n    Preparing ../test (identifier test)\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - no new branch created\n\n    $ git worktree add ../test2 origin/master\n    Preparing ../test2 (identifier test2)\n    HEAD is now at c2a499e6c Merge branch 'jh/partial-clone'\n\n - large repository\n\n    $ git worktree add ../test\n    Preparing ../test (identifier test)\n    Checking out files: 100% (62915/62915), done.\n    HEAD is now at c2a9838452a4 Merge tag 'for-4.16/dm-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm\n\n - error when directory already exists\n\n    $ git worktree add ../test\n    fatal: '../test' already exists\n\nInterdiff below:\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex eaa6bf713f..5d54f36a71 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,13 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a worktree with a branch named after\n-`$(basename <path>)` (call it `<branch>`) is created.  If `<branch>`\n+then, as a convenience, the new worktree is associated with a branch\n+(call it `<branch>`) named after `$(basename <path>)`.  If `<branch>`\n doesn't exist, a new branch based on HEAD is automatically created as\n-if `-b <branch>` was given.  If `<branch>` exists in the repository,\n-it will be checked out in the new worktree, if it's not checked out\n-anywhere else, otherwise the command will refuse to create the\n-worktree (unless `--force` is used).\n+if `-b <branch>` was given.  If `<branch>` does exist, it will be\n+checked out in the new worktree, if it's not checked out anywhere\n+else, otherwise the command will refuse to create the worktree (unless\n+`--force` is used).\n \n list::\n \ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 54b2576449..e15f595799 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -288,7 +288,6 @@ static int git_reset_config(const char *var, const char *value, void *cb)\n int cmd_reset(int argc, const char **argv, const char *prefix)\n {\n \tint reset_type = NONE, update_ref_status = 0, quiet = 0;\n-\tint show_new_head_line = 1;\n \tint patch_mode = 0, unborn;\n \tconst char *rev;\n \tstruct object_id oid;\n@@ -311,7 +310,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL('p', \"patch\", &patch_mode, N_(\"select hunks interactively\")),\n \t\tOPT_BOOL('N', \"intent-to-add\", &intent_to_add,\n \t\t\t\tN_(\"record only the fact that removed paths will be added later\")),\n-\t\tOPT_HIDDEN_BOOL(0, \"show-new-head-line\", &show_new_head_line, N_(\"show information on the new HEAD\")),\n \t\tOPT_END()\n \t};\n \n@@ -405,8 +403,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\t * switched to, saving the previous head in ORIG_HEAD before. */\n \t\tupdate_ref_status = reset_refs(rev, &oid);\n \n-\t\tif (reset_type == HARD && !update_ref_status && !quiet &&\n-\t\t    show_new_head_line)\n+\t\tif (reset_type == HARD && !update_ref_status && !quiet)\n \t\t\tprint_new_head_line(lookup_commit_reference(&oid));\n \t}\n \tif (!pathspec.nr)\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex ccc2e63e0f..f5a5283b39 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -27,7 +27,6 @@ struct add_opts {\n \tint detach;\n \tint checkout;\n \tint keep_locked;\n-\tint checkout_existing_branch;\n };\n \n static int show_only;\n@@ -317,28 +316,16 @@ static int add_worktree(const char *path, const char *refname,\n \tif (ret)\n \t\tgoto done;\n \n-\tif (opts->checkout_existing_branch)\n-\t\t  fprintf_ln(stderr, _(\"Checking out branch '%s'\"), refname);\n \tif (opts->checkout) {\n \t\tcp.argv = NULL;\n \t\targv_array_clear(&cp.args);\n \t\targv_array_pushl(&cp.args, \"reset\", \"--hard\", NULL);\n-\t\targv_array_push(&cp.args, \"--no-show-new-head-line\");\n \t\tcp.env = child_env.argv;\n \t\tret = run_command(&cp);\n \t\tif (ret)\n \t\t\tgoto done;\n \t}\n \n-\tfprintf(stderr, _(\"New worktree HEAD is now at %s\"),\n-\t\tfind_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));\n-\n-\tstrbuf_reset(&sb);\n-\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n-\tif (sb.len > 0)\n-\t\tfprintf(stderr, \" %s\", sb.buf);\n-\tfputc('\\n', stderr);\n-\n \tis_junk = 0;\n \tFREE_AND_NULL(junk_work_tree);\n \tFREE_AND_NULL(junk_git_dir);\n@@ -366,6 +353,34 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static void print_preparing_worktree_line(const char *branch,\n+\t\t\t\t\t  const char *new_branch,\n+\t\t\t\t\t  const char *new_branch_force,\n+\t\t\t\t\t  int checkout_existing_branch)\n+{\n+\tif (checkout_existing_branch) {\n+\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"), branch);\n+\t} else if (new_branch_force) {\n+\t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n+\t\tif (!commit)\n+\t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n+\t\telse\n+\t\t\tprintf_ln(_(\"Preparing worktree (resetting branch '%s' (was at %s))\"),\n+\t\t\t\t  new_branch_force,\n+\t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t\t     DEFAULT_ABBREV));\n+\t} else if (new_branch) {\n+\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n+\t} else {\n+\t\tstruct commit *commit = lookup_commit_reference_by_name(branch);\n+\t\tif (!commit)\n+\t\t\tdie(_(\"invalid reference: %s\"), branch);\n+\t\tprintf_ln(_(\"Preparing worktree (detached HEAD %s)\"),\n+\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t     DEFAULT_ABBREV));\n+\t}\n+}\n+\n static const char *dwim_branch(const char *path, const char **new_branch,\n \t\t\t       int *checkout_existing_branch)\n {\n@@ -397,6 +412,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tstruct add_opts opts;\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n+\tint checkout_existing_branch = 0;\n \tconst char *branch;\n \tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n@@ -445,7 +461,7 @@ static int add(int ac, const char **av, const char *prefix)\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n \t\tconst char *s = dwim_branch(path, &new_branch,\n-\t\t\t\t\t    &opts.checkout_existing_branch);\n+\t\t\t\t\t    &checkout_existing_branch);\n \t\tif (s)\n \t\t\tbranch = s;\n \t}\n@@ -465,10 +481,11 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n+\tprint_preparing_worktree_line(branch, new_branch, new_branch_force,\n+\t\t\t\t      checkout_existing_branch);\n+\n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n-\n-\t\tfprintf_ln(stderr, _(\"Creating branch '%s'\"), new_branch);\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n \t\tif (new_branch_force)\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex f72cb0eb0b..ad38507d00 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -204,7 +204,7 @@ test_expect_success '\"add\" checks out existing branch of dwimd name' '\n \ttest_cmp_rev HEAD~1 dwim &&\n \t(\n \t\tcd dwim &&\n-\t\ttest_cmp_rev dwim HEAD\n+\t\ttest_cmp_rev HEAD dwim\n \t)\n '\n \n@@ -215,6 +215,7 @@ test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n '\n \n test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n+\tgit checkout test-branch &&\n \tgit worktree add --force test-branch\n '\n \ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex a160f78aba..95653a08ca 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -568,9 +568,4 @@ test_expect_success 'reset --mixed sets up work tree' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'reset --no-show-new-head-line suppresses \"HEAD is now at\" output' '\n-\tgit reset --hard --no-show-new-head-line HEAD >actual &&\n-\t! grep \"HEAD is now at\" <actual\n-'\n-\n test_done\n\nThomas Gummerer (4):\n  worktree: remove extra members from struct add_opts\n  worktree: improve message when creating a new worktree\n  worktree: factor out dwim_branch function\n  worktree: teach \"add\" to check out existing branches\n\n Documentation/git-worktree.txt |   9 +++-\n builtin/worktree.c             | 101 ++++++++++++++++++++++++++++++-----------\n t/t2025-worktree-add.sh        |  26 ++++++++---\n 3 files changed, 100 insertions(+), 36 deletions(-)\n\n-- \n2.16.1.74.g6cd9b6cbe3\n\n"},{"id":"344750","messageId":"20180415202917.4360-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180415202917.4360-1-t.gummerer@gmail.com","subject":"[PATCH v7 1/4] worktree: remove extra members from struct add_opts","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-15T20:29:14Z","receivedAt":"2018-04-15T20:29:25Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"There are two members of 'struct add_opts', which are only used inside\nthe 'add()' function, but being part of 'struct add_opts' they are\nneedlessly also passed to the 'add_worktree' function.\n\nMake them local to the 'add()' function to make it clearer where they\nare used.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 32 +++++++++++++++-----------------\n 1 file changed, 15 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..4d96a21a45 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -27,8 +27,6 @@ struct add_opts {\n \tint detach;\n \tint checkout;\n \tint keep_locked;\n-\tconst char *new_branch;\n-\tint force_new_branch;\n };\n \n static int show_only;\n@@ -363,10 +361,11 @@ static int add(int ac, const char **av, const char *prefix)\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n \tconst char *branch;\n+\tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&opts.force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n-\t\tOPT_STRING('b', NULL, &opts.new_branch, N_(\"branch\"),\n+\t\tOPT_STRING('b', NULL, &new_branch, N_(\"branch\"),\n \t\t\t   N_(\"create a new branch\")),\n \t\tOPT_STRING('B', NULL, &new_branch_force, N_(\"branch\"),\n \t\t\t   N_(\"create or reset a branch\")),\n@@ -384,7 +383,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tmemset(&opts, 0, sizeof(opts));\n \topts.checkout = 1;\n \tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n-\tif (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1)\n+\tif (!!opts.detach + !!new_branch + !!new_branch_force > 1)\n \t\tdie(_(\"-b, -B, and --detach are mutually exclusive\"));\n \tif (ac < 1 || ac > 2)\n \t\tusage_with_options(worktree_usage, options);\n@@ -395,33 +394,32 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (!strcmp(branch, \"-\"))\n \t\tbranch = \"@{-1}\";\n \n-\topts.force_new_branch = !!new_branch_force;\n-\tif (opts.force_new_branch) {\n+\tif (new_branch_force) {\n \t\tstruct strbuf symref = STRBUF_INIT;\n \n-\t\topts.new_branch = new_branch_force;\n+\t\tnew_branch = new_branch_force;\n \n \t\tif (!opts.force &&\n-\t\t    !strbuf_check_branch_ref(&symref, opts.new_branch) &&\n+\t\t    !strbuf_check_branch_ref(&symref, new_branch) &&\n \t\t    ref_exists(symref.buf))\n \t\t\tdie_if_checked_out(symref.buf, 0);\n \t\tstrbuf_release(&symref);\n \t}\n \n-\tif (ac < 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac < 2 && !new_branch && !opts.detach) {\n \t\tint n;\n \t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n+\t\tnew_branch = xstrndup(s, n);\n \t\tif (guess_remote) {\n \t\t\tstruct object_id oid;\n \t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n+\t\t\t\tunique_tracking_name(new_branch, &oid);\n \t\t\tif (remote)\n \t\t\t\tbranch = remote;\n \t\t}\n \t}\n \n-\tif (ac == 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac == 2 && !new_branch && !opts.detach) {\n \t\tstruct object_id oid;\n \t\tstruct commit *commit;\n \t\tconst char *remote;\n@@ -430,25 +428,25 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tif (!commit) {\n \t\t\tremote = unique_tracking_name(branch, &oid);\n \t\t\tif (remote) {\n-\t\t\t\topts.new_branch = branch;\n+\t\t\t\tnew_branch = branch;\n \t\t\t\tbranch = remote;\n \t\t\t}\n \t\t}\n \t}\n \n-\tif (opts.new_branch) {\n+\tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n-\t\tif (opts.force_new_branch)\n+\t\tif (new_branch_force)\n \t\t\targv_array_push(&cp.args, \"--force\");\n-\t\targv_array_push(&cp.args, opts.new_branch);\n+\t\targv_array_push(&cp.args, new_branch);\n \t\targv_array_push(&cp.args, branch);\n \t\tif (opt_track)\n \t\t\targv_array_push(&cp.args, opt_track);\n \t\tif (run_command(&cp))\n \t\t\treturn -1;\n-\t\tbranch = opts.new_branch;\n+\t\tbranch = new_branch;\n \t} else if (opt_track) {\n \t\tdie(_(\"--[no-]track can only be used if a new branch is created\"));\n \t}\n-- \n2.17.0.252.gfe0a9eaf31\n\n"},{"id":"344751","messageId":"20180415202917.4360-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180415202917.4360-1-t.gummerer@gmail.com","subject":"[PATCH v7 3/4] worktree: factor out dwim_branch function","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-15T20:29:16Z","receivedAt":"2018-04-15T20:29:27Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Factor out a dwim_branch function, which takes care of the dwim'ery in\n'git worktree add <path>'.  It's not too much code currently, but we're\nadding a new kind of dwim in a subsequent patch, at which point it makes\nmore sense to have it as a separate function.\n\nFactor it out now to reduce the patch noise in the next patch.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 27 +++++++++++++++++----------\n 1 file changed, 17 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex a2667d74fb..893139629a 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -378,6 +378,20 @@ static void print_preparing_worktree_line(const char *branch,\n \t}\n }\n \n+static const char *dwim_branch(const char *path, const char **new_branch)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\t*new_branch = xstrndup(s, n);\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(*new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -430,16 +444,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\tnew_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n-\t\t}\n+\t\tconst char *s = dwim_branch(path, &new_branch);\n+\t\tif (s)\n+\t\t\tbranch = s;\n \t}\n \n \tif (ac == 2 && !new_branch && !opts.detach) {\n-- \n2.17.0.252.gfe0a9eaf31\n\n"},{"id":"344752","messageId":"20180415202917.4360-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180415202917.4360-1-t.gummerer@gmail.com","subject":"[PATCH v7 2/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-15T20:29:15Z","receivedAt":"2018-04-15T20:29:29Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following:\n\n    Preparing ../foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nThe '../foo' is the path where the worktree is created, which the user\nhas just given on the command line.  The identifier is an internal\nimplementation detail, which is not particularly relevant for the user\nand indeed isn't mentioned explicitly anywhere in the man page.\n\nInstead of this message, print a message that gives the user a bit more\ndetail of what exactly 'git worktree' is doing.  There are various dwim\nmodes which are perform some magic under the hood, which should be\nhelpful to users.  Just from the output of the command it is not always\nvisible to users what exactly has happened.\n\nHelp the users a bit more by modifying the \"Preparing ...\" message and\nadding some additional information of what 'git worktree add' did under\nthe hood, while not displaying the identifier anymore.\n\nCurrently this ends up in three different cases:\n\n  - 'git worktree add -b ...' or 'git worktree add <path>', both of\n    which create a new branch, either through the user explicitly\n    requesting it, or through 'git worktree add' implicitly creating\n    it.  This will end up with the following output:\n\n      Preparing worktree (new branch '<branch>')\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add -B ...', which may either create a new branch if\n    the branch with the given name does not exist yet, or resets an\n    existing branch to the current HEAD, or the commit-ish given.\n    Depending on which action is taken, we'll end up with the following\n    output:\n\n      Preparing worktree (resetting branch 'next' (was at caa68db14))\n      HEAD is now at 26da330922 <title>\n\n    or:\n\n      Preparing worktree (new branch '<branch>')\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add --detach' or 'git worktree add <path> <branch>',\n    both of which create a new worktree with a detached HEAD, for which\n    we will print the following output:\n\n      Preparing worktree (detached HEAD 26da330922)\n      HEAD is now at 26da330922 <title>\n\nAdditionally currently the \"Preparing ...\" line is printed to stderr,\nwhile the \"HEAD is now at ...\" line is printed to stdout by 'git reset\n--hard', which is used internally by 'git worktree add'.  Fix this\ninconsistency by printing the \"Preparing ...\" message to stdout as\nwell.  As \"Preparing ...\" is not an error, stdout also seems like the\nmore appropriate output stream.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 29 +++++++++++++++++++++++++++--\n 1 file changed, 27 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 4d96a21a45..a2667d74fb 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -301,8 +301,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -355,6 +353,31 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static void print_preparing_worktree_line(const char *branch,\n+\t\t\t\t\t  const char *new_branch,\n+\t\t\t\t\t  const char *new_branch_force)\n+{\n+\tif (new_branch_force) {\n+\t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n+\t\tif (!commit)\n+\t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n+\t\telse\n+\t\t\tprintf_ln(_(\"Preparing worktree (resetting branch '%s' (was at %s))\"),\n+\t\t\t\t  new_branch_force,\n+\t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t\t     DEFAULT_ABBREV));\n+\t} else if (new_branch) {\n+\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n+\t} else {\n+\t\tstruct commit *commit = lookup_commit_reference_by_name(branch);\n+\t\tif (!commit)\n+\t\t\tdie(_(\"invalid reference: %s\"), branch);\n+\t\tprintf_ln(_(\"Preparing worktree (detached HEAD %s)\"),\n+\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t     DEFAULT_ABBREV));\n+\t}\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -434,6 +457,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n+\tprint_preparing_worktree_line(branch, new_branch, new_branch_force);\n+\n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n-- \n2.17.0.252.gfe0a9eaf31\n\n"},{"id":"344753","messageId":"20180415202917.4360-5-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180415202917.4360-1-t.gummerer@gmail.com","subject":"[PATCH v7 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-15T20:29:17Z","receivedAt":"2018-04-15T20:29:31Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 30 ++++++++++++++++++++++++------\n t/t2025-worktree-add.sh        | 26 +++++++++++++++++++-------\n 3 files changed, 50 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..5d54f36a71 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, the new worktree is associated with a branch\n+(call it `<branch>`) named after `$(basename <path>)`.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` does exist, it will be\n+checked out in the new worktree, if it's not checked out anywhere\n+else, otherwise the command will refuse to create the worktree (unless\n+`--force` is used).\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 893139629a..f5a5283b39 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -355,9 +355,12 @@ static int add_worktree(const char *path, const char *refname,\n \n static void print_preparing_worktree_line(const char *branch,\n \t\t\t\t\t  const char *new_branch,\n-\t\t\t\t\t  const char *new_branch_force)\n+\t\t\t\t\t  const char *new_branch_force,\n+\t\t\t\t\t  int checkout_existing_branch)\n {\n-\tif (new_branch_force) {\n+\tif (checkout_existing_branch) {\n+\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"), branch);\n+\t} else if (new_branch_force) {\n \t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n \t\tif (!commit)\n \t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n@@ -378,11 +381,23 @@ static void print_preparing_worktree_line(const char *branch,\n \t}\n }\n \n-static const char *dwim_branch(const char *path, const char **new_branch)\n+static const char *dwim_branch(const char *path, const char **new_branch,\n+\t\t\t       int *checkout_existing_branch)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n-\t*new_branch = xstrndup(s, n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\t*checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\t*new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\n@@ -397,6 +412,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tstruct add_opts opts;\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n+\tint checkout_existing_branch = 0;\n \tconst char *branch;\n \tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n@@ -444,7 +460,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tconst char *s = dwim_branch(path, &new_branch);\n+\t\tconst char *s = dwim_branch(path, &new_branch,\n+\t\t\t\t\t    &checkout_existing_branch);\n \t\tif (s)\n \t\t\tbranch = s;\n \t}\n@@ -464,7 +481,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n-\tprint_preparing_worktree_line(branch, new_branch, new_branch_force);\n+\tprint_preparing_worktree_line(branch, new_branch, new_branch_force,\n+\t\t\t\t      checkout_existing_branch);\n \n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..ad38507d00 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,25 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n-\ttest_commit c1 &&\n-\ttest_commit c2 &&\n-\tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n-\ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+test_expect_success '\"add\" checks out existing branch of dwimd name' '\n+\tgit branch dwim HEAD~1 &&\n+\tgit worktree add dwim &&\n+\ttest_cmp_rev HEAD~1 dwim &&\n+\t(\n+\t\tcd dwim &&\n+\t\ttest_cmp_rev HEAD dwim\n+\t)\n+'\n+\n+test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n+'\n+\n+test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n+\tgit checkout test-branch &&\n+\tgit worktree add --force test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.17.0.252.gfe0a9eaf31\n\n"},{"id":"344768","messageId":"xmqq604rzytx.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"20180415202917.4360-3-t.gummerer@gmail.com","subject":"Re: [PATCH v7 2/4] worktree: improve message when creating a new worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-16T02:09:46Z","receivedAt":"2018-04-16T02:09:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Gummerer <t.gummerer@gmail.com> writes:\n\n> Currently 'git worktree add' produces output like the following:\n>\n>     Preparing ../foo (identifier foo)\n>     HEAD is now at 26da330922 <title>\n>\n> The '../foo' is the path where the worktree is created, which the user\n> has just given on the command line.  The identifier is an internal\n> implementation detail, which is not particularly relevant for the user\n> and indeed isn't mentioned explicitly anywhere in the man page.\n\nOK.  Maybe there once was a place or two that took the identifier as\nan input to name a specific worktree to work on (perhaps \"prune\"?),\nbut if we no longer do that (which makes sense, as we should be able\nto uniquely identify a worktree by the path to it), then it makes\nperfect sense to prevent it from appearing in the UI.\n\n> Instead of this message, print a message that gives the user a bit more\n> detail of what exactly 'git worktree' is doing.  There are various dwim\n> modes which are perform some magic under the hood, which should be\n\ns/are perform/perform/, I think (no need to reroll, only to fix this).\n\n> Additionally currently the \"Preparing ...\" line is printed to stderr,\n> while the \"HEAD is now at ...\" line is printed to stdout by 'git reset\n> --hard', which is used internally by 'git worktree add'.  Fix this\n> inconsistency by printing the \"Preparing ...\" message to stdout as\n> well.  As \"Preparing ...\" is not an error, stdout also seems like the\n> more appropriate output stream.\n\nI think it is a bug for reset to give this kind of informational\nmessage to the standard output stream.  A rule of thumb I use is \"is\nthis something that a user who wants quiet operation would wish to\nsquelch with --quiet option?\" and if the answer is yes, it should go\nto the standard error output, so info and progress should go to the\nstandard output in general.\n\nBut I am OK to unify to the standard output with this patch.  We may\nwant to come back and correct _both_ this new message and what reset\nsays, but that is outside the scope of this topic.\n\nThanks.\n"},{"id":"345443","messageId":"CAPig+cQSgY3yqYtZwTCY7Mq1e66WczbV3vM7=KsKH4b7peDw+Q@mail.gmail.com","threadId":"47657","inReplyTo":"20180415202917.4360-3-t.gummerer@gmail.com","subject":"Re: [PATCH v7 2/4] worktree: improve message when creating a new worktree","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-23T04:27:34Z","receivedAt":"2018-04-23T04:27:39Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Apr 15, 2018 at 4:29 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently 'git worktree add' produces output like the following:\n>\n>     Preparing ../foo (identifier foo)\n>     HEAD is now at 26da330922 <title>\n> [...]\n> Instead of this message, print a message that gives the user a bit more\n> detail of what exactly 'git worktree' is doing.  There are various dwim\n> modes which are perform some magic under the hood, which should be\n> helpful to users.  Just from the output of the command it is not always\n> visible to users what exactly has happened.\n>\n> Help the users a bit more by modifying the \"Preparing ...\" message and\n> adding some additional information of what 'git worktree add' did under\n> the hood, while not displaying the identifier anymore.\n>\n> Currently this ends up in three different cases:\n>\n>   - 'git worktree add -b ...' or 'git worktree add <path>' [...]\n>\n>   - 'git worktree add -B ...', which may either create a new branch if\n>     the branch with the given name does not exist yet, or resets an\n>     existing branch to the current HEAD, or the commit-ish given.\n>     Depending on which action is taken, we'll end up with the following\n>     output:\n>\n>       Preparing worktree (resetting branch 'next' (was at caa68db14))\n>       HEAD is now at 26da330922 <title>\n\nThe (...) embedded inside another (...) is ugly and hard to read.\nBetter perhaps:\n\n    Preparing worktree (resetting branch 'next'; was at caa68db14)\n\nNot necessarily worth a re-roll. It would be nice to see this series\nland; perhaps this can be tweaked later.\n\n>     or:\n>\n>       Preparing worktree (new branch '<branch>')\n>       HEAD is now at 26da330922 <title>\n>\n>   - 'git worktree add --detach' or 'git worktree add <path> <branch>',\n>     both of which create a new worktree with a detached HEAD, for which\n>     we will print the following output:\n>\n>       Preparing worktree (detached HEAD 26da330922)\n>       HEAD is now at 26da330922 <title>\n\nThis is inaccurate, isn't it? Certainly, specifying something like\n\"origin/floop\" for <branch> ends up detached:\n\n    % git worktree add w1 origin/floop\n    ...\n    % git worktree list\n    /proj     fe0a9eaf31 [master]\n    /proj/w1  b46fe60e1d (detached HEAD)\n\nbut specifying an existing local branch (say \"wip\") does not end up detached:\n\n    % git worktree add w2 wip\n    ...\n    % git worktree list\n    /proj     fe0a9eaf31 [master]\n    /proj/w1  b46fe60e1d (detached HEAD)\n    /proj/w2  820ed2a513 [wip]\n\n> Additionally currently the \"Preparing ...\" line is printed to stderr,\n> while the \"HEAD is now at ...\" line is printed to stdout by 'git reset\n> --hard', which is used internally by 'git worktree add'.  Fix this\n> inconsistency by printing the \"Preparing ...\" message to stdout as\n> well.  As \"Preparing ...\" is not an error, stdout also seems like the\n> more appropriate output stream.\n>\n> Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n"},{"id":"345444","messageId":"CAPig+cS=8na1Rm-DkZANez_kitU_WFQAbsqLxYe5dWUtsfdO8g@mail.gmail.com","threadId":"47657","inReplyTo":"20180415202917.4360-1-t.gummerer@gmail.com","subject":"Re: [PATCH v7 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-23T04:52:32Z","receivedAt":"2018-04-23T04:52:36Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Apr 15, 2018 at 4:29 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> The main change once again in this series is the user interface.  It\n> feels like we went in a complete circle here now, as this iteration is\n> bringing the \"Preparing ...\" line back (although in a slightly\n> different form than the original), and is moving away from printing\n> it's own \"HEAD is now at...\" line again.  This also means we don't\n> need the new hidden option to 'git reset' anymore, which is nice.\n\nI'm glad to see the proposed hidden git-reset option go away, and am\nlikewise happy to see that worktree no longer wants to print \"HEAD is\nnow at\" itself. I'm much more pleased with the direction this series\nis now taking than in earlier rounds. It's also much simpler, which is\na nice plus.\n\n> I do like the new UI more than what we had in the last round (which I\n> already liked more than the original UI) :)\n>\n> To demonstrate the UI updates, let's compare the new UI and the old UI\n> again.  This is the same commands as used for the demonstration in the\n> last iteration, so please have a look at <20180331151804.30380-1-t.gummerer@gmail.com>\n> for an example of what it looked like after the last round.\n\nThanks for presenting examples of the new UI under various conditions.\nLike you, I find the new \"Preparing...\" message superior to and much\nmore useful than the original.\n\nAside from the problem pointed out in my review of 2/4 in which it\nincorrectly shows \"detached HEAD\" for \"git worktree add wt\nexisting-local-branch\", I think this series is just about ready, and\nhope to see it land with the next re-roll.\n\nThanks for working on it.\n"},{"id":"345495","messageId":"20180423185008.GB25294@hank","threadId":"47657","inReplyTo":"CAPig+cQSgY3yqYtZwTCY7Mq1e66WczbV3vM7=KsKH4b7peDw+Q@mail.gmail.com","subject":"Re: [PATCH v7 2/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-23T18:50:08Z","receivedAt":"2018-04-23T18:50:07Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/23, Eric Sunshine wrote:\n> On Sun, Apr 15, 2018 at 4:29 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > Currently 'git worktree add' produces output like the following:\n> >\n> >     Preparing ../foo (identifier foo)\n> >     HEAD is now at 26da330922 <title>\n> > [...]\n> > Instead of this message, print a message that gives the user a bit more\n> > detail of what exactly 'git worktree' is doing.  There are various dwim\n> > modes which are perform some magic under the hood, which should be\n> > helpful to users.  Just from the output of the command it is not always\n> > visible to users what exactly has happened.\n> >\n> > Help the users a bit more by modifying the \"Preparing ...\" message and\n> > adding some additional information of what 'git worktree add' did under\n> > the hood, while not displaying the identifier anymore.\n> >\n> > Currently this ends up in three different cases:\n> >\n> >   - 'git worktree add -b ...' or 'git worktree add <path>' [...]\n> >\n> >   - 'git worktree add -B ...', which may either create a new branch if\n> >     the branch with the given name does not exist yet, or resets an\n> >     existing branch to the current HEAD, or the commit-ish given.\n> >     Depending on which action is taken, we'll end up with the following\n> >     output:\n> >\n> >       Preparing worktree (resetting branch 'next' (was at caa68db14))\n> >       HEAD is now at 26da330922 <title>\n> \n> The (...) embedded inside another (...) is ugly and hard to read.\n> Better perhaps:\n> \n>     Preparing worktree (resetting branch 'next'; was at caa68db14)\n> \n> Not necessarily worth a re-roll. It would be nice to see this series\n> land; perhaps this can be tweaked later.\n\nI'll tweak it while fixing the other bit.\n\n> >     or:\n> >\n> >       Preparing worktree (new branch '<branch>')\n> >       HEAD is now at 26da330922 <title>\n> >\n> >   - 'git worktree add --detach' or 'git worktree add <path> <branch>',\n> >     both of which create a new worktree with a detached HEAD, for which\n> >     we will print the following output:\n> >\n> >       Preparing worktree (detached HEAD 26da330922)\n> >       HEAD is now at 26da330922 <title>\n> \n> This is inaccurate, isn't it? Certainly, specifying something like\n> \"origin/floop\" for <branch> ends up detached:\n\nAh indeed, this was the case I missed.  I thought I managed to go\nthrough all of them, but this one slipped through the cracks.  Thanks\nfor catching this, will fix in a re-roll.\n\n>     % git worktree add w1 origin/floop\n>     ...\n>     % git worktree list\n>     /proj     fe0a9eaf31 [master]\n>     /proj/w1  b46fe60e1d (detached HEAD)\n> \n> but specifying an existing local branch (say \"wip\") does not end up detached:\n> \n>     % git worktree add w2 wip\n>     ...\n>     % git worktree list\n>     /proj     fe0a9eaf31 [master]\n>     /proj/w1  b46fe60e1d (detached HEAD)\n>     /proj/w2  820ed2a513 [wip]\n> \n> > Additionally currently the \"Preparing ...\" line is printed to stderr,\n> > while the \"HEAD is now at ...\" line is printed to stdout by 'git reset\n> > --hard', which is used internally by 'git worktree add'.  Fix this\n> > inconsistency by printing the \"Preparing ...\" message to stdout as\n> > well.  As \"Preparing ...\" is not an error, stdout also seems like the\n> > more appropriate output stream.\n> >\n> > Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n"},{"id":"345496","messageId":"20180423185506.GC25294@hank","threadId":"47657","inReplyTo":"xmqq604rzytx.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v7 2/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-23T18:55:06Z","receivedAt":"2018-04-23T18:55:05Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/16, Junio C Hamano wrote:\n> Thomas Gummerer <t.gummerer@gmail.com> writes:\n> \n> > Currently 'git worktree add' produces output like the following:\n> >\n> >     Preparing ../foo (identifier foo)\n> >     HEAD is now at 26da330922 <title>\n> >\n> > The '../foo' is the path where the worktree is created, which the user\n> > has just given on the command line.  The identifier is an internal\n> > implementation detail, which is not particularly relevant for the user\n> > and indeed isn't mentioned explicitly anywhere in the man page.\n> \n> OK.  Maybe there once was a place or two that took the identifier as\n> an input to name a specific worktree to work on (perhaps \"prune\"?),\n> but if we no longer do that (which makes sense, as we should be able\n> to uniquely identify a worktree by the path to it), then it makes\n> perfect sense to prevent it from appearing in the UI.\n> \n> > Instead of this message, print a message that gives the user a bit more\n> > detail of what exactly 'git worktree' is doing.  There are various dwim\n> > modes which are perform some magic under the hood, which should be\n> \n> s/are perform/perform/, I think (no need to reroll, only to fix this).\n\nNow that I'm re-rolling anyway, I'll fix this as well, thanks.\n\n> > Additionally currently the \"Preparing ...\" line is printed to stderr,\n> > while the \"HEAD is now at ...\" line is printed to stdout by 'git reset\n> > --hard', which is used internally by 'git worktree add'.  Fix this\n> > inconsistency by printing the \"Preparing ...\" message to stdout as\n> > well.  As \"Preparing ...\" is not an error, stdout also seems like the\n> > more appropriate output stream.\n> \n> I think it is a bug for reset to give this kind of informational\n> message to the standard output stream.  A rule of thumb I use is \"is\n> this something that a user who wants quiet operation would wish to\n> squelch with --quiet option?\" and if the answer is yes, it should go\n> to the standard error output, so info and progress should go to the\n> standard output in general.\n\nI assume you meant \"standard error output\" just above?\n\n> But I am OK to unify to the standard output with this patch.  We may\n> want to come back and correct _both_ this new message and what reset\n> says, but that is outside the scope of this topic.\n\nCool, I'd rather not add more moving pieces to this series, as it's\nalready at v7 (v8 soon), but I'm happy to have a look at this and fix\nit on top once the dust settled on this series.\n\n> Thanks.\n"},{"id":"345500","messageId":"20180423193848.5159-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180415202917.4360-1-t.gummerer@gmail.com","subject":"[PATCH v8 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-23T19:38:44Z","receivedAt":"2018-04-23T19:45:10Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Thanks Eric and Junio for the review the suggestions in the last\nround.\n\nPrevious rounds are at <20180121120208.12760-1-t.gummerer@gmail.com>,\n<20180204221305.28300-1-t.gummerer@gmail.com>,\n<20180317220830.30963-1-t.gummerer@gmail.com>,\n<20180317222219.4940-1-t.gummerer@gmail.com>,\n<20180325134947.25828-1-t.gummerer@gmail.com>,\n<20180331151804.30380-1-t.gummerer@gmail.com> and\n<20180415202917.4360-1-t.gummerer@gmail.com>.\n\nThis round updates the output for \"resetting branch ...\" to not have\nbraces embedded inside of another pair of braces, and is not correctly\nprinting \"checking out '<branch>'\" when 'git worktree add <path>\n<local-branch>' is used.  Both these changes are in patch 2/4, the\nother patches are the same as in the previous round.\n\nInterdiff below:\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex f5a5283b39..d52495f312 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -353,7 +353,8 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n-static void print_preparing_worktree_line(const char *branch,\n+static void print_preparing_worktree_line(int detach,\n+\t\t\t\t\t  const char *branch,\n \t\t\t\t\t  const char *new_branch,\n \t\t\t\t\t  const char *new_branch_force,\n \t\t\t\t\t  int checkout_existing_branch)\n@@ -365,19 +366,27 @@ static void print_preparing_worktree_line(const char *branch,\n \t\tif (!commit)\n \t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n \t\telse\n-\t\t\tprintf_ln(_(\"Preparing worktree (resetting branch '%s' (was at %s))\"),\n+\t\t\tprintf_ln(_(\"Preparing worktree (resetting branch '%s'; was at %s)\"),\n \t\t\t\t  new_branch_force,\n \t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n \t\t\t\t\t\t     DEFAULT_ABBREV));\n \t} else if (new_branch) {\n \t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n \t} else {\n-\t\tstruct commit *commit = lookup_commit_reference_by_name(branch);\n-\t\tif (!commit)\n-\t\t\tdie(_(\"invalid reference: %s\"), branch);\n-\t\tprintf_ln(_(\"Preparing worktree (detached HEAD %s)\"),\n-\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n-\t\t\t\t\t     DEFAULT_ABBREV));\n+\t\tstruct strbuf s = STRBUF_INIT;\n+\t\tif (!detach && !strbuf_check_branch_ref(&s, branch) &&\n+\t\t    ref_exists(s.buf))\n+\t\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"),\n+\t\t\t\t  branch);\n+\t\telse {\n+\t\t\tstruct commit *commit = lookup_commit_reference_by_name(branch);\n+\t\t\tif (!commit)\n+\t\t\t\tdie(_(\"invalid reference: %s\"), branch);\n+\t\t\tprintf_ln(_(\"Preparing worktree (detached HEAD %s)\"),\n+\t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t\t     DEFAULT_ABBREV));\n+\t\t}\n+\t\tstrbuf_release(&s);\n \t}\n }\n \n@@ -481,7 +490,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n-\tprint_preparing_worktree_line(branch, new_branch, new_branch_force,\n+\tprint_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force,\n \t\t\t\t      checkout_existing_branch);\n \n \tif (new_branch) {\n\nThomas Gummerer (4):\n  worktree: remove extra members from struct add_opts\n  worktree: improve message when creating a new worktree\n  worktree: factor out dwim_branch function\n  worktree: teach \"add\" to check out existing branches\n\n Documentation/git-worktree.txt |   9 +++-\n builtin/worktree.c             | 111 +++++++++++++++++++++++++++++++----------\n t/t2025-worktree-add.sh        |  26 +++++++---\n 3 files changed, 110 insertions(+), 36 deletions(-)\n\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345501","messageId":"20180423193848.5159-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180423193848.5159-1-t.gummerer@gmail.com","subject":"[PATCH v8 1/4] worktree: remove extra members from struct add_opts","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-23T19:38:45Z","receivedAt":"2018-04-23T19:45:20Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"There are two members of 'struct add_opts', which are only used inside\nthe 'add()' function, but being part of 'struct add_opts' they are\nneedlessly also passed to the 'add_worktree' function.\n\nMake them local to the 'add()' function to make it clearer where they\nare used.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 32 +++++++++++++++-----------------\n 1 file changed, 15 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..4d96a21a45 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -27,8 +27,6 @@ struct add_opts {\n \tint detach;\n \tint checkout;\n \tint keep_locked;\n-\tconst char *new_branch;\n-\tint force_new_branch;\n };\n \n static int show_only;\n@@ -363,10 +361,11 @@ static int add(int ac, const char **av, const char *prefix)\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n \tconst char *branch;\n+\tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&opts.force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n-\t\tOPT_STRING('b', NULL, &opts.new_branch, N_(\"branch\"),\n+\t\tOPT_STRING('b', NULL, &new_branch, N_(\"branch\"),\n \t\t\t   N_(\"create a new branch\")),\n \t\tOPT_STRING('B', NULL, &new_branch_force, N_(\"branch\"),\n \t\t\t   N_(\"create or reset a branch\")),\n@@ -384,7 +383,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tmemset(&opts, 0, sizeof(opts));\n \topts.checkout = 1;\n \tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n-\tif (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1)\n+\tif (!!opts.detach + !!new_branch + !!new_branch_force > 1)\n \t\tdie(_(\"-b, -B, and --detach are mutually exclusive\"));\n \tif (ac < 1 || ac > 2)\n \t\tusage_with_options(worktree_usage, options);\n@@ -395,33 +394,32 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (!strcmp(branch, \"-\"))\n \t\tbranch = \"@{-1}\";\n \n-\topts.force_new_branch = !!new_branch_force;\n-\tif (opts.force_new_branch) {\n+\tif (new_branch_force) {\n \t\tstruct strbuf symref = STRBUF_INIT;\n \n-\t\topts.new_branch = new_branch_force;\n+\t\tnew_branch = new_branch_force;\n \n \t\tif (!opts.force &&\n-\t\t    !strbuf_check_branch_ref(&symref, opts.new_branch) &&\n+\t\t    !strbuf_check_branch_ref(&symref, new_branch) &&\n \t\t    ref_exists(symref.buf))\n \t\t\tdie_if_checked_out(symref.buf, 0);\n \t\tstrbuf_release(&symref);\n \t}\n \n-\tif (ac < 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac < 2 && !new_branch && !opts.detach) {\n \t\tint n;\n \t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n+\t\tnew_branch = xstrndup(s, n);\n \t\tif (guess_remote) {\n \t\t\tstruct object_id oid;\n \t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n+\t\t\t\tunique_tracking_name(new_branch, &oid);\n \t\t\tif (remote)\n \t\t\t\tbranch = remote;\n \t\t}\n \t}\n \n-\tif (ac == 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac == 2 && !new_branch && !opts.detach) {\n \t\tstruct object_id oid;\n \t\tstruct commit *commit;\n \t\tconst char *remote;\n@@ -430,25 +428,25 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tif (!commit) {\n \t\t\tremote = unique_tracking_name(branch, &oid);\n \t\t\tif (remote) {\n-\t\t\t\topts.new_branch = branch;\n+\t\t\t\tnew_branch = branch;\n \t\t\t\tbranch = remote;\n \t\t\t}\n \t\t}\n \t}\n \n-\tif (opts.new_branch) {\n+\tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n-\t\tif (opts.force_new_branch)\n+\t\tif (new_branch_force)\n \t\t\targv_array_push(&cp.args, \"--force\");\n-\t\targv_array_push(&cp.args, opts.new_branch);\n+\t\targv_array_push(&cp.args, new_branch);\n \t\targv_array_push(&cp.args, branch);\n \t\tif (opt_track)\n \t\t\targv_array_push(&cp.args, opt_track);\n \t\tif (run_command(&cp))\n \t\t\treturn -1;\n-\t\tbranch = opts.new_branch;\n+\t\tbranch = new_branch;\n \t} else if (opt_track) {\n \t\tdie(_(\"--[no-]track can only be used if a new branch is created\"));\n \t}\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345502","messageId":"20180423193848.5159-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180423193848.5159-1-t.gummerer@gmail.com","subject":"[PATCH v8 2/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-23T19:38:46Z","receivedAt":"2018-04-23T19:45:25Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following:\n\n    Preparing ../foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nThe '../foo' is the path where the worktree is created, which the user\nhas just given on the command line.  The identifier is an internal\nimplementation detail, which is not particularly relevant for the user\nand indeed isn't mentioned explicitly anywhere in the man page.\n\nInstead of this message, print a message that gives the user a bit more\ndetail of what exactly 'git worktree' is doing.  There are various dwim\nmodes which perform some magic under the hood, which should be\nhelpful to users.  Just from the output of the command it is not always\nvisible to users what exactly has happened.\n\nHelp the users a bit more by modifying the \"Preparing ...\" message and\nadding some additional information of what 'git worktree add' did under\nthe hood, while not displaying the identifier anymore.\n\nCurrently this ends up in three different cases:\n\n  - 'git worktree add -b ...' or 'git worktree add <path>', both of\n    which create a new branch, either through the user explicitly\n    requesting it, or through 'git worktree add' implicitly creating\n    it.  This will end up with the following output:\n\n      Preparing worktree (new branch '<branch>')\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add -B ...', which may either create a new branch if\n    the branch with the given name does not exist yet, or resets an\n    existing branch to the current HEAD, or the commit-ish given.\n    Depending on which action is taken, we'll end up with the following\n    output:\n\n      Preparing worktree (resetting branch 'next'; was at caa68db14)\n      HEAD is now at 26da330922 <title>\n\n    or:\n\n      Preparing worktree (new branch '<branch>')\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add --detach' or 'git worktree add <path>\n    <commit-ish>', both of which create a new worktree with a detached\n    HEAD, for which we will print the following output:\n\n      Preparing worktree (detached HEAD 26da330922)\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add <path> <local-branch>', which checks out the\n    branch prints the following output:\n\n      Preparing worktree (checking out '<branch>')\n      HEAD is now at 47007d5 <title>\n\nAdditionally currently the \"Preparing ...\" line is printed to stderr,\nwhile the \"HEAD is now at ...\" line is printed to stdout by 'git reset\n--hard', which is used internally by 'git worktree add'.  Fix this\ninconsistency by printing the \"Preparing ...\" message to stdout as\nwell.  As \"Preparing ...\" is not an error, stdout also seems like the\nmore appropriate output stream.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 38 ++++++++++++++++++++++++++++++++++++--\n 1 file changed, 36 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 4d96a21a45..d348101216 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -301,8 +301,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -355,6 +353,40 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static void print_preparing_worktree_line(int detach,\n+\t\t\t\t\t  const char *branch,\n+\t\t\t\t\t  const char *new_branch,\n+\t\t\t\t\t  const char *new_branch_force)\n+{\n+\tif (new_branch_force) {\n+\t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n+\t\tif (!commit)\n+\t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n+\t\telse\n+\t\t\tprintf_ln(_(\"Preparing worktree (resetting branch '%s'; was at %s)\"),\n+\t\t\t\t  new_branch_force,\n+\t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t\t     DEFAULT_ABBREV));\n+\t} else if (new_branch) {\n+\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n+\t} else {\n+\t\tstruct strbuf s = STRBUF_INIT;\n+\t\tif (!detach && !strbuf_check_branch_ref(&s, branch) &&\n+\t\t    ref_exists(s.buf))\n+\t\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"),\n+\t\t\t\t  branch);\n+\t\telse {\n+\t\t\tstruct commit *commit = lookup_commit_reference_by_name(branch);\n+\t\t\tif (!commit)\n+\t\t\t\tdie(_(\"invalid reference: %s\"), branch);\n+\t\t\tprintf_ln(_(\"Preparing worktree (detached HEAD %s)\"),\n+\t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t\t     DEFAULT_ABBREV));\n+\t\t}\n+\t\tstrbuf_release(&s);\n+\t}\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -434,6 +466,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n+\tprint_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force);\n+\n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345503","messageId":"20180423193848.5159-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180423193848.5159-1-t.gummerer@gmail.com","subject":"[PATCH v8 3/4] worktree: factor out dwim_branch function","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-23T19:38:47Z","receivedAt":"2018-04-23T19:45:32Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Factor out a dwim_branch function, which takes care of the dwim'ery in\n'git worktree add <path>'.  It's not too much code currently, but we're\nadding a new kind of dwim in a subsequent patch, at which point it makes\nmore sense to have it as a separate function.\n\nFactor it out now to reduce the patch noise in the next patch.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 27 +++++++++++++++++----------\n 1 file changed, 17 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex d348101216..bd4cf4583f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -387,6 +387,20 @@ static void print_preparing_worktree_line(int detach,\n \t}\n }\n \n+static const char *dwim_branch(const char *path, const char **new_branch)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\t*new_branch = xstrndup(s, n);\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(*new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -439,16 +453,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\tnew_branch = xstrndup(s, n);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n-\t\t}\n+\t\tconst char *s = dwim_branch(path, &new_branch);\n+\t\tif (s)\n+\t\t\tbranch = s;\n \t}\n \n \tif (ac == 2 && !new_branch && !opts.detach) {\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345504","messageId":"20180423193848.5159-5-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180423193848.5159-1-t.gummerer@gmail.com","subject":"[PATCH v8 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-23T19:38:48Z","receivedAt":"2018-04-23T19:45:39Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 30 ++++++++++++++++++++++++------\n t/t2025-worktree-add.sh        | 26 +++++++++++++++++++-------\n 3 files changed, 50 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..5d54f36a71 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, the new worktree is associated with a branch\n+(call it `<branch>`) named after `$(basename <path>)`.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` does exist, it will be\n+checked out in the new worktree, if it's not checked out anywhere\n+else, otherwise the command will refuse to create the worktree (unless\n+`--force` is used).\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex bd4cf4583f..d52495f312 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -356,9 +356,12 @@ static int add_worktree(const char *path, const char *refname,\n static void print_preparing_worktree_line(int detach,\n \t\t\t\t\t  const char *branch,\n \t\t\t\t\t  const char *new_branch,\n-\t\t\t\t\t  const char *new_branch_force)\n+\t\t\t\t\t  const char *new_branch_force,\n+\t\t\t\t\t  int checkout_existing_branch)\n {\n-\tif (new_branch_force) {\n+\tif (checkout_existing_branch) {\n+\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"), branch);\n+\t} else if (new_branch_force) {\n \t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n \t\tif (!commit)\n \t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n@@ -387,11 +390,23 @@ static void print_preparing_worktree_line(int detach,\n \t}\n }\n \n-static const char *dwim_branch(const char *path, const char **new_branch)\n+static const char *dwim_branch(const char *path, const char **new_branch,\n+\t\t\t       int *checkout_existing_branch)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n-\t*new_branch = xstrndup(s, n);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\t*checkout_existing_branch = 1;\n+\t\tstrbuf_release(&ref);\n+\t\tUNLEAK(branchname);\n+\t\treturn branchname;\n+\t}\n+\n+\t*new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\n@@ -406,6 +421,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tstruct add_opts opts;\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n+\tint checkout_existing_branch = 0;\n \tconst char *branch;\n \tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n@@ -453,7 +469,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tconst char *s = dwim_branch(path, &new_branch);\n+\t\tconst char *s = dwim_branch(path, &new_branch,\n+\t\t\t\t\t    &checkout_existing_branch);\n \t\tif (s)\n \t\t\tbranch = s;\n \t}\n@@ -473,7 +490,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n-\tprint_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force);\n+\tprint_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force,\n+\t\t\t\t      checkout_existing_branch);\n \n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..ad38507d00 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,25 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n-\ttest_commit c1 &&\n-\ttest_commit c2 &&\n-\tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n-\ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+test_expect_success '\"add\" checks out existing branch of dwimd name' '\n+\tgit branch dwim HEAD~1 &&\n+\tgit worktree add dwim &&\n+\ttest_cmp_rev HEAD~1 dwim &&\n+\t(\n+\t\tcd dwim &&\n+\t\ttest_cmp_rev HEAD dwim\n+\t)\n+'\n+\n+test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n+'\n+\n+test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n+\tgit checkout test-branch &&\n+\tgit worktree add --force test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345603","messageId":"CAPig+cSH1ouZBU9BT64vL5vBz4cD+UFCoFH4fZyf8JrM7dKe5Q@mail.gmail.com","threadId":"47657","inReplyTo":"20180423193848.5159-2-t.gummerer@gmail.com","subject":"Re: [PATCH v8 1/4] worktree: remove extra members from struct add_opts","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-24T03:26:41Z","receivedAt":"2018-04-24T03:26:45Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Apr 23, 2018 at 3:38 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> There are two members of 'struct add_opts', which are only used inside\n> the 'add()' function, but being part of 'struct add_opts' they are\n> needlessly also passed to the 'add_worktree' function.\n>\n> Make them local to the 'add()' function to make it clearer where they\n> are used.\n>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -27,8 +27,6 @@ struct add_opts {\n>         int keep_locked;\n> -       const char *new_branch;\n> -       int force_new_branch;\n>  };\n> @@ -395,33 +394,32 @@ static int add(int ac, const char **av, const char *prefix)\n> -       if (ac < 2 && !opts.new_branch && !opts.detach) {\n> +       if (ac < 2 && !new_branch && !opts.detach) {\n>                 int n;\n>                 const char *s = worktree_basename(path, &n);\n> -               opts.new_branch = xstrndup(s, n);\n> +               new_branch = xstrndup(s, n);\n\nSorry for not noticing this earlier, but when 'new_branch' was part of\n'opts', this leaked xstrndup'd string was covered by the UNLEAK(opts)\nat the end of the function. However, now that 'new_branch' is a\nstandalone variable, it needs its own UNLEAK().\n"},{"id":"345604","messageId":"CAPig+cSOhdfyn+yJcsM9h3r7Atf4pQCX7pgPOB2hv+OHJ3r1bg@mail.gmail.com","threadId":"47657","inReplyTo":"20180423193848.5159-3-t.gummerer@gmail.com","subject":"Re: [PATCH v8 2/4] worktree: improve message when creating a new worktree","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-24T03:58:02Z","receivedAt":"2018-04-24T03:58:07Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Apr 23, 2018 at 3:38 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently 'git worktree add' produces output like the following:\n>\n>     Preparing ../foo (identifier foo)\n>     HEAD is now at 26da330922 <title>\n>\n> The '../foo' is the path where the worktree is created, which the user\n> has just given on the command line.  The identifier is an internal\n> implementation detail, which is not particularly relevant for the user\n> and indeed isn't mentioned explicitly anywhere in the man page.\n>\n> Instead of this message, print a message that gives the user a bit more\n> detail of what exactly 'git worktree' is doing.  There are various dwim\n> modes which perform some magic under the hood, which should be\n> helpful to users.  Just from the output of the command it is not always\n> visible to users what exactly has happened.\n>\n> Help the users a bit more by modifying the \"Preparing ...\" message and\n> adding some additional information of what 'git worktree add' did under\n> the hood, while not displaying the identifier anymore.\n>\n> Currently this ends up in three different cases:\n\nYou now enumerate four cases, not three. Perhaps: \"There are several\ndifferent cases:\"\n\n>   - 'git worktree add -b ...' or 'git worktree add <path>', both of\n>     which create a new branch, either through the user explicitly\n>     requesting it, or through 'git worktree add' implicitly creating\n>     it.  This will end up with the following output:\n>\n>       Preparing worktree (new branch '<branch>')\n>       HEAD is now at 26da330922 <title>\n>\n>   - 'git worktree add -B ...', which may either create a new branch if\n>     the branch with the given name does not exist yet, or resets an\n>     existing branch to the current HEAD, or the commit-ish given.\n>     Depending on which action is taken, we'll end up with the following\n>     output:\n>\n>       Preparing worktree (resetting branch 'next'; was at caa68db14)\n>       HEAD is now at 26da330922 <title>\n\nFor consistency with the other examples: s/next/<branch>/\n\n>     or:\n>\n>       Preparing worktree (new branch '<branch>')\n>       HEAD is now at 26da330922 <title>\n>\n>   - 'git worktree add --detach' or 'git worktree add <path>\n>     <commit-ish>', both of which create a new worktree with a detached\n>     HEAD, for which we will print the following output:\n>\n>       Preparing worktree (detached HEAD 26da330922)\n>       HEAD is now at 26da330922 <title>\n>\n>   - 'git worktree add <path> <local-branch>', which checks out the\n>     branch prints the following output:\n\ns/prints/and prints/\n\n>       Preparing worktree (checking out '<branch>')\n>       HEAD is now at 47007d5 <title>\n\ns/<branch>/<local-branch>/ would probably be clearer since you use\n<local-branch> in the example command.\n\n> [...]\n> Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -355,6 +353,40 @@ static int add_worktree(const char *path, const char *refname,\n> +static void print_preparing_worktree_line(int detach,\n> +                                         const char *branch,\n> +                                         const char *new_branch,\n> +                                         const char *new_branch_force)\n> +{\n> +       if (new_branch_force) {\n> +               struct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n\nNit: By the time this function is called, 'new_branch' contains the\nsame value as 'new_branch_force' if \"-B\" was used. 'new_branch' _is_\nthe name of the new branch, forced or not, and it's easier to reason\nabout 'new_branch_force' as a mere boolean indicating whether \"force\"\nis in effect. This suggests that the final argument to this function\nshould be a boolean (int) named either 'force' or 'force_new_branch',\nand that 'new_branch' should be used everywhere the code needs to\nreference the new branch name (forced or not).\n\nNot worth a re-roll.\n\n> +               if (!commit)\n> +                       printf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n> +               else\n> +                       printf_ln(_(\"Preparing worktree (resetting branch '%s'; was at %s)\"),\n> +                                 new_branch_force,\n> +                                 find_unique_abbrev(commit->object.oid.hash,\n> +                                                    DEFAULT_ABBREV));\n> +       } else if (new_branch) {\n> +               printf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n> +       } else {\n> +               struct strbuf s = STRBUF_INIT;\n> +               if (!detach && !strbuf_check_branch_ref(&s, branch) &&\n> +                   ref_exists(s.buf))\n> +                       printf_ln(_(\"Preparing worktree (checking out '%s')\"),\n> +                                 branch);\n> +               else {\n> +                       struct commit *commit = lookup_commit_reference_by_name(branch);\n> +                       if (!commit)\n> +                               die(_(\"invalid reference: %s\"), branch);\n> +                       printf_ln(_(\"Preparing worktree (detached HEAD %s)\"),\n> +                                 find_unique_abbrev(commit->object.oid.hash,\n> +                                                    DEFAULT_ABBREV));\n> +               }\n\nIt's too bad this final case duplicates so much code from\nadd_worktree(). Perhaps some future refactoring patch (not part of\nthis series) can consolidate the code.\n\n> +               strbuf_release(&s);\n> +       }\n> +}\n> @@ -434,6 +466,8 @@ static int add(int ac, const char **av, const char *prefix)\n> +       print_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force);\n> +\n>         if (new_branch) {\n>                 struct child_process cp = CHILD_PROCESS_INIT;\n"},{"id":"345605","messageId":"20180424042510.GA8431@flurp.local","threadId":"47657","inReplyTo":"20180423193848.5159-5-t.gummerer@gmail.com","subject":"Re: [PATCH v8 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-24T04:25:10Z","receivedAt":"2018-04-24T04:25:20Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Apr 23, 2018 at 3:38 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Currently 'git worktree add <path>' creates a new branch named after the\n> basename of the path by default.  If a branch with that name already\n> exists, the command refuses to do anything, unless the '--force' option\n> is given.\n>\n> However we can do a little better than that, and check the branch out if\n> it is not checked out anywhere else.  This will help users who just want\n> to check an existing branch out into a new worktree, and save a few\n> keystrokes.\n> [...]\n> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -356,9 +356,12 @@ static int add_worktree(const char *path, const char *refname,\n>  static void print_preparing_worktree_line(int detach,\n>                                           const char *branch,\n>                                           const char *new_branch,\n> -                                         const char *new_branch_force)\n> +                                         const char *new_branch_force,\n> +                                         int checkout_existing_branch)\n>  {\n> -       if (new_branch_force) {\n> +       if (checkout_existing_branch) {\n> +               printf_ln(_(\"Preparing worktree (checking out '%s')\"), branch);\n\nIs the new 'checkout_existing_branch' argument and this new\nconditional really needed? Both 'new_branch' and 'new_branch_force'\nwill be NULL in the case of an existing branch, so there should be no\nneed for 'checkout_existing_branch' to state explicitly what is\nalready indicated by their NULLness. With both of them NULL, the\nexisting \"(checking out '...')\" message later in the function will\nkick in, so this new condition isn't needed.\n\n> +       } else if (new_branch_force) {\n> @@ -387,11 +390,23 @@ static void print_preparing_worktree_line(int detach,\n> +static const char *dwim_branch(const char *path, const char **new_branch,\n> +                              int *checkout_existing_branch)\n>  {\n>         int n;\n>         const char *s = worktree_basename(path, &n);\n> -       *new_branch = xstrndup(s, n);\n> +       const char *branchname = xstrndup(s, n);\n> +       struct strbuf ref = STRBUF_INIT;\n> +\n> +       if (!strbuf_check_branch_ref(&ref, branchname) &&\n> +           ref_exists(ref.buf)) {\n> +               *checkout_existing_branch = 1;\n\nSee above regarding apparent lack of need for this new variable.\n\n> +               strbuf_release(&ref);\n> +               UNLEAK(branchname);\n> +               return branchname;\n> +       }\n\nTaking the above observation into account, I applied, atop this patch,\nthe following fixup! which removes the 'checkout_existing_branch'\ngunk and still get the same output:\n\n--- >8 ---\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -356,12 +356,9 @@ static int add_worktree(const char *path, const char *refname,\n static void print_preparing_worktree_line(int detach,\n \t\t\t\t\t  const char *branch,\n \t\t\t\t\t  const char *new_branch,\n-\t\t\t\t\t  const char *new_branch_force,\n-\t\t\t\t\t  int checkout_existing_branch)\n+\t\t\t\t\t  const char *new_branch_force)\n {\n-\tif (checkout_existing_branch) {\n-\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"), branch);\n-\t} else if (new_branch_force) {\n+\tif (new_branch_force) {\n \t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n \t\tif (!commit)\n \t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n@@ -390,8 +387,7 @@ static void print_preparing_worktree_line(int detach,\n \t}\n }\n \n-static const char *dwim_branch(const char *path, const char **new_branch,\n-\t\t\t       int *checkout_existing_branch)\n+static const char *dwim_branch(const char *path, const char **new_branch)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n@@ -400,7 +396,6 @@ static const char *dwim_branch(const char *path, const char **new_branch,\n \n \tif (!strbuf_check_branch_ref(&ref, branchname) &&\n \t    ref_exists(ref.buf)) {\n-\t\t*checkout_existing_branch = 1;\n \t\tstrbuf_release(&ref);\n \t\tUNLEAK(branchname);\n \t\treturn branchname;\n@@ -421,7 +416,6 @@ static int add(int ac, const char **av, const char *prefix)\n \tstruct add_opts opts;\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n-\tint checkout_existing_branch = 0;\n \tconst char *branch;\n \tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n@@ -469,8 +463,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tconst char *s = dwim_branch(path, &new_branch,\n-\t\t\t\t\t    &checkout_existing_branch);\n+\t\tconst char *s = dwim_branch(path, &new_branch);\n \t\tif (s)\n \t\t\tbranch = s;\n \t}\n@@ -490,8 +483,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n-\tprint_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force,\n-\t\t\t\t      checkout_existing_branch);\n+\tprint_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force);\n \n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n--- >8 ---\n"},{"id":"345688","messageId":"20180424215635.9183-1-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180423193848.5159-1-t.gummerer@gmail.com","subject":"[PATCH v9 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-24T21:56:31Z","receivedAt":"2018-04-24T21:57:12Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Previous rounds are at <20180121120208.12760-1-t.gummerer@gmail.com>,\n<20180204221305.28300-1-t.gummerer@gmail.com>,\n<20180317220830.30963-1-t.gummerer@gmail.com>,\n<20180317222219.4940-1-t.gummerer@gmail.com>,\n<20180325134947.25828-1-t.gummerer@gmail.com>,\n<20180331151804.30380-1-t.gummerer@gmail.com>,\n<20180415202917.4360-1-t.gummerer@gmail.com> and\n<20180423193848.5159-1-t.gummerer@gmail.com>.\n\nThanks Eric for the review and the suggestions on the previous round.\n\nChanges since the previous round:\n\n- UNLEAK new_branch after it was xstrndup'd\n- update the commit message of 2/4 according to Eric's suggestions\n- make force_new_branch a boolean flag in\n  print_preparing_worktree_line, instead of using it as the branch\n  name.  Instead use new_branch as the new branch name everywhere in\n  that function.\n- get rid of the ckeckout_existing_branch flag\n\nInterdiff below:\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex d52495f312..d3aeb4877d 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -356,18 +356,15 @@ static int add_worktree(const char *path, const char *refname,\n static void print_preparing_worktree_line(int detach,\n \t\t\t\t\t  const char *branch,\n \t\t\t\t\t  const char *new_branch,\n-\t\t\t\t\t  const char *new_branch_force,\n-\t\t\t\t\t  int checkout_existing_branch)\n+\t\t\t\t\t  int force_new_branch)\n {\n-\tif (checkout_existing_branch) {\n-\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"), branch);\n-\t} else if (new_branch_force) {\n-\t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch_force);\n+\tif (force_new_branch) {\n+\t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch);\n \t\tif (!commit)\n-\t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch_force);\n+\t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n \t\telse\n \t\t\tprintf_ln(_(\"Preparing worktree (resetting branch '%s'; was at %s)\"),\n-\t\t\t\t  new_branch_force,\n+\t\t\t\t  new_branch,\n \t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n \t\t\t\t\t\t     DEFAULT_ABBREV));\n \t} else if (new_branch) {\n@@ -390,19 +387,17 @@ static void print_preparing_worktree_line(int detach,\n \t}\n }\n \n-static const char *dwim_branch(const char *path, const char **new_branch,\n-\t\t\t       int *checkout_existing_branch)\n+static const char *dwim_branch(const char *path, const char **new_branch)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n \tconst char *branchname = xstrndup(s, n);\n \tstruct strbuf ref = STRBUF_INIT;\n \n+\tUNLEAK(branchname);\n \tif (!strbuf_check_branch_ref(&ref, branchname) &&\n \t    ref_exists(ref.buf)) {\n-\t\t*checkout_existing_branch = 1;\n \t\tstrbuf_release(&ref);\n-\t\tUNLEAK(branchname);\n \t\treturn branchname;\n \t}\n \n@@ -421,7 +416,6 @@ static int add(int ac, const char **av, const char *prefix)\n \tstruct add_opts opts;\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n-\tint checkout_existing_branch = 0;\n \tconst char *branch;\n \tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n@@ -469,8 +463,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tconst char *s = dwim_branch(path, &new_branch,\n-\t\t\t\t\t    &checkout_existing_branch);\n+\t\tconst char *s = dwim_branch(path, &new_branch);\n \t\tif (s)\n \t\t\tbranch = s;\n \t}\n@@ -490,8 +483,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n-\tprint_preparing_worktree_line(opts.detach, branch, new_branch, new_branch_force,\n-\t\t\t\t      checkout_existing_branch);\n+\tprint_preparing_worktree_line(opts.detach, branch, new_branch, !!new_branch_force);\n \n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n\nThomas Gummerer (4):\n  worktree: remove extra members from struct add_opts\n  worktree: improve message when creating a new worktree\n  worktree: factor out dwim_branch function\n  worktree: teach \"add\" to check out existing branches\n\n Documentation/git-worktree.txt |   9 +++-\n builtin/worktree.c             | 103 ++++++++++++++++++++++++++++++-----------\n t/t2025-worktree-add.sh        |  26 ++++++++---\n 3 files changed, 102 insertions(+), 36 deletions(-)\n\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345689","messageId":"20180424215635.9183-2-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180424215635.9183-1-t.gummerer@gmail.com","subject":"[PATCH v9 1/4] worktree: remove extra members from struct add_opts","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-24T21:56:32Z","receivedAt":"2018-04-24T21:57:16Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"There are two members of 'struct add_opts', which are only used inside\nthe 'add()' function, but being part of 'struct add_opts' they are\nneedlessly also passed to the 'add_worktree' function.\n\nMake them local to the 'add()' function to make it clearer where they\nare used.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 33 ++++++++++++++++-----------------\n 1 file changed, 16 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 7cef5b120b..bf305c8b7b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -27,8 +27,6 @@ struct add_opts {\n \tint detach;\n \tint checkout;\n \tint keep_locked;\n-\tconst char *new_branch;\n-\tint force_new_branch;\n };\n \n static int show_only;\n@@ -363,10 +361,11 @@ static int add(int ac, const char **av, const char *prefix)\n \tconst char *new_branch_force = NULL;\n \tchar *path;\n \tconst char *branch;\n+\tconst char *new_branch = NULL;\n \tconst char *opt_track = NULL;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&opts.force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n-\t\tOPT_STRING('b', NULL, &opts.new_branch, N_(\"branch\"),\n+\t\tOPT_STRING('b', NULL, &new_branch, N_(\"branch\"),\n \t\t\t   N_(\"create a new branch\")),\n \t\tOPT_STRING('B', NULL, &new_branch_force, N_(\"branch\"),\n \t\t\t   N_(\"create or reset a branch\")),\n@@ -384,7 +383,7 @@ static int add(int ac, const char **av, const char *prefix)\n \tmemset(&opts, 0, sizeof(opts));\n \topts.checkout = 1;\n \tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n-\tif (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1)\n+\tif (!!opts.detach + !!new_branch + !!new_branch_force > 1)\n \t\tdie(_(\"-b, -B, and --detach are mutually exclusive\"));\n \tif (ac < 1 || ac > 2)\n \t\tusage_with_options(worktree_usage, options);\n@@ -395,33 +394,33 @@ static int add(int ac, const char **av, const char *prefix)\n \tif (!strcmp(branch, \"-\"))\n \t\tbranch = \"@{-1}\";\n \n-\topts.force_new_branch = !!new_branch_force;\n-\tif (opts.force_new_branch) {\n+\tif (new_branch_force) {\n \t\tstruct strbuf symref = STRBUF_INIT;\n \n-\t\topts.new_branch = new_branch_force;\n+\t\tnew_branch = new_branch_force;\n \n \t\tif (!opts.force &&\n-\t\t    !strbuf_check_branch_ref(&symref, opts.new_branch) &&\n+\t\t    !strbuf_check_branch_ref(&symref, new_branch) &&\n \t\t    ref_exists(symref.buf))\n \t\t\tdie_if_checked_out(symref.buf, 0);\n \t\tstrbuf_release(&symref);\n \t}\n \n-\tif (ac < 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac < 2 && !new_branch && !opts.detach) {\n \t\tint n;\n \t\tconst char *s = worktree_basename(path, &n);\n-\t\topts.new_branch = xstrndup(s, n);\n+\t\tnew_branch = xstrndup(s, n);\n+\t\tUNLEAK(new_branch);\n \t\tif (guess_remote) {\n \t\t\tstruct object_id oid;\n \t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(opts.new_branch, &oid);\n+\t\t\t\tunique_tracking_name(new_branch, &oid);\n \t\t\tif (remote)\n \t\t\t\tbranch = remote;\n \t\t}\n \t}\n \n-\tif (ac == 2 && !opts.new_branch && !opts.detach) {\n+\tif (ac == 2 && !new_branch && !opts.detach) {\n \t\tstruct object_id oid;\n \t\tstruct commit *commit;\n \t\tconst char *remote;\n@@ -430,25 +429,25 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tif (!commit) {\n \t\t\tremote = unique_tracking_name(branch, &oid);\n \t\t\tif (remote) {\n-\t\t\t\topts.new_branch = branch;\n+\t\t\t\tnew_branch = branch;\n \t\t\t\tbranch = remote;\n \t\t\t}\n \t\t}\n \t}\n \n-\tif (opts.new_branch) {\n+\tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n \t\targv_array_push(&cp.args, \"branch\");\n-\t\tif (opts.force_new_branch)\n+\t\tif (new_branch_force)\n \t\t\targv_array_push(&cp.args, \"--force\");\n-\t\targv_array_push(&cp.args, opts.new_branch);\n+\t\targv_array_push(&cp.args, new_branch);\n \t\targv_array_push(&cp.args, branch);\n \t\tif (opt_track)\n \t\t\targv_array_push(&cp.args, opt_track);\n \t\tif (run_command(&cp))\n \t\t\treturn -1;\n-\t\tbranch = opts.new_branch;\n+\t\tbranch = new_branch;\n \t} else if (opt_track) {\n \t\tdie(_(\"--[no-]track can only be used if a new branch is created\"));\n \t}\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345690","messageId":"20180424215635.9183-3-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180424215635.9183-1-t.gummerer@gmail.com","subject":"[PATCH v9 2/4] worktree: improve message when creating a new worktree","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-24T21:56:33Z","receivedAt":"2018-04-24T21:57:17Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add' produces output like the following:\n\n    Preparing ../foo (identifier foo)\n    HEAD is now at 26da330922 <title>\n\nThe '../foo' is the path where the worktree is created, which the user\nhas just given on the command line.  The identifier is an internal\nimplementation detail, which is not particularly relevant for the user\nand indeed isn't mentioned explicitly anywhere in the man page.\n\nInstead of this message, print a message that gives the user a bit more\ndetail of what exactly 'git worktree' is doing.  There are various dwim\nmodes which perform some magic under the hood, which should be\nhelpful to users.  Just from the output of the command it is not always\nvisible to users what exactly has happened.\n\nHelp the users a bit more by modifying the \"Preparing ...\" message and\nadding some additional information of what 'git worktree add' did under\nthe hood, while not displaying the identifier anymore.\n\nCurrently there are several different cases:\n\n  - 'git worktree add -b ...' or 'git worktree add <path>', both of\n    which create a new branch, either through the user explicitly\n    requesting it, or through 'git worktree add' implicitly creating\n    it.  This will end up with the following output:\n\n      Preparing worktree (new branch '<branch>')\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add -B ...', which may either create a new branch if\n    the branch with the given name does not exist yet, or resets an\n    existing branch to the current HEAD, or the commit-ish given.\n    Depending on which action is taken, we'll end up with the following\n    output:\n\n      Preparing worktree (resetting branch '<branch>'; was at caa68db14)\n      HEAD is now at 26da330922 <title>\n\n    or:\n\n      Preparing worktree (new branch '<branch>')\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add --detach' or 'git worktree add <path>\n    <commit-ish>', both of which create a new worktree with a detached\n    HEAD, for which we will print the following output:\n\n      Preparing worktree (detached HEAD 26da330922)\n      HEAD is now at 26da330922 <title>\n\n  - 'git worktree add <path> <local-branch>', which checks out the\n    branch and prints the following output:\n\n      Preparing worktree (checking out '<local-branch>')\n      HEAD is now at 47007d5 <title>\n\nAdditionally currently the \"Preparing ...\" line is printed to stderr,\nwhile the \"HEAD is now at ...\" line is printed to stdout by 'git reset\n--hard', which is used internally by 'git worktree add'.  Fix this\ninconsistency by printing the \"Preparing ...\" message to stdout as\nwell.  As \"Preparing ...\" is not an error, stdout also seems like the\nmore appropriate output stream.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 38 ++++++++++++++++++++++++++++++++++++--\n 1 file changed, 36 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex bf305c8b7b..39bf1ea865 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -301,8 +301,6 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, \"../..\");\n \n-\tfprintf_ln(stderr, _(\"Preparing %s (identifier %s)\"), path, name);\n-\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_DIR_ENVIRONMENT, sb_git.buf);\n \targv_array_pushf(&child_env, \"%s=%s\", GIT_WORK_TREE_ENVIRONMENT, path);\n \tcp.git_cmd = 1;\n@@ -355,6 +353,40 @@ static int add_worktree(const char *path, const char *refname,\n \treturn ret;\n }\n \n+static void print_preparing_worktree_line(int detach,\n+\t\t\t\t\t  const char *branch,\n+\t\t\t\t\t  const char *new_branch,\n+\t\t\t\t\t  int force_new_branch)\n+{\n+\tif (force_new_branch) {\n+\t\tstruct commit *commit = lookup_commit_reference_by_name(new_branch);\n+\t\tif (!commit)\n+\t\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n+\t\telse\n+\t\t\tprintf_ln(_(\"Preparing worktree (resetting branch '%s'; was at %s)\"),\n+\t\t\t\t  new_branch,\n+\t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t\t     DEFAULT_ABBREV));\n+\t} else if (new_branch) {\n+\t\tprintf_ln(_(\"Preparing worktree (new branch '%s')\"), new_branch);\n+\t} else {\n+\t\tstruct strbuf s = STRBUF_INIT;\n+\t\tif (!detach && !strbuf_check_branch_ref(&s, branch) &&\n+\t\t    ref_exists(s.buf))\n+\t\t\tprintf_ln(_(\"Preparing worktree (checking out '%s')\"),\n+\t\t\t\t  branch);\n+\t\telse {\n+\t\t\tstruct commit *commit = lookup_commit_reference_by_name(branch);\n+\t\t\tif (!commit)\n+\t\t\t\tdie(_(\"invalid reference: %s\"), branch);\n+\t\t\tprintf_ln(_(\"Preparing worktree (detached HEAD %s)\"),\n+\t\t\t\t  find_unique_abbrev(commit->object.oid.hash,\n+\t\t\t\t\t\t     DEFAULT_ABBREV));\n+\t\t}\n+\t\tstrbuf_release(&s);\n+\t}\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -435,6 +467,8 @@ static int add(int ac, const char **av, const char *prefix)\n \t\t}\n \t}\n \n+\tprint_preparing_worktree_line(opts.detach, branch, new_branch, !!new_branch_force);\n+\n \tif (new_branch) {\n \t\tstruct child_process cp = CHILD_PROCESS_INIT;\n \t\tcp.git_cmd = 1;\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345691","messageId":"20180424215635.9183-4-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180424215635.9183-1-t.gummerer@gmail.com","subject":"[PATCH v9 3/4] worktree: factor out dwim_branch function","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-24T21:56:34Z","receivedAt":"2018-04-24T21:57:20Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Factor out a dwim_branch function, which takes care of the dwim'ery in\n'git worktree add <path>'.  It's not too much code currently, but we're\nadding a new kind of dwim in a subsequent patch, at which point it makes\nmore sense to have it as a separate function.\n\nFactor it out now to reduce the patch noise in the next patch.\n\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n builtin/worktree.c | 29 ++++++++++++++++++-----------\n 1 file changed, 18 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 39bf1ea865..6bd32b6090 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -387,6 +387,21 @@ static void print_preparing_worktree_line(int detach,\n \t}\n }\n \n+static const char *dwim_branch(const char *path, const char **new_branch)\n+{\n+\tint n;\n+\tconst char *s = worktree_basename(path, &n);\n+\t*new_branch = xstrndup(s, n);\n+\tUNLEAK(*new_branch);\n+\tif (guess_remote) {\n+\t\tstruct object_id oid;\n+\t\tconst char *remote =\n+\t\t\tunique_tracking_name(*new_branch, &oid);\n+\t\treturn remote;\n+\t}\n+\treturn NULL;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct add_opts opts;\n@@ -439,17 +454,9 @@ static int add(int ac, const char **av, const char *prefix)\n \t}\n \n \tif (ac < 2 && !new_branch && !opts.detach) {\n-\t\tint n;\n-\t\tconst char *s = worktree_basename(path, &n);\n-\t\tnew_branch = xstrndup(s, n);\n-\t\tUNLEAK(new_branch);\n-\t\tif (guess_remote) {\n-\t\t\tstruct object_id oid;\n-\t\t\tconst char *remote =\n-\t\t\t\tunique_tracking_name(new_branch, &oid);\n-\t\t\tif (remote)\n-\t\t\t\tbranch = remote;\n-\t\t}\n+\t\tconst char *s = dwim_branch(path, &new_branch);\n+\t\tif (s)\n+\t\t\tbranch = s;\n \t}\n \n \tif (ac == 2 && !new_branch && !opts.detach) {\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345692","messageId":"20180424215635.9183-5-t.gummerer@gmail.com","threadId":"47657","inReplyTo":"20180424215635.9183-1-t.gummerer@gmail.com","subject":"[PATCH v9 4/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-24T21:56:35Z","receivedAt":"2018-04-24T21:57:21Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"Currently 'git worktree add <path>' creates a new branch named after the\nbasename of the path by default.  If a branch with that name already\nexists, the command refuses to do anything, unless the '--force' option\nis given.\n\nHowever we can do a little better than that, and check the branch out if\nit is not checked out anywhere else.  This will help users who just want\nto check an existing branch out into a new worktree, and save a few\nkeystrokes.\n\nAs the current behaviour is to simply 'die()' when a branch with the name\nof the basename of the path already exists, there are no backwards\ncompatibility worries here.\n\nWe will still 'die()' if the branch is checked out in another worktree,\nunless the --force flag is passed.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Thomas Gummerer <t.gummerer@gmail.com>\n---\n Documentation/git-worktree.txt |  9 +++++++--\n builtin/worktree.c             | 13 +++++++++++--\n t/t2025-worktree-add.sh        | 26 +++++++++++++++++++-------\n 3 files changed, 37 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41585f535d..5d54f36a71 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>\n ------------\n +\n If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,\n-then, as a convenience, a new branch based at HEAD is created automatically,\n-as if `-b $(basename <path>)` was specified.\n+then, as a convenience, the new worktree is associated with a branch\n+(call it `<branch>`) named after `$(basename <path>)`.  If `<branch>`\n+doesn't exist, a new branch based on HEAD is automatically created as\n+if `-b <branch>` was given.  If `<branch>` does exist, it will be\n+checked out in the new worktree, if it's not checked out anywhere\n+else, otherwise the command will refuse to create the worktree (unless\n+`--force` is used).\n \n list::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 6bd32b6090..d3aeb4877d 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -391,8 +391,17 @@ static const char *dwim_branch(const char *path, const char **new_branch)\n {\n \tint n;\n \tconst char *s = worktree_basename(path, &n);\n-\t*new_branch = xstrndup(s, n);\n-\tUNLEAK(*new_branch);\n+\tconst char *branchname = xstrndup(s, n);\n+\tstruct strbuf ref = STRBUF_INIT;\n+\n+\tUNLEAK(branchname);\n+\tif (!strbuf_check_branch_ref(&ref, branchname) &&\n+\t    ref_exists(ref.buf)) {\n+\t\tstrbuf_release(&ref);\n+\t\treturn branchname;\n+\t}\n+\n+\t*new_branch = branchname;\n \tif (guess_remote) {\n \t\tstruct object_id oid;\n \t\tconst char *remote =\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 2b95944973..ad38507d00 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -198,13 +198,25 @@ test_expect_success '\"add\" with <branch> omitted' '\n \ttest_cmp_rev HEAD bat\n '\n \n-test_expect_success '\"add\" auto-vivify does not clobber existing branch' '\n-\ttest_commit c1 &&\n-\ttest_commit c2 &&\n-\tgit branch precious HEAD~1 &&\n-\ttest_must_fail git worktree add precious &&\n-\ttest_cmp_rev HEAD~1 precious &&\n-\ttest_path_is_missing precious\n+test_expect_success '\"add\" checks out existing branch of dwimd name' '\n+\tgit branch dwim HEAD~1 &&\n+\tgit worktree add dwim &&\n+\ttest_cmp_rev HEAD~1 dwim &&\n+\t(\n+\t\tcd dwim &&\n+\t\ttest_cmp_rev HEAD dwim\n+\t)\n+'\n+\n+test_expect_success '\"add <path>\" dwim fails with checked out branch' '\n+\tgit checkout -b test-branch &&\n+\ttest_must_fail git worktree add test-branch &&\n+\ttest_path_is_missing test-branch\n+'\n+\n+test_expect_success '\"add --force\" with existing dwimd name doesnt die' '\n+\tgit checkout test-branch &&\n+\tgit worktree add --force test-branch\n '\n \n test_expect_success '\"add\" no auto-vivify with --detach and <branch> omitted' '\n-- \n2.16.1.74.g7afd1c25cc.dirty\n\n"},{"id":"345943","messageId":"CAPig+cRor4UXXZhoAkhOQfe6W+oC84YFmA-KwpLspuEh_A4Zng@mail.gmail.com","threadId":"47657","inReplyTo":"20180424215635.9183-1-t.gummerer@gmail.com","subject":"Re: [PATCH v9 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-04-27T07:36:16Z","receivedAt":"2018-04-27T07:36:21Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Apr 24, 2018 at 5:56 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> Thanks Eric for the review and the suggestions on the previous round.\n>\n> Changes since the previous round:\n>\n> - UNLEAK new_branch after it was xstrndup'd\n> - update the commit message of 2/4 according to Eric's suggestions\n> - make force_new_branch a boolean flag in\n>   print_preparing_worktree_line, instead of using it as the branch\n>   name.  Instead use new_branch as the new branch name everywhere in\n>   that function.\n> - get rid of the ckeckout_existing_branch flag\n\nThanks. I did another full review of all the patches and played around\nwith the new functionality again for good measure. Everything looked\ngood, and I think the patches are now ready to graduate.\n\nFor what it's worth, the entire series is:\n\nReviewed-by: Eric Sunshine <sunshine@sunshineco.com>\n"},{"id":"346043","messageId":"20180428160950.GA17619@hank.intra.tgummerer.com","threadId":"47657","inReplyTo":"CAPig+cRor4UXXZhoAkhOQfe6W+oC84YFmA-KwpLspuEh_A4Zng@mail.gmail.com","subject":"Re: [PATCH v9 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2018-04-28T16:09:50Z","receivedAt":"2018-04-28T16:09:53Z","isPatch":true,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 04/27, Eric Sunshine wrote:\n> On Tue, Apr 24, 2018 at 5:56 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n> > Thanks Eric for the review and the suggestions on the previous round.\n> >\n> > Changes since the previous round:\n> >\n> > - UNLEAK new_branch after it was xstrndup'd\n> > - update the commit message of 2/4 according to Eric's suggestions\n> > - make force_new_branch a boolean flag in\n> >   print_preparing_worktree_line, instead of using it as the branch\n> >   name.  Instead use new_branch as the new branch name everywhere in\n> >   that function.\n> > - get rid of the ckeckout_existing_branch flag\n> \n> Thanks. I did another full review of all the patches and played around\n> with the new functionality again for good measure. Everything looked\n> good, and I think the patches are now ready to graduate.\n\nThanks for all your review work on this series!\n\n> For what it's worth, the entire series is:\n> \n> Reviewed-by: Eric Sunshine <sunshine@sunshineco.com>\n"},{"id":"346117","messageId":"xmqqh8ntzhe4.fsf@gitster-ct.c.googlers.com","threadId":"47657","inReplyTo":"20180428160950.GA17619@hank.intra.tgummerer.com","subject":"Re: [PATCH v9 0/4] worktree: teach \"add\" to check out existing branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-30T00:07:15Z","receivedAt":"2018-04-30T00:07:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Gummerer <t.gummerer@gmail.com> writes:\n\n> On 04/27, Eric Sunshine wrote:\n>> On Tue, Apr 24, 2018 at 5:56 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:\n>> > Thanks Eric for the review and the suggestions on the previous round.\n>> >\n>> > Changes since the previous round:\n>> >\n>> > - UNLEAK new_branch after it was xstrndup'd\n>> > - update the commit message of 2/4 according to Eric's suggestions\n>> > - make force_new_branch a boolean flag in\n>> >   print_preparing_worktree_line, instead of using it as the branch\n>> >   name.  Instead use new_branch as the new branch name everywhere in\n>> >   that function.\n>> > - get rid of the ckeckout_existing_branch flag\n>> \n>> Thanks. I did another full review of all the patches and played around\n>> with the new functionality again for good measure. Everything looked\n>> good, and I think the patches are now ready to graduate.\n>\n> Thanks for all your review work on this series!\n\nThanks, both.\n"}]}