{"thread":{"id":"39787","subject":"[PATCH v3 09/23] checkout: relocate --to's \"no branch specified\" check","startedAt":"2015-07-06T17:30:37Z","lastAt":"2015-07-08T16:58:05Z","messageCount":36,"participants":["Eric Sunshine","Junio C Hamano","Mark Levedahl"],"isPatch":true,"patchVersion":3,"patchTotal":23},"messages":[{"id":"265582","messageId":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":null,"subject":"[PATCH v3 00/23] replace \"checkout --to\" with \"worktree add\"","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:37Z","receivedAt":"2015-07-06T17:30:37Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"This is v3 of the series to replace \"git checkout --to\" with \"git\nworktree add\". It's built atop Duy's df0b6cf (worktree: new place for\n\"git prune --worktrees\", 2015-06-29). Thanks to Duy for his review\nof v2[*1*].\n\nA v2 to v3 interdiff is included below for ease of review.\n\nChanges since v2:\n\n* retire --to from git-checkout documentation (v1 did this, but v2\n  forgot)\n\n* add \"git worktree list\" to the enumeration of not-yet-implemented\n  commands in the BUGS section of the documentation\n\n* state only that \"git worktree add\" will create <path> rather than\n  mentioning that a pre-existing <path> is valid as long as it is an\n  empty directory[*2*]\n\n* fix comment stating that \"any valid value\" is acceptable as temporary\n  HEAD in the newly created worktree, as patch 8/23 proves this to be\n  false\n\n* use test_cmp_rev to simplify a couple new tests\n\n* minor grammatical fixes to documentation and a few commit messages\n\n[*1*]: http://thread.gmane.org/gmane.comp.version-control.git/273316\n[*2*]: http://article.gmane.org/gmane.comp.version-control.git/273358\n\nEric Sunshine (23):\n  Documentation/git-checkout: fix incorrect worktree prune command\n  Documentation/git-worktree: associate options with commands\n  Documentation: move linked worktree description from checkout to\n    worktree\n  Documentation/git-worktree: add BUGS section\n  Documentation/git-worktree: split technical info from general\n    description\n  Documentation/git-worktree: add high-level 'lock' overview\n  Documentation/git-worktree: add EXAMPLES section\n  checkout: fix bug with --to and relative HEAD\n  checkout: relocate --to's \"no branch specified\" check\n  checkout: prepare_linked_checkout: drop now-unused 'new' argument\n  checkout: make --to unconditionally verbose\n  checkout: drop 'checkout_opts' dependency from prepare_linked_checkout\n  worktree: introduce \"add\" command\n  worktree: add --force option\n  worktree: add --detach option\n  worktree: add -b/-B options\n  tests: worktree: retrofit \"checkout --to\" tests for \"worktree add\"\n  checkout: retire --to option\n  checkout: require worktree unconditionally\n  worktree: extract basename computation to new function\n  worktree: add: make -b/-B default to HEAD when <branch> is omitted\n  worktree: add: auto-vivify new branch when <branch> is omitted\n  checkout: retire --ignore-other-worktrees in favor of --force\n\n Documentation/git-checkout.txt                    |  81 +--------\n Documentation/git-worktree.txt                    | 141 ++++++++++++++-\n builtin/checkout.c                                | 161 +-----------------\n builtin/worktree.c                                | 198 ++++++++++++++++++++++\n git.c                                             |   2 +-\n t/{t2025-checkout-to.sh => t2025-worktree-add.sh} |  64 ++++---\n t/t2026-prune-linked-checkouts.sh                 |   2 +-\n t/t7410-submodule-checkout-to.sh                  |   4 +-\n 8 files changed, 382 insertions(+), 271 deletions(-)\n rename t/{t2025-checkout-to.sh => t2025-worktree-add.sh} (54%)\n\n-- \n2.5.0.rc1.197.g417e668\n\n\n--- 8< ---\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 41148ce..6c3085d 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -228,13 +228,6 @@ This means that you can use `git checkout -p` to selectively discard\n edits from your current working tree. See the ``Interactive Mode''\n section of linkgit:git-add[1] to learn how to operate the `--patch` mode.\n \n---to=<path>::\n-\tCheck out a branch in a separate working directory at\n-\t`<path>`. A new working directory is linked to the current\n-\trepository, sharing everything except working directory\n-\tspecific files such as HEAD, index, etc. See\n-\tlinkgit:git-worktree[1] for a description of linked worktrees.\n-\n <branch>::\n \tBranch to checkout; if it refers to a branch (i.e., a name that,\n \twhen prepended with \"refs/heads/\", is a valid ref), then that\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 938bdab..da71f50 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -47,13 +47,12 @@ COMMANDS\n --------\n add <path> [<branch>]::\n \n-Check out `<branch>` into a separate working directory, `<path>`, creating\n-`<path>` if necessary. The new working directory is linked to the current\n-repository, sharing everything except working directory specific files\n-such as HEAD, index, etc. If `<path>` already exists, it must be empty.\n+Create `<path>` and checkout `<branch>` into it. The new working directory\n+is linked to the current repository, sharing everything except working\n+directory specific files such as HEAD, index, etc.\n +\n-If `<branch>` is omitted and neither `-b` nor `-B` used, then, as a\n-convenience, a new branch rooted at HEAD is created automatically, as if\n+If `<branch>` is omitted and neither `-b` nor `-B` is used, then, as a\n+convenience, a new branch based at HEAD is created automatically, as if\n `-b $(basename <path>)` was specified.\n \n prune::\n@@ -137,10 +136,10 @@ linkgit:gitrepository-layout[5] for details.\n \n EXAMPLES\n --------\n-You are middle of a refactoring session and your boss comes in and demands\n-that you fix something immediately. You might typically use\n+You are in the middle of a refactoring session and your boss comes in and\n+demands that you fix something immediately. You might typically use\n linkgit:git-stash[1] to store your changes away temporarily, however, your\n-worktree is in such a state of disarray (with new, removed, moved files,\n+worktree is in such a state of disarray (with new, moved, and removed files,\n and other bits and pieces strewn around) that you don't want to risk\n disturbing any of it. Instead, you create a temporary linked worktree to\n make the emergency fix, remove it when done, and then resume your earlier\n@@ -167,6 +166,7 @@ performed manually, such as:\n - `remove` to remove a linked worktree and its administrative files (and\n   warn if the worktree is dirty)\n - `mv` to move or rename a worktree and update its administrative files\n+- `list` to list linked worktrees\n - `lock` to prevent automatic pruning of administrative files (for instance,\n   for a worktree on a portable device)\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 8a6c7fa..050b443 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -227,9 +227,14 @@ static int add_worktree(const char *path, const char **child_argv)\n \t\t   real_path(get_git_common_dir()), name);\n \t/*\n \t * This is to keep resolve_ref() happy. We need a valid HEAD\n-\t * or is_git_directory() will reject the directory. Any valid\n-\t * value would do because this value will be ignored and\n-\t * replaced at the next (real) checkout.\n+\t * or is_git_directory() will reject the directory. Moreover, HEAD\n+\t * in the new worktree must resolve to the same value as HEAD in\n+\t * the current tree since the command invoked to populate the new\n+\t * worktree will be handed the branch/ref specified by the user.\n+\t * For instance, if the user asks for the new worktree to be based\n+\t * at HEAD~5, then the resolved HEAD~5 in the new worktree must\n+\t * match the resolved HEAD~5 in the current tree in order to match\n+\t * the user's expectation.\n \t */\n \tif (!resolve_ref_unsafe(\"HEAD\", 0, rev, NULL))\n \t\tdie(_(\"unable to resolve HEAD\"));\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 59d73ff..8fe242f 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -141,17 +141,13 @@ test_expect_success '\"add\" from relative HEAD' '\n '\n \n test_expect_success '\"add -b\" with <branch> omitted' '\n-\tgit rev-parse HEAD >expected &&\n \tgit worktree add -b burble flornk &&\n-\tgit rev-parse burble >actual &&\n-\ttest_cmp expected actual\n+\ttest_cmp_rev HEAD burble\n '\n \n test_expect_success '\"add\" with <branch> omitted' '\n-\tgit rev-parse HEAD >expected &&\n \tgit worktree add wiffle/bat &&\n-\tgit rev-parse bat >actual &&\n-\ttest_cmp expected actual\n+\ttest_cmp_rev HEAD bat\n '\n \n test_done\n--- 8< ---\n"},{"id":"265600","messageId":"1436203860-846-2-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 01/23] Documentation/git-checkout: fix incorrect worktree prune command","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:38Z","receivedAt":"2015-07-06T17:30:38Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"This was missed when \"git prune --worktrees\" became \"git worktree prune\".\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-checkout.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 72def5b..ce223e6 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -444,7 +444,7 @@ When you are done with a linked working tree you can simply delete it.\n The working tree's entry in the repository's $GIT_DIR/worktrees\n directory will eventually be removed automatically (see\n `gc.pruneworktreesexpire` in linkgit::git-config[1]), or you can run\n-`git prune --worktrees` in the main or any linked working tree to\n+`git worktree prune` in the main or any linked working tree to\n clean up any stale entries in $GIT_DIR/worktrees.\n \n If you move a linked working directory to another file system, or\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265601","messageId":"1436203860-846-3-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 02/23] Documentation/git-worktree: associate options with commands","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:39Z","receivedAt":"2015-07-06T17:30:39Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"git-worktree options affect some worktree commands but not others, but\nthis is not necessarily obvious from the option descriptions. Make this\nclear by indicating explicitly which commands are affected by which\noptions.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 41103e5..1ac1217 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -28,15 +28,15 @@ OPTIONS\n \n -n::\n --dry-run::\n-\tDo not remove anything; just report what it would\n+\tWith `prune`, do not remove anything; just report what it would\n \tremove.\n \n -v::\n --verbose::\n-\tReport all removals.\n+\tWith `prune`, report all removals.\n \n --expire <time>::\n-\tOnly expire unused worktrees older than <time>.\n+\tWith `prune`, only expire unused worktrees older than <time>.\n \n SEE ALSO\n --------\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265581","messageId":"1436203860-846-4-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 03/23] Documentation: move linked worktree description from checkout to worktree","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:40Z","receivedAt":"2015-07-06T17:30:40Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Now that the git-worktree command exists, its documentation page is the\nnatural place for the linked worktree description to reside. Relocate\nthe \"MULTIPLE WORKING TREES\" description verbatim from git-checkout.txt\nto git-worktree.txt.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-checkout.txt | 69 ++----------------------------------------\n Documentation/git-worktree.txt | 62 +++++++++++++++++++++++++++++++++++++\n 2 files changed, 64 insertions(+), 67 deletions(-)\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex ce223e6..77b7141 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -229,8 +229,8 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.\n \tCheck out a branch in a separate working directory at\n \t`<path>`. A new working directory is linked to the current\n \trepository, sharing everything except working directory\n-\tspecific files such as HEAD, index... See \"MULTIPLE WORKING\n-\tTREES\" section for more information.\n+\tspecific files such as HEAD, index, etc. See\n+\tlinkgit:git-worktree[1] for a description of linked worktrees.\n \n --ignore-other-worktrees::\n \t`git checkout` refuses when the wanted ref is already checked\n@@ -401,71 +401,6 @@ $ git reflog -2 HEAD # or\n $ git log -g -2 HEAD\n ------------\n \n-MULTIPLE WORKING TREES\n-----------------------\n-\n-A git repository can support multiple working trees, allowing you to check\n-out more than one branch at a time.  With `git checkout --to` a new working\n-tree is associated with the repository.  This new working tree is called a\n-\"linked working tree\" as opposed to the \"main working tree\" prepared by \"git\n-init\" or \"git clone\".  A repository has one main working tree (if it's not a\n-bare repository) and zero or more linked working trees.\n-\n-Each linked working tree has a private sub-directory in the repository's\n-$GIT_DIR/worktrees directory.  The private sub-directory's name is usually\n-the base name of the linked working tree's path, possibly appended with a\n-number to make it unique.  For example, when `$GIT_DIR=/path/main/.git` the\n-command `git checkout --to /path/other/test-next next` creates the linked\n-working tree in `/path/other/test-next` and also creates a\n-`$GIT_DIR/worktrees/test-next` directory (or `$GIT_DIR/worktrees/test-next1`\n-if `test-next` is already taken).\n-\n-Within a linked working tree, $GIT_DIR is set to point to this private\n-directory (e.g. `/path/main/.git/worktrees/test-next` in the example) and\n-$GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR\n-(e.g. `/path/main/.git`). These settings are made in a `.git` file located at\n-the top directory of the linked working tree.\n-\n-Path resolution via `git rev-parse --git-path` uses either\n-$GIT_DIR or $GIT_COMMON_DIR depending on the path. For example, in the\n-linked working tree `git rev-parse --git-path HEAD` returns\n-`/path/main/.git/worktrees/test-next/HEAD` (not\n-`/path/other/test-next/.git/HEAD` or `/path/main/.git/HEAD`) while `git\n-rev-parse --git-path refs/heads/master` uses\n-$GIT_COMMON_DIR and returns `/path/main/.git/refs/heads/master`,\n-since refs are shared across all working trees.\n-\n-See linkgit:gitrepository-layout[5] for more information. The rule of\n-thumb is do not make any assumption about whether a path belongs to\n-$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something\n-inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.\n-\n-When you are done with a linked working tree you can simply delete it.\n-The working tree's entry in the repository's $GIT_DIR/worktrees\n-directory will eventually be removed automatically (see\n-`gc.pruneworktreesexpire` in linkgit::git-config[1]), or you can run\n-`git worktree prune` in the main or any linked working tree to\n-clean up any stale entries in $GIT_DIR/worktrees.\n-\n-If you move a linked working directory to another file system, or\n-within a file system that does not support hard links, you need to run\n-at least one git command inside the linked working directory\n-(e.g. `git status`) in order to update its entry in $GIT_DIR/worktrees\n-so that it does not get automatically removed.\n-\n-To prevent a $GIT_DIR/worktrees entry from from being pruned (which\n-can be useful in some situations, such as when the\n-entry's working tree is stored on a portable device), add a file named\n-'locked' to the entry's directory. The file contains the reason in\n-plain text. For example, if a linked working tree's `.git` file points\n-to `/path/main/.git/worktrees/test-next` then a file named\n-`/path/main/.git/worktrees/test-next/locked` will prevent the\n-`test-next` entry from being pruned.  See\n-linkgit:gitrepository-layout[5] for details.\n-\n-Multiple checkout support for submodules is incomplete. It is NOT\n-recommended to make multiple checkouts of a superproject.\n-\n EXAMPLES\n --------\n \ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 1ac1217..3d28896 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -17,6 +17,68 @@ DESCRIPTION\n Manage multiple worktrees attached to the same repository. These are\n created by the command `git checkout --to`.\n \n+A git repository can support multiple working trees, allowing you to check\n+out more than one branch at a time.  With `git checkout --to` a new working\n+tree is associated with the repository.  This new working tree is called a\n+\"linked working tree\" as opposed to the \"main working tree\" prepared by \"git\n+init\" or \"git clone\".  A repository has one main working tree (if it's not a\n+bare repository) and zero or more linked working trees.\n+\n+Each linked working tree has a private sub-directory in the repository's\n+$GIT_DIR/worktrees directory.  The private sub-directory's name is usually\n+the base name of the linked working tree's path, possibly appended with a\n+number to make it unique.  For example, when `$GIT_DIR=/path/main/.git` the\n+command `git checkout --to /path/other/test-next next` creates the linked\n+working tree in `/path/other/test-next` and also creates a\n+`$GIT_DIR/worktrees/test-next` directory (or `$GIT_DIR/worktrees/test-next1`\n+if `test-next` is already taken).\n+\n+Within a linked working tree, $GIT_DIR is set to point to this private\n+directory (e.g. `/path/main/.git/worktrees/test-next` in the example) and\n+$GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR\n+(e.g. `/path/main/.git`). These settings are made in a `.git` file located at\n+the top directory of the linked working tree.\n+\n+Path resolution via `git rev-parse --git-path` uses either\n+$GIT_DIR or $GIT_COMMON_DIR depending on the path. For example, in the\n+linked working tree `git rev-parse --git-path HEAD` returns\n+`/path/main/.git/worktrees/test-next/HEAD` (not\n+`/path/other/test-next/.git/HEAD` or `/path/main/.git/HEAD`) while `git\n+rev-parse --git-path refs/heads/master` uses\n+$GIT_COMMON_DIR and returns `/path/main/.git/refs/heads/master`,\n+since refs are shared across all working trees.\n+\n+See linkgit:gitrepository-layout[5] for more information. The rule of\n+thumb is do not make any assumption about whether a path belongs to\n+$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something\n+inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.\n+\n+When you are done with a linked working tree you can simply delete it.\n+The working tree's entry in the repository's $GIT_DIR/worktrees\n+directory will eventually be removed automatically (see\n+`gc.pruneworktreesexpire` in linkgit::git-config[1]), or you can run\n+`git worktree prune` in the main or any linked working tree to\n+clean up any stale entries in $GIT_DIR/worktrees.\n+\n+If you move a linked working directory to another file system, or\n+within a file system that does not support hard links, you need to run\n+at least one git command inside the linked working directory\n+(e.g. `git status`) in order to update its entry in $GIT_DIR/worktrees\n+so that it does not get automatically removed.\n+\n+To prevent a $GIT_DIR/worktrees entry from from being pruned (which\n+can be useful in some situations, such as when the\n+entry's working tree is stored on a portable device), add a file named\n+'locked' to the entry's directory. The file contains the reason in\n+plain text. For example, if a linked working tree's `.git` file points\n+to `/path/main/.git/worktrees/test-next` then a file named\n+`/path/main/.git/worktrees/test-next/locked` will prevent the\n+`test-next` entry from being pruned.  See\n+linkgit:gitrepository-layout[5] for details.\n+\n+Multiple checkout support for submodules is incomplete. It is NOT\n+recommended to make multiple checkouts of a superproject.\n+\n COMMANDS\n --------\n prune::\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265598","messageId":"1436203860-846-5-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 04/23] Documentation/git-worktree: add BUGS section","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:41Z","receivedAt":"2015-07-06T17:30:41Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Relocate submodule warning to BUGS and enumerate missing commands.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 19 ++++++++++++++++---\n 1 file changed, 16 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 3d28896..bf6a1e2 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -76,9 +76,6 @@ to `/path/main/.git/worktrees/test-next` then a file named\n `test-next` entry from being pruned.  See\n linkgit:gitrepository-layout[5] for details.\n \n-Multiple checkout support for submodules is incomplete. It is NOT\n-recommended to make multiple checkouts of a superproject.\n-\n COMMANDS\n --------\n prune::\n@@ -100,6 +97,22 @@ OPTIONS\n --expire <time>::\n \tWith `prune`, only expire unused worktrees older than <time>.\n \n+BUGS\n+----\n+Multiple checkout support for submodules is incomplete. It is NOT\n+recommended to make multiple checkouts of a superproject.\n+\n+git-worktree could provide more automation for tasks currently\n+performed manually or via other commands, such as:\n+\n+- `add` to create a new linked worktree\n+- `remove` to remove a linked worktree and its administrative files (and\n+  warn if the worktree is dirty)\n+- `mv` to move or rename a worktree and update its administrative files\n+- `list` to list linked worktrees\n+- `lock` to prevent automatic pruning of administrative files (for instance,\n+  for a worktree on a portable device)\n+\n SEE ALSO\n --------\n \n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265602","messageId":"1436203860-846-6-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 05/23] Documentation/git-worktree: split technical info from general description","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:42Z","receivedAt":"2015-07-06T17:30:42Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"The DESCRIPTION section should provide a high-level overview of linked\nworktree functionality to bring users up to speed quickly, without\noverloading them with low-level details, so relocate the technical\ninformation to a new DETAILS section.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 70 ++++++++++++++++++++++--------------------\n 1 file changed, 36 insertions(+), 34 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex bf6a1e2..2954dc6 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -24,47 +24,18 @@ tree is associated with the repository.  This new working tree is called a\n init\" or \"git clone\".  A repository has one main working tree (if it's not a\n bare repository) and zero or more linked working trees.\n \n-Each linked working tree has a private sub-directory in the repository's\n-$GIT_DIR/worktrees directory.  The private sub-directory's name is usually\n-the base name of the linked working tree's path, possibly appended with a\n-number to make it unique.  For example, when `$GIT_DIR=/path/main/.git` the\n-command `git checkout --to /path/other/test-next next` creates the linked\n-working tree in `/path/other/test-next` and also creates a\n-`$GIT_DIR/worktrees/test-next` directory (or `$GIT_DIR/worktrees/test-next1`\n-if `test-next` is already taken).\n-\n-Within a linked working tree, $GIT_DIR is set to point to this private\n-directory (e.g. `/path/main/.git/worktrees/test-next` in the example) and\n-$GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR\n-(e.g. `/path/main/.git`). These settings are made in a `.git` file located at\n-the top directory of the linked working tree.\n-\n-Path resolution via `git rev-parse --git-path` uses either\n-$GIT_DIR or $GIT_COMMON_DIR depending on the path. For example, in the\n-linked working tree `git rev-parse --git-path HEAD` returns\n-`/path/main/.git/worktrees/test-next/HEAD` (not\n-`/path/other/test-next/.git/HEAD` or `/path/main/.git/HEAD`) while `git\n-rev-parse --git-path refs/heads/master` uses\n-$GIT_COMMON_DIR and returns `/path/main/.git/refs/heads/master`,\n-since refs are shared across all working trees.\n-\n-See linkgit:gitrepository-layout[5] for more information. The rule of\n-thumb is do not make any assumption about whether a path belongs to\n-$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something\n-inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.\n-\n When you are done with a linked working tree you can simply delete it.\n-The working tree's entry in the repository's $GIT_DIR/worktrees\n-directory will eventually be removed automatically (see\n+The working tree's administrative files in the repository (see\n+\"DETAILS\" below) will eventually be removed automatically (see\n `gc.pruneworktreesexpire` in linkgit::git-config[1]), or you can run\n `git worktree prune` in the main or any linked working tree to\n-clean up any stale entries in $GIT_DIR/worktrees.\n+clean up any stale administrative files.\n \n If you move a linked working directory to another file system, or\n within a file system that does not support hard links, you need to run\n at least one git command inside the linked working directory\n-(e.g. `git status`) in order to update its entry in $GIT_DIR/worktrees\n-so that it does not get automatically removed.\n+(e.g. `git status`) in order to update its administrative files in the\n+repository so that they do not get automatically pruned.\n \n To prevent a $GIT_DIR/worktrees entry from from being pruned (which\n can be useful in some situations, such as when the\n@@ -97,6 +68,37 @@ OPTIONS\n --expire <time>::\n \tWith `prune`, only expire unused worktrees older than <time>.\n \n+DETAILS\n+-------\n+Each linked working tree has a private sub-directory in the repository's\n+$GIT_DIR/worktrees directory.  The private sub-directory's name is usually\n+the base name of the linked working tree's path, possibly appended with a\n+number to make it unique.  For example, when `$GIT_DIR=/path/main/.git` the\n+command `git checkout --to /path/other/test-next next` creates the linked\n+working tree in `/path/other/test-next` and also creates a\n+`$GIT_DIR/worktrees/test-next` directory (or `$GIT_DIR/worktrees/test-next1`\n+if `test-next` is already taken).\n+\n+Within a linked working tree, $GIT_DIR is set to point to this private\n+directory (e.g. `/path/main/.git/worktrees/test-next` in the example) and\n+$GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR\n+(e.g. `/path/main/.git`). These settings are made in a `.git` file located at\n+the top directory of the linked working tree.\n+\n+Path resolution via `git rev-parse --git-path` uses either\n+$GIT_DIR or $GIT_COMMON_DIR depending on the path. For example, in the\n+linked working tree `git rev-parse --git-path HEAD` returns\n+`/path/main/.git/worktrees/test-next/HEAD` (not\n+`/path/other/test-next/.git/HEAD` or `/path/main/.git/HEAD`) while `git\n+rev-parse --git-path refs/heads/master` uses\n+$GIT_COMMON_DIR and returns `/path/main/.git/refs/heads/master`,\n+since refs are shared across all working trees.\n+\n+See linkgit:gitrepository-layout[5] for more information. The rule of\n+thumb is do not make any assumption about whether a path belongs to\n+$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something\n+inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.\n+\n BUGS\n ----\n Multiple checkout support for submodules is incomplete. It is NOT\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265603","messageId":"1436203860-846-7-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 06/23] Documentation/git-worktree: add high-level 'lock' overview","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:43Z","receivedAt":"2015-07-06T17:30:43Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Due to the (current) absence of a \"git worktree lock\" command, locking\na worktree's administrative files to prevent automatic pruning is a\nmanual task, necessarily requiring low-level understanding of linked\nworktree functionality. However, this level of detail does not belong\nin the high-level DESCRIPTION section, so add a generalized discussion\nof locking to DESCRIPTION and move the technical information to DETAILS.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 24 +++++++++++++++---------\n 1 file changed, 15 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 2954dc6..0385e9a 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -37,15 +37,11 @@ at least one git command inside the linked working directory\n (e.g. `git status`) in order to update its administrative files in the\n repository so that they do not get automatically pruned.\n \n-To prevent a $GIT_DIR/worktrees entry from from being pruned (which\n-can be useful in some situations, such as when the\n-entry's working tree is stored on a portable device), add a file named\n-'locked' to the entry's directory. The file contains the reason in\n-plain text. For example, if a linked working tree's `.git` file points\n-to `/path/main/.git/worktrees/test-next` then a file named\n-`/path/main/.git/worktrees/test-next/locked` will prevent the\n-`test-next` entry from being pruned.  See\n-linkgit:gitrepository-layout[5] for details.\n+If a linked working tree is stored on a portable device or network share\n+which is not always mounted, you can prevent its administrative files from\n+being pruned by creating a file named 'lock' alongside the other\n+administrative files, optionally containing a plain text reason that\n+pruning should be suppressed. See section \"DETAILS\" for more information.\n \n COMMANDS\n --------\n@@ -99,6 +95,16 @@ thumb is do not make any assumption about whether a path belongs to\n $GIT_DIR or $GIT_COMMON_DIR when you need to directly access something\n inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.\n \n+To prevent a $GIT_DIR/worktrees entry from from being pruned (which\n+can be useful in some situations, such as when the\n+entry's working tree is stored on a portable device), add a file named\n+'locked' to the entry's directory. The file contains the reason in\n+plain text. For example, if a linked working tree's `.git` file points\n+to `/path/main/.git/worktrees/test-next` then a file named\n+`/path/main/.git/worktrees/test-next/locked` will prevent the\n+`test-next` entry from being pruned.  See\n+linkgit:gitrepository-layout[5] for details.\n+\n BUGS\n ----\n Multiple checkout support for submodules is incomplete. It is NOT\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265599","messageId":"1436203860-846-8-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 07/23] Documentation/git-worktree: add EXAMPLES section","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:44Z","receivedAt":"2015-07-06T17:30:44Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 22 ++++++++++++++++++++++\n 1 file changed, 22 insertions(+)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 0385e9a..6afff1e 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -105,6 +105,28 @@ to `/path/main/.git/worktrees/test-next` then a file named\n `test-next` entry from being pruned.  See\n linkgit:gitrepository-layout[5] for details.\n \n+EXAMPLES\n+--------\n+You are in the middle of a refactoring session and your boss comes in and\n+demands that you fix something immediately. You might typically use\n+linkgit:git-stash[1] to store your changes away temporarily, however, your\n+worktree is in such a state of disarray (with new, moved, and removed files,\n+and other bits and pieces strewn around) that you don't want to risk\n+disturbing any of it. Instead, you create a temporary linked worktree to\n+make the emergency fix, remove it when done, and then resume your earlier\n+refactoring session.\n+\n+------------\n+$ git branch emergency-fix master\n+$ git checkout --to ../temp emergency-fix\n+$ pushd ../temp\n+# ... hack hack hack ...\n+$ git commit -a -m 'emergency fix for boss'\n+$ popd\n+$ rm -rf ../temp\n+$ git worktree prune\n+------------\n+\n BUGS\n ----\n Multiple checkout support for submodules is incomplete. It is NOT\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265583","messageId":"1436203860-846-9-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 08/23] checkout: fix bug with --to and relative HEAD","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:45Z","receivedAt":"2015-07-06T17:30:45Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Given \"git checkout --to <path> HEAD~1\", the new worktree's HEAD should\nbegin life at the current branch's HEAD~1, however, it actually ends up\nat HEAD~2. This happens because:\n\n    1. git-checkout resolves HEAD~1\n\n    2. to satisfy is_git_directory(), prepare_linked_worktree() creates\n       a HEAD for the new worktree with the value of the resolved HEAD~1\n\n    3. git-checkout re-invokes itself with the same arguments within the\n       new worktree to populate the worktree\n\n    4. the sub git-checkout resolves HEAD~1 relative to its own HEAD,\n       which is the resolved HEAD~1 from the original invocation,\n       resulting unexpectedly and incorrectly in HEAD~2 (relative to the\n       original)\n\nFix this by unconditionally assigning the current worktree's HEAD as the\nvalue of the new worktree's HEAD.\n\nAs a side-effect, this change also eliminates a dependence within\nprepare_linked_checkout() upon 'struct branch_info'. The plan is to\neventually relocate \"git checkout --to\" functionality to \"git worktree\nadd\", and worktree.c won't have knowledge of 'struct branch_info', so\nremoval of this dependency is a step toward that goal.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n builtin/checkout.c     | 16 ++++++++++++----\n t/t2025-checkout-to.sh | 10 ++++++++++\n 2 files changed, 22 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 2079aa4..5ada22a 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -863,6 +863,7 @@ static int prepare_linked_checkout(const struct checkout_opts *opts,\n \tstruct stat st;\n \tstruct child_process cp;\n \tint counter = 0, len, ret;\n+\tunsigned char rev[20];\n \n \tif (!new->commit)\n \t\tdie(_(\"no branch specified\"));\n@@ -920,13 +921,20 @@ static int prepare_linked_checkout(const struct checkout_opts *opts,\n \t\t   real_path(get_git_common_dir()), name);\n \t/*\n \t * This is to keep resolve_ref() happy. We need a valid HEAD\n-\t * or is_git_directory() will reject the directory. Any valid\n-\t * value would do because this value will be ignored and\n-\t * replaced at the next (real) checkout.\n+\t * or is_git_directory() will reject the directory. Moreover, HEAD\n+\t * in the new worktree must resolve to the same value as HEAD in\n+\t * the current tree since the command invoked to populate the new\n+\t * worktree will be handed the branch/ref specified by the user.\n+\t * For instance, if the user asks for the new worktree to be based\n+\t * at HEAD~5, then the resolved HEAD~5 in the new worktree must\n+\t * match the resolved HEAD~5 in the current tree in order to match\n+\t * the user's expectation.\n \t */\n+\tif (!resolve_ref_unsafe(\"HEAD\", 0, rev, NULL))\n+\t\tdie(_(\"unable to resolve HEAD\"));\n \tstrbuf_reset(&sb);\n \tstrbuf_addf(&sb, \"%s/HEAD\", sb_repo.buf);\n-\twrite_file(sb.buf, 1, \"%s\\n\", sha1_to_hex(new->commit->object.sha1));\n+\twrite_file(sb.buf, 1, \"%s\\n\", sha1_to_hex(rev));\n \tstrbuf_reset(&sb);\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, 1, \"../..\\n\");\ndiff --git a/t/t2025-checkout-to.sh b/t/t2025-checkout-to.sh\nindex a8d9336..0fd731b 100755\n--- a/t/t2025-checkout-to.sh\n+++ b/t/t2025-checkout-to.sh\n@@ -134,4 +134,14 @@ test_expect_success 'checkout with grafts' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'checkout --to from relative HEAD' '\n+\ttest_commit a &&\n+\ttest_commit b &&\n+\ttest_commit c &&\n+\tgit rev-parse HEAD~1 >expected &&\n+\tgit checkout --to relhead HEAD~1 &&\n+\tgit -C relhead rev-parse HEAD >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_done\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265580","messageId":"1436203860-846-10-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 09/23] checkout: relocate --to's \"no branch specified\" check","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:46Z","receivedAt":"2015-07-06T17:30:46Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"The plan is to relocate \"git checkout --to\" functionality to \"git\nworktree add\", however, this check expects a 'struct branch_info' which\ngit-worktree won't have at hand. It will, however, have access to its\nown command-line from which it can pick up the branch name. Therefore,\nas a preparatory step, rather than having prepare_linked_checkout()\nperform this check, make it the caller's responsibility.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n builtin/checkout.c | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 5ada22a..162c822 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -865,8 +865,6 @@ static int prepare_linked_checkout(const struct checkout_opts *opts,\n \tint counter = 0, len, ret;\n \tunsigned char rev[20];\n \n-\tif (!new->commit)\n-\t\tdie(_(\"no branch specified\"));\n \tif (file_exists(path) && !is_empty_dir(path))\n \t\tdie(_(\"'%s' already exists\"), path);\n \n@@ -1303,8 +1301,11 @@ static int checkout_branch(struct checkout_opts *opts,\n \t\tfree(head_ref);\n \t}\n \n-\tif (opts->new_worktree)\n+\tif (opts->new_worktree) {\n+\t\tif (!new->commit)\n+\t\t\tdie(_(\"no branch specified\"));\n \t\treturn prepare_linked_checkout(opts, new);\n+\t}\n \n \tif (!new->commit && opts->new_branch) {\n \t\tunsigned char rev[20];\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265597","messageId":"1436203860-846-11-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 10/23] checkout: prepare_linked_checkout: drop now-unused 'new' argument","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:47Z","receivedAt":"2015-07-06T17:30:47Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"The only references to 'new' were folded out by the last two patches.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n builtin/checkout.c | 5 ++---\n 1 file changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 162c822..134b6d6 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -854,8 +854,7 @@ static void remove_junk_on_signal(int signo)\n \traise(signo);\n }\n \n-static int prepare_linked_checkout(const struct checkout_opts *opts,\n-\t\t\t\t   struct branch_info *new)\n+static int prepare_linked_checkout(const struct checkout_opts *opts)\n {\n \tstruct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;\n \tstruct strbuf sb = STRBUF_INIT;\n@@ -1304,7 +1303,7 @@ static int checkout_branch(struct checkout_opts *opts,\n \tif (opts->new_worktree) {\n \t\tif (!new->commit)\n \t\t\tdie(_(\"no branch specified\"));\n-\t\treturn prepare_linked_checkout(opts, new);\n+\t\treturn prepare_linked_checkout(opts);\n \t}\n \n \tif (!new->commit && opts->new_branch) {\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265596","messageId":"1436203860-846-12-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 11/23] checkout: make --to unconditionally verbose","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:48Z","receivedAt":"2015-07-06T17:30:48Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"prepare_linked_checkout() respects git-checkout's --quiet flag, however,\nthe plan is to relocate \"git checkout --to\" functionality to \"git\nworktree add\", and git-worktree does not (yet) have a --quiet flag.\nConsequently, make prepare_linked_checkout() unconditionally verbose to\nease eventual code movement to worktree.c.\n\n(A --quiet flag can be added to git-worktree later if there is demand\nfor it.)\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n builtin/checkout.c | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 134b6d6..90bb3cd 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -936,8 +936,7 @@ static int prepare_linked_checkout(const struct checkout_opts *opts)\n \tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n \twrite_file(sb.buf, 1, \"../..\\n\");\n \n-\tif (!opts->quiet)\n-\t\tfprintf_ln(stderr, _(\"Enter %s (identifier %s)\"), path, name);\n+\tfprintf_ln(stderr, _(\"Enter %s (identifier %s)\"), path, name);\n \n \tsetenv(\"GIT_CHECKOUT_NEW_WORKTREE\", \"1\", 1);\n \tsetenv(GIT_DIR_ENVIRONMENT, sb_git.buf, 1);\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265591","messageId":"1436203860-846-13-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 12/23] checkout: drop 'checkout_opts' dependency from prepare_linked_checkout","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:49Z","receivedAt":"2015-07-06T17:30:49Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"The plan is to relocate \"git checkout --to\" functionality to \"git\nworktree add\", however, worktree.c won't have access to the 'struct\ncheckout_opts' passed to prepare_linked_worktree(), which it consults\nfor the pathname of the new worktree and the argv[] of the command it\nshould run to populate the new worktree. Facilitate relocation of\nprepare_linked_worktree() by instead having it accept the pathname and\nargv[] directly, thus eliminating the final references to 'struct\ncheckout_opts'.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n builtin/checkout.c | 9 +++++----\n 1 file changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 90bb3cd..e4064a8 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -854,11 +854,11 @@ static void remove_junk_on_signal(int signo)\n \traise(signo);\n }\n \n-static int prepare_linked_checkout(const struct checkout_opts *opts)\n+static int prepare_linked_checkout(const char *path, const char **child_argv)\n {\n \tstruct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;\n \tstruct strbuf sb = STRBUF_INIT;\n-\tconst char *path = opts->new_worktree, *name;\n+\tconst char *name;\n \tstruct stat st;\n \tstruct child_process cp;\n \tint counter = 0, len, ret;\n@@ -943,7 +943,7 @@ static int prepare_linked_checkout(const struct checkout_opts *opts)\n \tsetenv(GIT_WORK_TREE_ENVIRONMENT, path, 1);\n \tmemset(&cp, 0, sizeof(cp));\n \tcp.git_cmd = 1;\n-\tcp.argv = opts->saved_argv;\n+\tcp.argv = child_argv;\n \tret = run_command(&cp);\n \tif (!ret) {\n \t\tis_junk = 0;\n@@ -1302,7 +1302,8 @@ static int checkout_branch(struct checkout_opts *opts,\n \tif (opts->new_worktree) {\n \t\tif (!new->commit)\n \t\t\tdie(_(\"no branch specified\"));\n-\t\treturn prepare_linked_checkout(opts);\n+\t\treturn prepare_linked_checkout(opts->new_worktree,\n+\t\t\t\t\t       opts->saved_argv);\n \t}\n \n \tif (!new->commit && opts->new_branch) {\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265585","messageId":"1436203860-846-14-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 13/23] worktree: introduce \"add\" command","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:50Z","receivedAt":"2015-07-06T17:30:50Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"The plan is to relocate \"git checkout --to\" functionality to \"git\nworktree add\". As a first step, introduce a bare-bones git-worktree\n\"add\" command along with documentation. At this stage, \"git worktree\nadd\" merely invokes \"git checkout --to\" behind the scenes, but an\nupcoming patch will move the actual functionality\n(checkout.c:prepare_linked_checkout() and its helpers) to worktree.c.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 20 ++++++++++----------\n builtin/worktree.c             | 31 +++++++++++++++++++++++++++++++\n 2 files changed, 41 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 6afff1e..def3027 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -9,13 +9,13 @@ git-worktree - Manage multiple worktrees\n SYNOPSIS\n --------\n [verse]\n+'git worktree add' <path> <branch>\n 'git worktree prune' [-n] [-v] [--expire <expire>]\n \n DESCRIPTION\n -----------\n \n-Manage multiple worktrees attached to the same repository. These are\n-created by the command `git checkout --to`.\n+Manage multiple worktrees attached to the same repository.\n \n A git repository can support multiple working trees, allowing you to check\n out more than one branch at a time.  With `git checkout --to` a new working\n@@ -45,6 +45,12 @@ pruning should be suppressed. See section \"DETAILS\" for more information.\n \n COMMANDS\n --------\n+add <path> <branch>::\n+\n+Create `<path>` and checkout `<branch>` into it. The new working directory\n+is linked to the current repository, sharing everything except working\n+directory specific files such as HEAD, index, etc.\n+\n prune::\n \n Prune working tree information in $GIT_DIR/worktrees.\n@@ -118,7 +124,7 @@ refactoring session.\n \n ------------\n $ git branch emergency-fix master\n-$ git checkout --to ../temp emergency-fix\n+$ git worktree add ../temp emergency-fix\n $ pushd ../temp\n # ... hack hack hack ...\n $ git commit -a -m 'emergency fix for boss'\n@@ -133,9 +139,8 @@ Multiple checkout support for submodules is incomplete. It is NOT\n recommended to make multiple checkouts of a superproject.\n \n git-worktree could provide more automation for tasks currently\n-performed manually or via other commands, such as:\n+performed manually, such as:\n \n-- `add` to create a new linked worktree\n - `remove` to remove a linked worktree and its administrative files (and\n   warn if the worktree is dirty)\n - `mv` to move or rename a worktree and update its administrative files\n@@ -143,11 +148,6 @@ performed manually or via other commands, such as:\n - `lock` to prevent automatic pruning of administrative files (for instance,\n   for a worktree on a portable device)\n \n-SEE ALSO\n---------\n-\n-linkgit:git-checkout[1]\n-\n GIT\n ---\n Part of the linkgit:git[1] suite\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 2a729c6..e0749c0 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -2,8 +2,11 @@\n #include \"builtin.h\"\n #include \"dir.h\"\n #include \"parse-options.h\"\n+#include \"argv-array.h\"\n+#include \"run-command.h\"\n \n static const char * const worktree_usage[] = {\n+\tN_(\"git worktree add <path> <branch>\"),\n \tN_(\"git worktree prune [<options>]\"),\n \tNULL\n };\n@@ -119,6 +122,32 @@ static int prune(int ac, const char **av, const char *prefix)\n \treturn 0;\n }\n \n+static int add(int ac, const char **av, const char *prefix)\n+{\n+\tstruct child_process c;\n+\tconst char *path, *branch;\n+\tstruct argv_array cmd = ARGV_ARRAY_INIT;\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n+\n+\tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n+\tif (ac != 2)\n+\t\tusage_with_options(worktree_usage, options);\n+\n+\tpath = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0];\n+\tbranch = av[1];\n+\n+\targv_array_push(&cmd, \"checkout\");\n+\targv_array_pushl(&cmd, \"--to\", path, NULL);\n+\targv_array_push(&cmd, branch);\n+\n+\tmemset(&c, 0, sizeof(c));\n+\tc.git_cmd = 1;\n+\tc.argv = cmd.argv;\n+\treturn run_command(&c);\n+}\n+\n int cmd_worktree(int ac, const char **av, const char *prefix)\n {\n \tstruct option options[] = {\n@@ -127,6 +156,8 @@ int cmd_worktree(int ac, const char **av, const char *prefix)\n \n \tif (ac < 2)\n \t\tusage_with_options(worktree_usage, options);\n+\tif (!strcmp(av[1], \"add\"))\n+\t\treturn add(ac - 1, av + 1, prefix);\n \tif (!strcmp(av[1], \"prune\"))\n \t\treturn prune(ac - 1, av + 1, prefix);\n \tusage_with_options(worktree_usage, options);\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265586","messageId":"1436203860-846-15-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 14/23] worktree: add --force option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:51Z","receivedAt":"2015-07-06T17:30:51Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"By default, \"git worktree add\" refuses to create a new worktree when\nthe requested branch is already checked out elsewhere. Add a --force\noption to override this safeguard.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 8 +++++++-\n builtin/worktree.c             | 6 +++++-\n 2 files changed, 12 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex def3027..8891de0 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -9,7 +9,7 @@ git-worktree - Manage multiple worktrees\n SYNOPSIS\n --------\n [verse]\n-'git worktree add' <path> <branch>\n+'git worktree add' [-f] <path> <branch>\n 'git worktree prune' [-n] [-v] [--expire <expire>]\n \n DESCRIPTION\n@@ -58,6 +58,12 @@ Prune working tree information in $GIT_DIR/worktrees.\n OPTIONS\n -------\n \n+-f::\n+--force::\n+\tBy default, `add` refuses to create a new worktree when\t`<branch>`\n+\tis already checked out by another worktree. This option overrides\n+\tthat safeguard.\n+\n -n::\n --dry-run::\n \tWith `prune`, do not remove anything; just report what it would\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex e0749c0..8c35023 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -6,7 +6,7 @@\n #include \"run-command.h\"\n \n static const char * const worktree_usage[] = {\n-\tN_(\"git worktree add <path> <branch>\"),\n+\tN_(\"git worktree add [<options>] <path> <branch>\"),\n \tN_(\"git worktree prune [<options>]\"),\n \tNULL\n };\n@@ -125,9 +125,11 @@ static int prune(int ac, const char **av, const char *prefix)\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct child_process c;\n+\tint force = 0;\n \tconst char *path, *branch;\n \tstruct argv_array cmd = ARGV_ARRAY_INIT;\n \tstruct option options[] = {\n+\t\tOPT__FORCE(&force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n \t\tOPT_END()\n \t};\n \n@@ -140,6 +142,8 @@ static int add(int ac, const char **av, const char *prefix)\n \n \targv_array_push(&cmd, \"checkout\");\n \targv_array_pushl(&cmd, \"--to\", path, NULL);\n+\tif (force)\n+\t\targv_array_push(&cmd, \"--ignore-other-worktrees\");\n \targv_array_push(&cmd, branch);\n \n \tmemset(&c, 0, sizeof(c));\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265587","messageId":"1436203860-846-16-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 15/23] worktree: add --detach option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:52Z","receivedAt":"2015-07-06T17:30:52Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"One of git-worktree's roles is to populate the new worktree, much like\ngit-checkout, and thus, for convenience, ought to support several of the\nsame shortcuts. Toward this goal, add a --detach option to detach HEAD\nin the new worktree.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 6 +++++-\n builtin/worktree.c             | 5 ++++-\n 2 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 8891de0..231271b 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -9,7 +9,7 @@ git-worktree - Manage multiple worktrees\n SYNOPSIS\n --------\n [verse]\n-'git worktree add' [-f] <path> <branch>\n+'git worktree add' [-f] [--detach] <path> <branch>\n 'git worktree prune' [-n] [-v] [--expire <expire>]\n \n DESCRIPTION\n@@ -64,6 +64,10 @@ OPTIONS\n \tis already checked out by another worktree. This option overrides\n \tthat safeguard.\n \n+--detach::\n+\tWith `add`, detach HEAD in the new worktree. See \"DETACHED HEAD\" in\n+\tlinkgit:git-checkout[1].\n+\n -n::\n --dry-run::\n \tWith `prune`, do not remove anything; just report what it would\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 8c35023..9dc92b0 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -125,11 +125,12 @@ static int prune(int ac, const char **av, const char *prefix)\n static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct child_process c;\n-\tint force = 0;\n+\tint force = 0, detach = 0;\n \tconst char *path, *branch;\n \tstruct argv_array cmd = ARGV_ARRAY_INIT;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&force, N_(\"checkout <branch> even if already checked out in other worktree\")),\n+\t\tOPT_BOOL(0, \"detach\", &detach, N_(\"detach HEAD at named commit\")),\n \t\tOPT_END()\n \t};\n \n@@ -144,6 +145,8 @@ static int add(int ac, const char **av, const char *prefix)\n \targv_array_pushl(&cmd, \"--to\", path, NULL);\n \tif (force)\n \t\targv_array_push(&cmd, \"--ignore-other-worktrees\");\n+\tif (detach)\n+\t\targv_array_push(&cmd, \"--detach\");\n \targv_array_push(&cmd, branch);\n \n \tmemset(&c, 0, sizeof(c));\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265584","messageId":"1436203860-846-17-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 16/23] worktree: add -b/-B options","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:53Z","receivedAt":"2015-07-06T17:30:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"One of git-worktree's roles is to populate the new worktree, much like\ngit-checkout, and thus, for convenience, ought to support several of the\nsame shortcuts. Toward this goal, add -b/-B options to create a new\nbranch and check it out in the new worktree.\n\n(For brevity, only -b is mentioned in the synopsis; -B is omitted.)\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 13 ++++++++++---\n builtin/worktree.c             | 11 +++++++++++\n 2 files changed, 21 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 231271b..f44cd78 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -9,7 +9,7 @@ git-worktree - Manage multiple worktrees\n SYNOPSIS\n --------\n [verse]\n-'git worktree add' [-f] [--detach] <path> <branch>\n+'git worktree add' [-f] [--detach] [-b <new-branch>] <path> <branch>\n 'git worktree prune' [-n] [-v] [--expire <expire>]\n \n DESCRIPTION\n@@ -64,6 +64,14 @@ OPTIONS\n \tis already checked out by another worktree. This option overrides\n \tthat safeguard.\n \n+-b <new-branch>::\n+-B <new-branch>::\n+\tWith `add`, create a new branch named `<new-branch>` starting at\n+\t`<branch>`, and check out `<new-branch>` into the new worktree.\n+\tBy default, `-b` refuses to create a new branch if it already\n+\texists. `-B` overrides this safeguard, resetting `<new-branch>` to\n+\t`<branch>`.\n+\n --detach::\n \tWith `add`, detach HEAD in the new worktree. See \"DETACHED HEAD\" in\n \tlinkgit:git-checkout[1].\n@@ -133,8 +141,7 @@ make the emergency fix, remove it when done, and then resume your earlier\n refactoring session.\n \n ------------\n-$ git branch emergency-fix master\n-$ git worktree add ../temp emergency-fix\n+$ git worktree add -b emergency-fix ../temp master\n $ pushd ../temp\n # ... hack hack hack ...\n $ git commit -a -m 'emergency fix for boss'\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 9dc92b0..d6d0eee 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -126,15 +126,22 @@ static int add(int ac, const char **av, const char *prefix)\n {\n \tstruct child_process c;\n \tint force = 0, detach = 0;\n+\tconst char *new_branch = NULL, *new_branch_force = NULL;\n \tconst char *path, *branch;\n \tstruct argv_array cmd = ARGV_ARRAY_INIT;\n \tstruct option options[] = {\n \t\tOPT__FORCE(&force, N_(\"checkout <branch> even if already checked out in other worktree\")),\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 \t\tOPT_BOOL(0, \"detach\", &detach, N_(\"detach HEAD at named commit\")),\n \t\tOPT_END()\n \t};\n \n \tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n+\tif (new_branch && new_branch_force)\n+\t\tdie(_(\"-b and -B are mutually exclusive\"));\n \tif (ac != 2)\n \t\tusage_with_options(worktree_usage, options);\n \n@@ -145,6 +152,10 @@ static int add(int ac, const char **av, const char *prefix)\n \targv_array_pushl(&cmd, \"--to\", path, NULL);\n \tif (force)\n \t\targv_array_push(&cmd, \"--ignore-other-worktrees\");\n+\tif (new_branch)\n+\t\targv_array_pushl(&cmd, \"-b\", new_branch, NULL);\n+\tif (new_branch_force)\n+\t\targv_array_pushl(&cmd, \"-B\", new_branch_force, NULL);\n \tif (detach)\n \t\targv_array_push(&cmd, \"--detach\");\n \targv_array_push(&cmd, branch);\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265593","messageId":"1436203860-846-18-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 17/23] tests: worktree: retrofit \"checkout --to\" tests for \"worktree add\"","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:54Z","receivedAt":"2015-07-06T17:30:54Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"With the introduction of \"git worktree add\", \"git checkout --to\" is\nslated for removal. Therefore, retrofit linked worktree creation tests\nto use \"git worktree add\" instead.\n\n(The test to check exclusivity of \"checkout --to\" and \"checkout <paths>\"\nis dropped altogether since it becomes meaningless with retirement of\n\"checkout --to\".)\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n t/{t2025-checkout-to.sh => t2025-worktree-add.sh} | 48 +++++++++++------------\n t/t2026-prune-linked-checkouts.sh                 |  2 +-\n t/t7410-submodule-checkout-to.sh                  |  4 +-\n 3 files changed, 25 insertions(+), 29 deletions(-)\n rename t/{t2025-checkout-to.sh => t2025-worktree-add.sh} (59%)\n\ndiff --git a/t/t2025-checkout-to.sh b/t/t2025-worktree-add.sh\nsimilarity index 59%\nrename from t/t2025-checkout-to.sh\nrename to t/t2025-worktree-add.sh\nindex 0fd731b..192c936 100755\n--- a/t/t2025-checkout-to.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -1,6 +1,6 @@\n #!/bin/sh\n \n-test_description='test git checkout --to'\n+test_description='test git worktree add'\n \n . ./test-lib.sh\n \n@@ -8,22 +8,18 @@ test_expect_success 'setup' '\n \ttest_commit init\n '\n \n-test_expect_success 'checkout --to not updating paths' '\n-\ttest_must_fail git checkout --to -- init.t\n-'\n-\n-test_expect_success 'checkout --to an existing worktree' '\n+test_expect_success '\"add\" an existing worktree' '\n \tmkdir -p existing/subtree &&\n-\ttest_must_fail git checkout --detach --to existing master\n+\ttest_must_fail git worktree add --detach existing master\n '\n \n-test_expect_success 'checkout --to an existing empty worktree' '\n+test_expect_success '\"add\" an existing empty worktree' '\n \tmkdir existing_empty &&\n-\tgit checkout --detach --to existing_empty master\n+\tgit worktree add --detach existing_empty master\n '\n \n-test_expect_success 'checkout --to refuses to checkout locked branch' '\n-\ttest_must_fail git checkout --to zere master &&\n+test_expect_success '\"add\" refuses to checkout locked branch' '\n+\ttest_must_fail git worktree add zere master &&\n \t! test -d zere &&\n \t! test -d .git/worktrees/zere\n '\n@@ -36,9 +32,9 @@ test_expect_success 'checking out paths not complaining about linked checkouts'\n \t)\n '\n \n-test_expect_success 'checkout --to a new worktree' '\n+test_expect_success '\"add\" worktree' '\n \tgit rev-parse HEAD >expect &&\n-\tgit checkout --detach --to here master &&\n+\tgit worktree add --detach here master &&\n \t(\n \t\tcd here &&\n \t\ttest_cmp ../init.t init.t &&\n@@ -49,27 +45,27 @@ test_expect_success 'checkout --to a new worktree' '\n \t)\n '\n \n-test_expect_success 'checkout --to a new worktree from a subdir' '\n+test_expect_success '\"add\" worktree from a subdir' '\n \t(\n \t\tmkdir sub &&\n \t\tcd sub &&\n-\t\tgit checkout --detach --to here master &&\n+\t\tgit worktree add --detach here master &&\n \t\tcd here &&\n \t\ttest_cmp ../../init.t init.t\n \t)\n '\n \n-test_expect_success 'checkout --to from a linked checkout' '\n+test_expect_success '\"add\" from a linked checkout' '\n \t(\n \t\tcd here &&\n-\t\tgit checkout --detach --to nested-here master &&\n+\t\tgit worktree add --detach nested-here master &&\n \t\tcd nested-here &&\n \t\tgit fsck\n \t)\n '\n \n-test_expect_success 'checkout --to a new worktree creating new branch' '\n-\tgit checkout --to there -b newmaster master &&\n+test_expect_success '\"add\" worktree creating new branch' '\n+\tgit worktree add -b newmaster there master &&\n \t(\n \t\tcd there &&\n \t\ttest_cmp ../init.t init.t &&\n@@ -90,7 +86,7 @@ test_expect_success 'die the same branch is already checked out' '\n test_expect_success 'not die the same branch is already checked out' '\n \t(\n \t\tcd here &&\n-\t\tgit checkout --ignore-other-worktrees --to anothernewmaster newmaster\n+\t\tgit worktree add --force anothernewmaster newmaster\n \t)\n '\n \n@@ -101,15 +97,15 @@ test_expect_success 'not die on re-checking out current branch' '\n \t)\n '\n \n-test_expect_success 'checkout --to from a bare repo' '\n+test_expect_success '\"add\" from a bare repo' '\n \t(\n \t\tgit clone --bare . bare &&\n \t\tcd bare &&\n-\t\tgit checkout --to ../there2 -b bare-master master\n+\t\tgit worktree add -b bare-master ../there2 master\n \t)\n '\n \n-test_expect_success 'checkout from a bare repo without --to' '\n+test_expect_success 'checkout from a bare repo without \"add\"' '\n \t(\n \t\tcd bare &&\n \t\ttest_must_fail git checkout master\n@@ -129,17 +125,17 @@ test_expect_success 'checkout with grafts' '\n \tEOF\n \tgit log --format=%s -2 >actual &&\n \ttest_cmp expected actual &&\n-\tgit checkout --detach --to grafted master &&\n+\tgit worktree add --detach grafted master &&\n \tgit --git-dir=grafted/.git log --format=%s -2 >actual &&\n \ttest_cmp expected actual\n '\n \n-test_expect_success 'checkout --to from relative HEAD' '\n+test_expect_success '\"add\" from relative HEAD' '\n \ttest_commit a &&\n \ttest_commit b &&\n \ttest_commit c &&\n \tgit rev-parse HEAD~1 >expected &&\n-\tgit checkout --to relhead HEAD~1 &&\n+\tgit worktree add relhead HEAD~1 &&\n \tgit -C relhead rev-parse HEAD >actual &&\n \ttest_cmp expected actual\n '\ndiff --git a/t/t2026-prune-linked-checkouts.sh b/t/t2026-prune-linked-checkouts.sh\nindex e872f02..a0f1e3b 100755\n--- a/t/t2026-prune-linked-checkouts.sh\n+++ b/t/t2026-prune-linked-checkouts.sh\n@@ -88,7 +88,7 @@ test_expect_success 'not prune recent checkouts' '\n \n test_expect_success 'not prune proper checkouts' '\n \ttest_when_finished rm -r .git/worktrees &&\n-\tgit checkout \"--to=$PWD/nop\" --detach master &&\n+\tgit worktree add --detach \"$PWD/nop\" master &&\n \tgit worktree prune &&\n \ttest -d .git/worktrees/nop\n '\ndiff --git a/t/t7410-submodule-checkout-to.sh b/t/t7410-submodule-checkout-to.sh\nindex 8f30aed..3f609e8 100755\n--- a/t/t7410-submodule-checkout-to.sh\n+++ b/t/t7410-submodule-checkout-to.sh\n@@ -33,7 +33,7 @@ rev1_hash_sub=$(git --git-dir=origin/sub/.git show --pretty=format:%h -q \"HEAD~1\n test_expect_success 'checkout main' \\\n     'mkdir default_checkout &&\n     (cd clone/main &&\n-\tgit checkout --to \"$base_path/default_checkout/main\" \"$rev1_hash_main\")'\n+\tgit worktree add \"$base_path/default_checkout/main\" \"$rev1_hash_main\")'\n \n test_expect_failure 'can see submodule diffs just after checkout' \\\n     '(cd default_checkout/main && git diff --submodule master\"^!\" | grep \"file1 updated\")'\n@@ -41,7 +41,7 @@ test_expect_failure 'can see submodule diffs just after checkout' \\\n test_expect_success 'checkout main and initialize independed clones' \\\n     'mkdir fully_cloned_submodule &&\n     (cd clone/main &&\n-\tgit checkout --to \"$base_path/fully_cloned_submodule/main\" \"$rev1_hash_main\") &&\n+\tgit worktree add \"$base_path/fully_cloned_submodule/main\" \"$rev1_hash_main\") &&\n     (cd fully_cloned_submodule/main && git submodule update)'\n \n test_expect_success 'can see submodule diffs after independed cloning' \\\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265594","messageId":"1436203860-846-19-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 18/23] checkout: retire --to option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:55Z","receivedAt":"2015-07-06T17:30:55Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Now that \"git worktree add\" has achieved user-facing feature-parity with\n\"git checkout --to\", retire the latter.\n\nMove the actual linked worktree creation functionality,\nprepare_linked_checkout() and its helpers, verbatim from checkout.c to\nworktree.c.\n\nThis effectively reverts changes to checkout.c by 529fef2 (checkout:\nsupport checking out into a new working directory, 2014-11-30) with the\nexception of merge_working_tree() and switch_branches() which still\nrequire specialized knowledge that a the checkout is occurring in a\nnewly-created linked worktree (signaled to them by the private\nGIT_CHECKOUT_NEW_WORKTREE environment variable).\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-checkout.txt |   7 --\n builtin/checkout.c             | 161 +----------------------------------------\n builtin/worktree.c             | 144 ++++++++++++++++++++++++++++++++++--\n 3 files changed, 139 insertions(+), 173 deletions(-)\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 77b7141..efe6a02 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -225,13 +225,6 @@ This means that you can use `git checkout -p` to selectively discard\n edits from your current working tree. See the ``Interactive Mode''\n section of linkgit:git-add[1] to learn how to operate the `--patch` mode.\n \n---to=<path>::\n-\tCheck out a branch in a separate working directory at\n-\t`<path>`. A new working directory is linked to the current\n-\trepository, sharing everything except working directory\n-\tspecific files such as HEAD, index, etc. See\n-\tlinkgit:git-worktree[1] for a description of linked worktrees.\n-\n --ignore-other-worktrees::\n \t`git checkout` refuses when the wanted ref is already checked\n \tout by another worktree. This option makes it check the ref\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex e4064a8..b1e68b3 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -19,8 +19,6 @@\n #include \"ll-merge.h\"\n #include \"resolve-undo.h\"\n #include \"submodule.h\"\n-#include \"argv-array.h\"\n-#include \"sigchain.h\"\n \n static const char * const checkout_usage[] = {\n \tN_(\"git checkout [options] <branch>\"),\n@@ -51,8 +49,6 @@ struct checkout_opts {\n \tstruct pathspec pathspec;\n \tstruct tree *source_tree;\n \n-\tconst char *new_worktree;\n-\tconst char **saved_argv;\n \tint new_worktree_mode;\n };\n \n@@ -255,9 +251,6 @@ static int checkout_paths(const struct checkout_opts *opts,\n \t\tdie(_(\"Cannot update paths and switch to branch '%s' at the same time.\"),\n \t\t    opts->new_branch);\n \n-\tif (opts->new_worktree)\n-\t\tdie(_(\"'%s' cannot be used with updating paths\"), \"--to\");\n-\n \tif (opts->patch_mode)\n \t\treturn run_add_interactive(revision, \"--patch=checkout\",\n \t\t\t\t\t   &opts->pathspec);\n@@ -825,142 +818,6 @@ static int switch_branches(const struct checkout_opts *opts,\n \treturn ret || writeout_error;\n }\n \n-static char *junk_work_tree;\n-static char *junk_git_dir;\n-static int is_junk;\n-static pid_t junk_pid;\n-\n-static void remove_junk(void)\n-{\n-\tstruct strbuf sb = STRBUF_INIT;\n-\tif (!is_junk || getpid() != junk_pid)\n-\t\treturn;\n-\tif (junk_git_dir) {\n-\t\tstrbuf_addstr(&sb, junk_git_dir);\n-\t\tremove_dir_recursively(&sb, 0);\n-\t\tstrbuf_reset(&sb);\n-\t}\n-\tif (junk_work_tree) {\n-\t\tstrbuf_addstr(&sb, junk_work_tree);\n-\t\tremove_dir_recursively(&sb, 0);\n-\t}\n-\tstrbuf_release(&sb);\n-}\n-\n-static void remove_junk_on_signal(int signo)\n-{\n-\tremove_junk();\n-\tsigchain_pop(signo);\n-\traise(signo);\n-}\n-\n-static int prepare_linked_checkout(const char *path, const char **child_argv)\n-{\n-\tstruct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;\n-\tstruct strbuf sb = STRBUF_INIT;\n-\tconst char *name;\n-\tstruct stat st;\n-\tstruct child_process cp;\n-\tint counter = 0, len, ret;\n-\tunsigned char rev[20];\n-\n-\tif (file_exists(path) && !is_empty_dir(path))\n-\t\tdie(_(\"'%s' already exists\"), path);\n-\n-\tlen = strlen(path);\n-\twhile (len && is_dir_sep(path[len - 1]))\n-\t\tlen--;\n-\n-\tfor (name = path + len - 1; name > path; name--)\n-\t\tif (is_dir_sep(*name)) {\n-\t\t\tname++;\n-\t\t\tbreak;\n-\t\t}\n-\tstrbuf_addstr(&sb_repo,\n-\t\t      git_path(\"worktrees/%.*s\", (int)(path + len - name), name));\n-\tlen = sb_repo.len;\n-\tif (safe_create_leading_directories_const(sb_repo.buf))\n-\t\tdie_errno(_(\"could not create leading directories of '%s'\"),\n-\t\t\t  sb_repo.buf);\n-\twhile (!stat(sb_repo.buf, &st)) {\n-\t\tcounter++;\n-\t\tstrbuf_setlen(&sb_repo, len);\n-\t\tstrbuf_addf(&sb_repo, \"%d\", counter);\n-\t}\n-\tname = strrchr(sb_repo.buf, '/') + 1;\n-\n-\tjunk_pid = getpid();\n-\tatexit(remove_junk);\n-\tsigchain_push_common(remove_junk_on_signal);\n-\n-\tif (mkdir(sb_repo.buf, 0777))\n-\t\tdie_errno(_(\"could not create directory of '%s'\"), sb_repo.buf);\n-\tjunk_git_dir = xstrdup(sb_repo.buf);\n-\tis_junk = 1;\n-\n-\t/*\n-\t * lock the incomplete repo so prune won't delete it, unlock\n-\t * after the preparation is over.\n-\t */\n-\tstrbuf_addf(&sb, \"%s/locked\", sb_repo.buf);\n-\twrite_file(sb.buf, 1, \"initializing\\n\");\n-\n-\tstrbuf_addf(&sb_git, \"%s/.git\", path);\n-\tif (safe_create_leading_directories_const(sb_git.buf))\n-\t\tdie_errno(_(\"could not create leading directories of '%s'\"),\n-\t\t\t  sb_git.buf);\n-\tjunk_work_tree = xstrdup(path);\n-\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"%s/gitdir\", sb_repo.buf);\n-\twrite_file(sb.buf, 1, \"%s\\n\", real_path(sb_git.buf));\n-\twrite_file(sb_git.buf, 1, \"gitdir: %s/worktrees/%s\\n\",\n-\t\t   real_path(get_git_common_dir()), name);\n-\t/*\n-\t * This is to keep resolve_ref() happy. We need a valid HEAD\n-\t * or is_git_directory() will reject the directory. Moreover, HEAD\n-\t * in the new worktree must resolve to the same value as HEAD in\n-\t * the current tree since the command invoked to populate the new\n-\t * worktree will be handed the branch/ref specified by the user.\n-\t * For instance, if the user asks for the new worktree to be based\n-\t * at HEAD~5, then the resolved HEAD~5 in the new worktree must\n-\t * match the resolved HEAD~5 in the current tree in order to match\n-\t * the user's expectation.\n-\t */\n-\tif (!resolve_ref_unsafe(\"HEAD\", 0, rev, NULL))\n-\t\tdie(_(\"unable to resolve HEAD\"));\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"%s/HEAD\", sb_repo.buf);\n-\twrite_file(sb.buf, 1, \"%s\\n\", sha1_to_hex(rev));\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n-\twrite_file(sb.buf, 1, \"../..\\n\");\n-\n-\tfprintf_ln(stderr, _(\"Enter %s (identifier %s)\"), path, name);\n-\n-\tsetenv(\"GIT_CHECKOUT_NEW_WORKTREE\", \"1\", 1);\n-\tsetenv(GIT_DIR_ENVIRONMENT, sb_git.buf, 1);\n-\tsetenv(GIT_WORK_TREE_ENVIRONMENT, path, 1);\n-\tmemset(&cp, 0, sizeof(cp));\n-\tcp.git_cmd = 1;\n-\tcp.argv = child_argv;\n-\tret = run_command(&cp);\n-\tif (!ret) {\n-\t\tis_junk = 0;\n-\t\tfree(junk_work_tree);\n-\t\tfree(junk_git_dir);\n-\t\tjunk_work_tree = NULL;\n-\t\tjunk_git_dir = NULL;\n-\t}\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"%s/locked\", sb_repo.buf);\n-\tunlink_or_warn(sb.buf);\n-\tstrbuf_release(&sb);\n-\tstrbuf_release(&sb_repo);\n-\tstrbuf_release(&sb_git);\n-\treturn ret;\n-}\n-\n static int git_checkout_config(const char *var, const char *value, void *cb)\n {\n \tif (!strcmp(var, \"diff.ignoresubmodules\")) {\n@@ -1299,13 +1156,6 @@ static int checkout_branch(struct checkout_opts *opts,\n \t\tfree(head_ref);\n \t}\n \n-\tif (opts->new_worktree) {\n-\t\tif (!new->commit)\n-\t\t\tdie(_(\"no branch specified\"));\n-\t\treturn prepare_linked_checkout(opts->new_worktree,\n-\t\t\t\t\t       opts->saved_argv);\n-\t}\n-\n \tif (!new->commit && opts->new_branch) {\n \t\tunsigned char rev[20];\n \t\tint flag;\n@@ -1348,8 +1198,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"do not limit pathspecs to sparse entries only\")),\n \t\tOPT_HIDDEN_BOOL(0, \"guess\", &dwim_new_local_branch,\n \t\t\t\tN_(\"second guess 'git checkout no-such-branch'\")),\n-\t\tOPT_FILENAME(0, \"to\", &opts.new_worktree,\n-\t\t\t   N_(\"check a branch out in a separate working directory\")),\n \t\tOPT_BOOL(0, \"ignore-other-worktrees\", &opts.ignore_other_worktrees,\n \t\t\t N_(\"do not check if another worktree is holding the given ref\")),\n \t\tOPT_END(),\n@@ -1360,9 +1208,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \topts.overwrite_ignore = 1;\n \topts.prefix = prefix;\n \n-\topts.saved_argv = xmalloc(sizeof(const char *) * (argc + 2));\n-\tmemcpy(opts.saved_argv, argv, sizeof(const char *) * (argc + 1));\n-\n \tgitmodules_config();\n \tgit_config(git_checkout_config, &opts);\n \n@@ -1371,13 +1216,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options, checkout_usage,\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n-\t/* recursive execution from checkout_new_worktree() */\n \topts.new_worktree_mode = getenv(\"GIT_CHECKOUT_NEW_WORKTREE\") != NULL;\n-\tif (opts.new_worktree_mode)\n-\t\topts.new_worktree = NULL;\n \n-\tif (!opts.new_worktree)\n-\t\tsetup_work_tree();\n+\tsetup_work_tree();\n \n \tif (conflict_style) {\n \t\topts.merge = 1; /* implied */\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex d6d0eee..04e6d0f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -4,6 +4,7 @@\n #include \"parse-options.h\"\n #include \"argv-array.h\"\n #include \"run-command.h\"\n+#include \"sigchain.h\"\n \n static const char * const worktree_usage[] = {\n \tN_(\"git worktree add [<options>] <path> <branch>\"),\n@@ -122,9 +123,144 @@ static int prune(int ac, const char **av, const char *prefix)\n \treturn 0;\n }\n \n+static char *junk_work_tree;\n+static char *junk_git_dir;\n+static int is_junk;\n+static pid_t junk_pid;\n+\n+static void remove_junk(void)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tif (!is_junk || getpid() != junk_pid)\n+\t\treturn;\n+\tif (junk_git_dir) {\n+\t\tstrbuf_addstr(&sb, junk_git_dir);\n+\t\tremove_dir_recursively(&sb, 0);\n+\t\tstrbuf_reset(&sb);\n+\t}\n+\tif (junk_work_tree) {\n+\t\tstrbuf_addstr(&sb, junk_work_tree);\n+\t\tremove_dir_recursively(&sb, 0);\n+\t}\n+\tstrbuf_release(&sb);\n+}\n+\n+static void remove_junk_on_signal(int signo)\n+{\n+\tremove_junk();\n+\tsigchain_pop(signo);\n+\traise(signo);\n+}\n+\n+static int add_worktree(const char *path, const char **child_argv)\n+{\n+\tstruct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tconst char *name;\n+\tstruct stat st;\n+\tstruct child_process cp;\n+\tint counter = 0, len, ret;\n+\tunsigned char rev[20];\n+\n+\tif (file_exists(path) && !is_empty_dir(path))\n+\t\tdie(_(\"'%s' already exists\"), path);\n+\n+\tlen = strlen(path);\n+\twhile (len && is_dir_sep(path[len - 1]))\n+\t\tlen--;\n+\n+\tfor (name = path + len - 1; name > path; name--)\n+\t\tif (is_dir_sep(*name)) {\n+\t\t\tname++;\n+\t\t\tbreak;\n+\t\t}\n+\tstrbuf_addstr(&sb_repo,\n+\t\t      git_path(\"worktrees/%.*s\", (int)(path + len - name), name));\n+\tlen = sb_repo.len;\n+\tif (safe_create_leading_directories_const(sb_repo.buf))\n+\t\tdie_errno(_(\"could not create leading directories of '%s'\"),\n+\t\t\t  sb_repo.buf);\n+\twhile (!stat(sb_repo.buf, &st)) {\n+\t\tcounter++;\n+\t\tstrbuf_setlen(&sb_repo, len);\n+\t\tstrbuf_addf(&sb_repo, \"%d\", counter);\n+\t}\n+\tname = strrchr(sb_repo.buf, '/') + 1;\n+\n+\tjunk_pid = getpid();\n+\tatexit(remove_junk);\n+\tsigchain_push_common(remove_junk_on_signal);\n+\n+\tif (mkdir(sb_repo.buf, 0777))\n+\t\tdie_errno(_(\"could not create directory of '%s'\"), sb_repo.buf);\n+\tjunk_git_dir = xstrdup(sb_repo.buf);\n+\tis_junk = 1;\n+\n+\t/*\n+\t * lock the incomplete repo so prune won't delete it, unlock\n+\t * after the preparation is over.\n+\t */\n+\tstrbuf_addf(&sb, \"%s/locked\", sb_repo.buf);\n+\twrite_file(sb.buf, 1, \"initializing\\n\");\n+\n+\tstrbuf_addf(&sb_git, \"%s/.git\", path);\n+\tif (safe_create_leading_directories_const(sb_git.buf))\n+\t\tdie_errno(_(\"could not create leading directories of '%s'\"),\n+\t\t\t  sb_git.buf);\n+\tjunk_work_tree = xstrdup(path);\n+\n+\tstrbuf_reset(&sb);\n+\tstrbuf_addf(&sb, \"%s/gitdir\", sb_repo.buf);\n+\twrite_file(sb.buf, 1, \"%s\\n\", real_path(sb_git.buf));\n+\twrite_file(sb_git.buf, 1, \"gitdir: %s/worktrees/%s\\n\",\n+\t\t   real_path(get_git_common_dir()), name);\n+\t/*\n+\t * This is to keep resolve_ref() happy. We need a valid HEAD\n+\t * or is_git_directory() will reject the directory. Moreover, HEAD\n+\t * in the new worktree must resolve to the same value as HEAD in\n+\t * the current tree since the command invoked to populate the new\n+\t * worktree will be handed the branch/ref specified by the user.\n+\t * For instance, if the user asks for the new worktree to be based\n+\t * at HEAD~5, then the resolved HEAD~5 in the new worktree must\n+\t * match the resolved HEAD~5 in the current tree in order to match\n+\t * the user's expectation.\n+\t */\n+\tif (!resolve_ref_unsafe(\"HEAD\", 0, rev, NULL))\n+\t\tdie(_(\"unable to resolve HEAD\"));\n+\tstrbuf_reset(&sb);\n+\tstrbuf_addf(&sb, \"%s/HEAD\", sb_repo.buf);\n+\twrite_file(sb.buf, 1, \"%s\\n\", sha1_to_hex(rev));\n+\tstrbuf_reset(&sb);\n+\tstrbuf_addf(&sb, \"%s/commondir\", sb_repo.buf);\n+\twrite_file(sb.buf, 1, \"../..\\n\");\n+\n+\tfprintf_ln(stderr, _(\"Enter %s (identifier %s)\"), path, name);\n+\n+\tsetenv(\"GIT_CHECKOUT_NEW_WORKTREE\", \"1\", 1);\n+\tsetenv(GIT_DIR_ENVIRONMENT, sb_git.buf, 1);\n+\tsetenv(GIT_WORK_TREE_ENVIRONMENT, path, 1);\n+\tmemset(&cp, 0, sizeof(cp));\n+\tcp.git_cmd = 1;\n+\tcp.argv = child_argv;\n+\tret = run_command(&cp);\n+\tif (!ret) {\n+\t\tis_junk = 0;\n+\t\tfree(junk_work_tree);\n+\t\tfree(junk_git_dir);\n+\t\tjunk_work_tree = NULL;\n+\t\tjunk_git_dir = NULL;\n+\t}\n+\tstrbuf_reset(&sb);\n+\tstrbuf_addf(&sb, \"%s/locked\", sb_repo.buf);\n+\tunlink_or_warn(sb.buf);\n+\tstrbuf_release(&sb);\n+\tstrbuf_release(&sb_repo);\n+\tstrbuf_release(&sb_git);\n+\treturn ret;\n+}\n+\n static int add(int ac, const char **av, const char *prefix)\n {\n-\tstruct child_process c;\n \tint force = 0, detach = 0;\n \tconst char *new_branch = NULL, *new_branch_force = NULL;\n \tconst char *path, *branch;\n@@ -149,7 +285,6 @@ static int add(int ac, const char **av, const char *prefix)\n \tbranch = av[1];\n \n \targv_array_push(&cmd, \"checkout\");\n-\targv_array_pushl(&cmd, \"--to\", path, NULL);\n \tif (force)\n \t\targv_array_push(&cmd, \"--ignore-other-worktrees\");\n \tif (new_branch)\n@@ -160,10 +295,7 @@ static int add(int ac, const char **av, const char *prefix)\n \t\targv_array_push(&cmd, \"--detach\");\n \targv_array_push(&cmd, branch);\n \n-\tmemset(&c, 0, sizeof(c));\n-\tc.git_cmd = 1;\n-\tc.argv = cmd.argv;\n-\treturn run_command(&c);\n+\treturn add_worktree(path, cmd.argv);\n }\n \n int cmd_worktree(int ac, const char **av, const char *prefix)\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265595","messageId":"1436203860-846-20-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 19/23] checkout: require worktree unconditionally","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:56Z","receivedAt":"2015-07-06T17:30:56Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"In order to allow linked worktree creation via \"git checkout --to\" from\na bare repository, 3473ad0 (checkout: don't require a work tree when\nchecking out into a new one, 2014-11-30) dropped git-checkout's\nunconditional NEED_WORK_TREE requirement and instead performed worktree\nsetup conditionally based upon presence or absence of the --to option.\nNow that --to has been retired and git-checkout is no longer responsible\nfor linked worktree creation, the NEED_WORK_TREE requirement can be\nre-instated.\n\nThis effectively reverts 3473ad0, except for the tests it added which\nnow check bare repository behavior of \"git worktree add\" instead.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n builtin/checkout.c | 2 --\n git.c              | 2 +-\n 2 files changed, 1 insertion(+), 3 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex b1e68b3..5754554 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -1218,8 +1218,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \n \topts.new_worktree_mode = getenv(\"GIT_CHECKOUT_NEW_WORKTREE\") != NULL;\n \n-\tsetup_work_tree();\n-\n \tif (conflict_style) {\n \t\topts.merge = 1; /* implied */\n \t\tgit_xmerge_config(\"merge.conflictstyle\", conflict_style, NULL);\ndiff --git a/git.c b/git.c\nindex f227838..21a6398 100644\n--- a/git.c\n+++ b/git.c\n@@ -383,7 +383,7 @@ static struct cmd_struct commands[] = {\n \t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n \t{ \"check-ref-format\", cmd_check_ref_format },\n-\t{ \"checkout\", cmd_checkout, RUN_SETUP },\n+\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"checkout-index\", cmd_checkout_index,\n \t\tRUN_SETUP | NEED_WORK_TREE},\n \t{ \"cherry\", cmd_cherry, RUN_SETUP },\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265592","messageId":"1436203860-846-21-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 20/23] worktree: extract basename computation to new function","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:57Z","receivedAt":"2015-07-06T17:30:57Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"A subsequent patch will also need to compute the basename of the new\nworktree, so factor out this logic into a new function.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n builtin/worktree.c | 29 ++++++++++++++++++++---------\n 1 file changed, 20 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 04e6d0f..25fe25b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -152,6 +152,25 @@ static void remove_junk_on_signal(int signo)\n \traise(signo);\n }\n \n+static const char *worktree_basename(const char *path, int *olen)\n+{\n+\tconst char *name;\n+\tint len;\n+\n+\tlen = strlen(path);\n+\twhile (len && is_dir_sep(path[len - 1]))\n+\t\tlen--;\n+\n+\tfor (name = path + len - 1; name > path; name--)\n+\t\tif (is_dir_sep(*name)) {\n+\t\t\tname++;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t*olen = len;\n+\treturn name;\n+}\n+\n static int add_worktree(const char *path, const char **child_argv)\n {\n \tstruct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;\n@@ -165,15 +184,7 @@ static int add_worktree(const char *path, const char **child_argv)\n \tif (file_exists(path) && !is_empty_dir(path))\n \t\tdie(_(\"'%s' already exists\"), path);\n \n-\tlen = strlen(path);\n-\twhile (len && is_dir_sep(path[len - 1]))\n-\t\tlen--;\n-\n-\tfor (name = path + len - 1; name > path; name--)\n-\t\tif (is_dir_sep(*name)) {\n-\t\t\tname++;\n-\t\t\tbreak;\n-\t\t}\n+\tname = worktree_basename(path, &len);\n \tstrbuf_addstr(&sb_repo,\n \t\t      git_path(\"worktrees/%.*s\", (int)(path + len - name), name));\n \tlen = sb_repo.len;\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265589","messageId":"1436203860-846-22-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 21/23] worktree: add: make -b/-B default to HEAD when <branch> is omitted","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:58Z","receivedAt":"2015-07-06T17:30:58Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"As a convenience, like \"git branch\" and \"git checkout -b\", make\n\"git worktree add -b <newbranch> <path> <branch>\" default to HEAD when\n<branch> is omitted.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 1 +\n builtin/worktree.c             | 6 ++++--\n t/t2025-worktree-add.sh        | 5 +++++\n 3 files changed, 10 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex f44cd78..377ae0f 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -68,6 +68,7 @@ OPTIONS\n -B <new-branch>::\n \tWith `add`, create a new branch named `<new-branch>` starting at\n \t`<branch>`, and check out `<new-branch>` into the new worktree.\n+\tIf `<branch>` is omitted, it defaults to HEAD.\n \tBy default, `-b` refuses to create a new branch if it already\n \texists. `-B` overrides this safeguard, resetting `<new-branch>` to\n \t`<branch>`.\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 25fe25b..323d444 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -289,11 +289,13 @@ static int add(int ac, const char **av, const char *prefix)\n \tac = parse_options(ac, av, prefix, options, worktree_usage, 0);\n \tif (new_branch && new_branch_force)\n \t\tdie(_(\"-b and -B are mutually exclusive\"));\n-\tif (ac != 2)\n+\tif (ac < 1 || ac > 2)\n+\t\tusage_with_options(worktree_usage, options);\n+\tif (ac < 2 && !new_branch && !new_branch_force)\n \t\tusage_with_options(worktree_usage, options);\n \n \tpath = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0];\n-\tbranch = av[1];\n+\tbranch = ac < 2 ? \"HEAD\" : av[1];\n \n \targv_array_push(&cmd, \"checkout\");\n \tif (force)\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 192c936..8964dec 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -140,4 +140,9 @@ test_expect_success '\"add\" from relative HEAD' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success '\"add -b\" with <branch> omitted' '\n+\tgit worktree add -b burble flornk &&\n+\ttest_cmp_rev HEAD burble\n+'\n+\n test_done\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265588","messageId":"1436203860-846-23-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 22/23] worktree: add: auto-vivify new branch when <branch> is omitted","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:30:59Z","receivedAt":"2015-07-06T17:30:59Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"As a convenience, when <branch> is omitted from \"git worktree <path>\n<branch>\" and neither -b nor -B is used, automatically create a new\nbranch named after <path>, as if \"-b $(basename <path>)\" was specified.\nThus, \"git worktree add ../hotfix\" creates a new branch named \"hotfix\"\nand associates it with new worktree \"../hotfix\".\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n Documentation/git-worktree.txt | 8 ++++++--\n builtin/worktree.c             | 8 ++++++--\n t/t2025-worktree-add.sh        | 5 +++++\n 3 files changed, 17 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\nindex 377ae0f..da71f50 100644\n--- a/Documentation/git-worktree.txt\n+++ b/Documentation/git-worktree.txt\n@@ -9,7 +9,7 @@ git-worktree - Manage multiple worktrees\n SYNOPSIS\n --------\n [verse]\n-'git worktree add' [-f] [--detach] [-b <new-branch>] <path> <branch>\n+'git worktree add' [-f] [--detach] [-b <new-branch>] <path> [<branch>]\n 'git worktree prune' [-n] [-v] [--expire <expire>]\n \n DESCRIPTION\n@@ -45,11 +45,15 @@ pruning should be suppressed. See section \"DETAILS\" for more information.\n \n COMMANDS\n --------\n-add <path> <branch>::\n+add <path> [<branch>]::\n \n Create `<path>` and checkout `<branch>` into it. The new working directory\n is linked to the current repository, sharing everything except working\n directory specific files such as HEAD, index, etc.\n++\n+If `<branch>` is omitted and neither `-b` nor `-B` is used, then, as a\n+convenience, a new branch based at HEAD is created automatically, as if\n+`-b $(basename <path>)` was specified.\n \n prune::\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 323d444..69248ba 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -291,12 +291,16 @@ static int add(int ac, const char **av, const char *prefix)\n \t\tdie(_(\"-b and -B are mutually exclusive\"));\n \tif (ac < 1 || ac > 2)\n \t\tusage_with_options(worktree_usage, options);\n-\tif (ac < 2 && !new_branch && !new_branch_force)\n-\t\tusage_with_options(worktree_usage, options);\n \n \tpath = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0];\n \tbranch = ac < 2 ? \"HEAD\" : av[1];\n \n+\tif (ac < 2 && !new_branch && !new_branch_force) {\n+\t\tint n;\n+\t\tconst char *s = worktree_basename(path, &n);\n+\t\tnew_branch = xstrndup(s, n);\n+\t}\n+\n \targv_array_push(&cmd, \"checkout\");\n \tif (force)\n \t\targv_array_push(&cmd, \"--ignore-other-worktrees\");\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 8964dec..8fe242f 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -145,4 +145,9 @@ test_expect_success '\"add -b\" with <branch> omitted' '\n \ttest_cmp_rev HEAD burble\n '\n \n+test_expect_success '\"add\" with <branch> omitted' '\n+\tgit worktree add wiffle/bat &&\n+\ttest_cmp_rev HEAD bat\n+'\n+\n test_done\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265590","messageId":"1436203860-846-24-git-send-email-sunshine@sunshineco.com","threadId":"39787","inReplyTo":"1436203860-846-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 23/23] checkout: retire --ignore-other-worktrees in favor of --force","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-06T17:31:00Z","receivedAt":"2015-07-06T17:31:00Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"As a safeguard, checking out a branch already checked out by a different\nworktree is disallowed. This behavior can be overridden with\n--ignore-other-worktrees, however, this option is neither obvious nor\nparticularly discoverable. As a common safeguard override, --force is\nmore likely to come to mind. Therefore, overload it to also suppress the\ncheck for a branch already checked out elsewhere.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n\nI plopped this patch at the end of the series so that it can be dropped\neasily if desired since Junio indicated[1] that he would \"moderately\nobject\" to this change.\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/273032/focus=273108\n\n Documentation/git-checkout.txt | 9 +++------\n builtin/checkout.c             | 8 +++-----\n builtin/worktree.c             | 2 +-\n 3 files changed, 7 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex efe6a02..6c3085d 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -111,6 +111,9 @@ OPTIONS\n +\n When checking out paths from the index, do not fail upon unmerged\n entries; instead, unmerged entries are ignored.\n++\n+By default, checking out a branch already checked out in another worktree\n+is disallowed. This overrides that safeguard.\n \n --ours::\n --theirs::\n@@ -225,12 +228,6 @@ This means that you can use `git checkout -p` to selectively discard\n edits from your current working tree. See the ``Interactive Mode''\n section of linkgit:git-add[1] to learn how to operate the `--patch` mode.\n \n---ignore-other-worktrees::\n-\t`git checkout` refuses when the wanted ref is already checked\n-\tout by another worktree. This option makes it check the ref\n-\tout anyway. In other words, the ref can be held by more than one\n-\tworktree.\n-\n <branch>::\n \tBranch to checkout; if it refers to a branch (i.e., a name that,\n \twhen prepended with \"refs/heads/\", is a valid ref), then that\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 5754554..01c7c30 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -35,7 +35,6 @@ struct checkout_opts {\n \tint writeout_stage;\n \tint overwrite_ignore;\n \tint ignore_skipworktree;\n-\tint ignore_other_worktrees;\n \n \tconst char *new_branch;\n \tconst char *new_branch_force;\n@@ -903,7 +902,8 @@ static void check_linked_checkout(struct branch_info *new, const char *id)\n \t\tstrbuf_rtrim(&gitdir);\n \t} else\n \t\tstrbuf_addstr(&gitdir, get_git_common_dir());\n-\tdie(_(\"'%s' is already checked out at '%s'\"), new->name, gitdir.buf);\n+\tdie(_(\"'%s' is already checked out at '%s'; use --force to override\"),\n+\t    new->name, gitdir.buf);\n done:\n \tstrbuf_release(&path);\n \tstrbuf_release(&sb);\n@@ -1151,7 +1151,7 @@ static int checkout_branch(struct checkout_opts *opts,\n \t\tchar *head_ref = resolve_refdup(\"HEAD\", 0, sha1, &flag);\n \t\tif (head_ref &&\n \t\t    (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)) &&\n-\t\t    !opts->ignore_other_worktrees)\n+\t\t    !opts->force)\n \t\t\tcheck_linked_checkouts(new);\n \t\tfree(head_ref);\n \t}\n@@ -1198,8 +1198,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\t\t N_(\"do not limit pathspecs to sparse entries only\")),\n \t\tOPT_HIDDEN_BOOL(0, \"guess\", &dwim_new_local_branch,\n \t\t\t\tN_(\"second guess 'git checkout no-such-branch'\")),\n-\t\tOPT_BOOL(0, \"ignore-other-worktrees\", &opts.ignore_other_worktrees,\n-\t\t\t N_(\"do not check if another worktree is holding the given ref\")),\n \t\tOPT_END(),\n \t};\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 69248ba..050b443 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -303,7 +303,7 @@ static int add(int ac, const char **av, const char *prefix)\n \n \targv_array_push(&cmd, \"checkout\");\n \tif (force)\n-\t\targv_array_push(&cmd, \"--ignore-other-worktrees\");\n+\t\targv_array_push(&cmd, \"--force\");\n \tif (new_branch)\n \t\targv_array_pushl(&cmd, \"-b\", new_branch, NULL);\n \tif (new_branch_force)\n-- \n2.5.0.rc1.197.g417e668\n"},{"id":"265617","messageId":"xmqqpp45ytzh.fsf@gitster.dls.corp.google.com","threadId":"39787","inReplyTo":"1436203860-846-23-git-send-email-sunshine@sunshineco.com","subject":"Re: [PATCH v3 22/23] worktree: add: auto-vivify new branch when <branch> is omitted","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-07-06T19:19:14Z","receivedAt":"2015-07-06T19:19:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\n> index 377ae0f..da71f50 100644\n> --- a/Documentation/git-worktree.txt\n> +++ b/Documentation/git-worktree.txt\n> @@ -9,7 +9,7 @@ git-worktree - Manage multiple worktrees\n>  SYNOPSIS\n>  --------\n>  [verse]\n> -'git worktree add' [-f] [--detach] [-b <new-branch>] <path> <branch>\n> +'git worktree add' [-f] [--detach] [-b <new-branch>] <path> [<branch>]\n\nAhh, OK, this answers my previous question.\n\n> +\tif (ac < 2 && !new_branch && !new_branch_force) {\n> +\t\tint n;\n> +\t\tconst char *s = worktree_basename(path, &n);\n> +\t\tnew_branch = xstrndup(s, n);\n> +\t}\n> +\n\nand because this is new_branch, not new_branch_force, we will not\naccidentally clobber an existing branch.  The \"hotfix\" time is when\nthe end-user tends to be less careful, and it is a good thing to\nmake sure \"git worktree add ../hotfix\" will not clobber an unrelated\n\"hotfix\" branch.\n\nGood.\n\nWhich may be something we would want to have a test for, though.\n\n> diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> index 8964dec..8fe242f 100755\n> --- a/t/t2025-worktree-add.sh\n> +++ b/t/t2025-worktree-add.sh\n> @@ -145,4 +145,9 @@ test_expect_success '\"add -b\" with <branch> omitted' '\n>  \ttest_cmp_rev HEAD burble\n>  '\n>  \n> +test_expect_success '\"add\" with <branch> omitted' '\n> +\tgit worktree add wiffle/bat &&\n> +\ttest_cmp_rev HEAD bat\n> +'\n> +\n>  test_done\n"},{"id":"265620","messageId":"xmqqlhetyszz.fsf@gitster.dls.corp.google.com","threadId":"39787","inReplyTo":"1436203860-846-24-git-send-email-sunshine@sunshineco.com","subject":"Re: [PATCH v3 23/23] checkout: retire --ignore-other-worktrees in favor of --force","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-07-06T19:40:32Z","receivedAt":"2015-07-06T19:40:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> As a safeguard, checking out a branch already checked out by a different\n> worktree is disallowed. This behavior can be overridden with\n> --ignore-other-worktrees, however, this option is neither obvious nor\n> particularly discoverable. As a common safeguard override, --force is\n> more likely to come to mind. Therefore, overload it to also suppress the\n> check for a branch already checked out elsewhere.\n\nI hate to be asking this again but why is it a good idea to allow\n'ignore-other-worktrees' in the first place (let alone making it\nmore discoverable)?  You'll have multiple working trees, either\nusing the new \"git worktree\" or using the old contrib/workdir, for\none of the two reasons:\n\n * You need a separate work area to build a new history.\n\n * You need a separate work area to expand the contents of a\n   specific commit.\n\nHere \"create binary by running make\" falls into the latter category;\nas far as Git is concerned, you are only looking at, not extending\nthe history of any specific branch.\n\nIf you are extending the history of some branch, then you would want\nto be on that branch.  Why would you want to have another worktree\nthat will get into a confusing state once you create that commit on\nthe checked out branch in this newly created worktree?\n\nWasn't the whole point of making the primary repository aware of the\nsecondary worktrees via the \"linked checkout\" mechanism because that\nconfusion was the biggest sore point of the old contrib/workdir\nimplementation?\n"},{"id":"265621","messageId":"xmqqh9physyu.fsf@gitster.dls.corp.google.com","threadId":"39787","inReplyTo":"1436203860-846-19-git-send-email-sunshine@sunshineco.com","subject":"Re: [PATCH v3 18/23] checkout: retire --to option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-07-06T19:41:13Z","receivedAt":"2015-07-06T19:41:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> Now that \"git worktree add\" has achieved user-facing feature-parity with\n> \"git checkout --to\", retire the latter.\n>\n> Move the actual linked worktree creation functionality,\n> prepare_linked_checkout() and its helpers, verbatim from checkout.c to\n> worktree.c.\n>\n> This effectively reverts changes to checkout.c by 529fef2 (checkout:\n> support checking out into a new working directory, 2014-11-30) with the\n> exception of merge_working_tree() and switch_branches() which still\n> require specialized knowledge that a the checkout is occurring in a\n> newly-created linked worktree (signaled to them by the private\n> GIT_CHECKOUT_NEW_WORKTREE environment variable).\n\n\nI do not quite understand why we still need the hidden environment\nvariable.  Is this a sign that the implementation is shared too much\nbetween unrelated codepaths (or to put it another way, perhaps API\nfunctions that are not best fit are being used)?\n\nStepping back a bit, with or without the new \"linked worktree\"\nfeature, when you came across a repository whose working tree does\nnot have any file (i.e. somebody ran \"git ls-files | xargs rm\"), you\ndo not know and care what is in .git/index right now, you do not\nknow and care what branch its .git/HEAD points at, but you *do* know\nwhat branch you want to be on (or where you want its HEAD detached\nat), what would be the command you would use?\n\nThe state immediately after a new worktree is constructed by\npopulating /path/main/.git/worktrees/test-next/ and pointing it from\n/path/other/test-next/.git but before the index or the files under\n/path/other/test-next/ are populated is exactly that situation, no?\nWouldn't \"symbolic-ref HEAD the-branch-i-want\" (or \"update-ref HEAD\nthe-commit-i-want\" in the detached case) followed by \"reset --hard\"\nthe more natural thing to use, instead of merge-working-tree and\nswitch-branches that are implementation details of \"checkout\"?\n"},{"id":"265639","messageId":"20150707013301.GA26523@flurp.local","threadId":"39787","inReplyTo":"xmqqpp45ytzh.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 22/23] worktree: add: auto-vivify new branch when <branch> is omitted","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-07T01:33:01Z","receivedAt":"2015-07-07T01:33:01Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Jul 06, 2015 at 12:19:14PM -0700, Junio C Hamano wrote:\n> Eric Sunshine <sunshine@sunshineco.com> writes:\n> > diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt\n> > index 377ae0f..da71f50 100644\n> > --- a/Documentation/git-worktree.txt\n> > +++ b/Documentation/git-worktree.txt\n> > @@ -9,7 +9,7 @@ git-worktree - Manage multiple worktrees\n> >  SYNOPSIS\n> >  --------\n> >  [verse]\n> > -'git worktree add' [-f] [--detach] [-b <new-branch>] <path> <branch>\n> > +'git worktree add' [-f] [--detach] [-b <new-branch>] <path> [<branch>]\n> \n> Ahh, OK, this answers my previous question.\n\nRight. I considered squashing this patch with the previous one, in\nwhich case the synopsis question wouldn't have come up, but kept them\nseparate since they are (or can be) conceptually distinct, and the one\npatch builds upon the other (and keeping them separate makes them a\nbit easier to review).\n\n> > +\tif (ac < 2 && !new_branch && !new_branch_force) {\n> > +\t\tint n;\n> > +\t\tconst char *s = worktree_basename(path, &n);\n> > +\t\tnew_branch = xstrndup(s, n);\n> > +\t}\n> > +\n> \n> and because this is new_branch, not new_branch_force, we will not\n> accidentally clobber an existing branch.  The \"hotfix\" time is when\n> the end-user tends to be less careful, and it is a good thing to\n> make sure \"git worktree add ../hotfix\" will not clobber an unrelated\n> \"hotfix\" branch.\n> \n> Good.\n> \n> Which may be something we would want to have a test for, though.\n\nGood idea. How about the following as a squash-in?\n\n--- 8< ---\nFrom: Eric Sunshine <sunshine@sunshineco.com>\nSubject: [PATCH] fixup! worktree: add: auto-vivify new branch when <branch> is omitted\n\n---\n t/t2025-worktree-add.sh | 9 +++++++++\n 1 file changed, 9 insertions(+)\n\ndiff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\nindex 8fe242f..ead8aa2 100755\n--- a/t/t2025-worktree-add.sh\n+++ b/t/t2025-worktree-add.sh\n@@ -150,4 +150,13 @@ 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+'\n+\n test_done\n-- \n2.5.0.rc1.201.ga12d9f8\n"},{"id":"265649","messageId":"CAPig+cSBp-U_jC3fcPXkZQ6kEPh7TRs2bAwKYQGGTtoGR3UYeg@mail.gmail.com","threadId":"39787","inReplyTo":"xmqqh9physyu.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 18/23] checkout: retire --to option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-07T07:08:36Z","receivedAt":"2015-07-07T07:08:36Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Jul 6, 2015 at 3:41 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Eric Sunshine <sunshine@sunshineco.com> writes:\n>> Now that \"git worktree add\" has achieved user-facing feature-parity with\n>> \"git checkout --to\", retire the latter.\n>> [...]\n>> This effectively reverts changes to checkout.c by 529fef2 (checkout:\n>> support checking out into a new working directory, 2014-11-30) with the\n>> exception of merge_working_tree() and switch_branches() which still\n>> require specialized knowledge that a the checkout is occurring in a\n>> newly-created linked worktree (signaled to them by the private\n>> GIT_CHECKOUT_NEW_WORKTREE environment variable).\n>\n> I do not quite understand why we still need the hidden environment\n> variable.  Is this a sign that the implementation is shared too much\n> between unrelated codepaths (or to put it another way, perhaps API\n> functions that are not best fit are being used)?\n\nDuy had responded[1][2] to my inquiry about these two remaining bits\nof checkout.c code with intimate knowledge of the initial\nlinked-worktree checkout (merge_working_tree & switch_branches), but I\ndon't know the checkout code well enough (yet) to fully understand his\nresponses or to answer your question satisfactorily. This is also why\nI was afraid to rip out those final two bits of code, even though in\nmy own testing, having ripped them out locally, I was unable to\ntrigger any sort of \"bad\" behavior, as far as I could tell. Thus, I\nwasn't sure if those two bits of code were needed, and was hoping\nsomeone more qualified (Duy, for instance) would be able to provide a\nmore authoritative answer.\n\nHaving now re-read and finally digested Duy's response about\nswitch_branches(), when I rip out the `new_worktree_mode` check\nlocally, I find that I can trigger the misleading warning about an\norphaned commit, so that bit of code still serves a practical purpose.\nThis doesn't justify that such ugly intimacy between git-worktree and\ngit-checkout is desirable; only that it still seems to be needed until\n\"git reset --hard\" can be swapped in to replace \"git checkout\".\n\n[1]: http://article.gmane.org/gmane.comp.version-control.git/273225\n[2]: http://article.gmane.org/gmane.comp.version-control.git/273226\n\n> Stepping back a bit, with or without the new \"linked worktree\"\n> feature, when you came across a repository whose working tree does\n> not have any file (i.e. somebody ran \"git ls-files | xargs rm\"), you\n> do not know and care what is in .git/index right now, you do not\n> know and care what branch its .git/HEAD points at, but you *do* know\n> what branch you want to be on (or where you want its HEAD detached\n> at), what would be the command you would use?\n>\n> The state immediately after a new worktree is constructed by\n> populating /path/main/.git/worktrees/test-next/ and pointing it from\n> /path/other/test-next/.git but before the index or the files under\n> /path/other/test-next/ are populated is exactly that situation, no?\n> Wouldn't \"symbolic-ref HEAD the-branch-i-want\" (or \"update-ref HEAD\n> the-commit-i-want\" in the detached case) followed by \"reset --hard\"\n> the more natural thing to use, instead of merge-working-tree and\n> switch-branches that are implementation details of \"checkout\"?\n\nIt seems so to me. I didn't repeat it in the v3 cover letter, but the\nv2 cover letter said this (which still holds true for v3):\n\n    v2 does not attempt either of the suggestions by Junio[*3*] or\n    Duy[*4*] for eliminating git-checkout from the equation, which\n    would allow us to remove the final couple bits of code in\n    git-checkout which require intimate knowledge that the checkout\n    is occurring in a newly created linked worktree. This series is\n    already too long, and I didn't want it to grow further by\n    implementing either of those ideas. Instead, this series leaves\n    git-worktree at a state where one or the other of those\n    suggestions can be done as follow-on patches touching only the\n    underlying machinery, without affecting the user-facing\n    interface.\n\n    [*3*]: via private email which suggested using \"git-reset --hard\"\n           rather than \"git checkout\" to populate the new linked\n           worktree.\n    [*4*]: http://thread.gmane.org/gmane.comp.version-control.git/273032/focus=273226\n\nIn order to use \"git reset --hard\" in place of \"git checkout\",\ngit-worktree will need to handle -b/-B, --detach, --force (and\npossibly --track and --orphan) itself. I'm still in the process of\nfamiliarizing myself with the code needed to perform those actions, as\nwell as whatever else is needed to make \"git reset --hard\" a reality,\nso I am not yet in a position to say now much time or work will be\nrequired to swap out \"git checkout\" for \"git reset --hard\". As such, I\ndidn't want to hold up the series for an unknown amount of time while\nstudying the issue; and, as the series stands, the remaining ugly\nintimate knowledge between git-worktree and git-checkout is\nbehind-the-scenes and localized (not affecting the user experience).\n"},{"id":"265658","messageId":"CAPig+cSSooqUcR_gW6vQP5Ws5v9p47bt7JWX4HgAyD6mFZynDA@mail.gmail.com","threadId":"39787","inReplyTo":"xmqqlhetyszz.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 23/23] checkout: retire --ignore-other-worktrees in favor of --force","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-07T08:24:05Z","receivedAt":"2015-07-07T08:24:05Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Jul 6, 2015 at 3:40 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Eric Sunshine <sunshine@sunshineco.com> writes:\n>> As a safeguard, checking out a branch already checked out by a different\n>> worktree is disallowed. This behavior can be overridden with\n>> --ignore-other-worktrees, however, this option is neither obvious nor\n>> particularly discoverable. As a common safeguard override, --force is\n>> more likely to come to mind. Therefore, overload it to also suppress the\n>> check for a branch already checked out elsewhere.\n>\n> I hate to be asking this again but why is it a good idea to allow\n> 'ignore-other-worktrees' in the first place (let alone making it\n> more discoverable)?  You'll have multiple working trees, either\n> using the new \"git worktree\" or using the old contrib/workdir, for\n> one of the two reasons:\n>\n>  * You need a separate work area to build a new history.\n>\n>  * You need a separate work area to expand the contents of a\n>    specific commit.\n>\n> Here \"create binary by running make\" falls into the latter category;\n> as far as Git is concerned, you are only looking at, not extending\n> the history of any specific branch.\n>\n> If you are extending the history of some branch, then you would want\n> to be on that branch.  Why would you want to have another worktree\n> that will get into a confusing state once you create that commit on\n> the checked out branch in this newly created worktree?\n>\n> Wasn't the whole point of making the primary repository aware of the\n> secondary worktrees via the \"linked checkout\" mechanism because that\n> confusion was the biggest sore point of the old contrib/workdir\n> implementation?\n\nHaving never used contrib/get-new-workdir, and not being involved in\nthe choice, nor recall seeing justification for disallowing the a\nbranch to be checked out in multiple locations, I lack insight to\nanswer. I do recall Mark pointing out that this restriction posed a\nbarrier for his migration from git-new-workdir to \"git checkout\n--to\"[1], and Duy adding --ignore-other-worktrees in response. Mark\npresented a use-case here [2], but then the discussion petered out.\n\nI likewise probably lack understanding of the finer points to make a\ncogent argument for or against.\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/260387/focus=260411\n[2]: http://article.gmane.org/gmane.comp.version-control.git/260645\n"},{"id":"265662","messageId":"CAPig+cSz3xS-pdtsiw14A80m7UqdwfGLy6kRdguHSUyAjfnWSQ@mail.gmail.com","threadId":"39787","inReplyTo":"CAPig+cSSooqUcR_gW6vQP5Ws5v9p47bt7JWX4HgAyD6mFZynDA@mail.gmail.com","subject":"Re: [PATCH v3 23/23] checkout: retire --ignore-other-worktrees in favor of --force","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-07T09:41:43Z","receivedAt":"2015-07-07T09:41:43Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Jul 7, 2015 at 4:24 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Mon, Jul 6, 2015 at 3:40 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> If you are extending the history of some branch, then you would want\n>> to be on that branch.  Why would you want to have another worktree\n>> that will get into a confusing state once you create that commit on\n>> the checked out branch in this newly created worktree?\n>>\n>> Wasn't the whole point of making the primary repository aware of the\n>> secondary worktrees via the \"linked checkout\" mechanism because that\n>> confusion was the biggest sore point of the old contrib/workdir\n>> implementation?\n>\n> I [...] probably lack understanding of the finer points to make a\n> cogent argument for or against.\n\nIs receive.denyCurrentBranch worth mentioning as an argument? Although\npushing a branch into a non-bare repo where that branch is already\nchecked out is normally disallowed, receive.denyCurrentBranch\noverrides the safeguard. Presumably, the user has experience and\nknowledge to know that \"git reset --hard\" will be required to sync\nthings up.\n\nUsing --force or --ignore-other-worktrees (or whatever) to override\ngit-checkout's normal safeguard against checking out a branch into\nmore than one linked-worktree parallels receive.denyCurrentBranch,\ndoesn't it? There is a certain amount of precedent elsewhere in Git\nfor allowing a person to shoot himself in the foot.\n"},{"id":"265750","messageId":"xmqqmvz83q4s.fsf@gitster.dls.corp.google.com","threadId":"39787","inReplyTo":"20150707013301.GA26523@flurp.local","subject":"Re: [PATCH v3 22/23] worktree: add: auto-vivify new branch when <branch> is omitted","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-07-07T16:10:27Z","receivedAt":"2015-07-07T16:10:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n>> Which may be something we would want to have a test for, though.\n>\n> Good idea. How about the following as a squash-in?\n\nSounds sensible.\n\nAt this point we do not have \"worktree list\", but if we gained that,\nwe may want to add this as one more postcondition after the failed\n\"worktree add\":\n\n       git worktree list >actual &&\n       ! grep precious actual\n\nbut that should happen in the series that adds \"worktree list\" ;-)\n\n> --- 8< ---\n> From: Eric Sunshine <sunshine@sunshineco.com>\n> Subject: [PATCH] fixup! worktree: add: auto-vivify new branch when <branch> is omitted\n>\n> ---\n>  t/t2025-worktree-add.sh | 9 +++++++++\n>  1 file changed, 9 insertions(+)\n>\n> diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh\n> index 8fe242f..ead8aa2 100755\n> --- a/t/t2025-worktree-add.sh\n> +++ b/t/t2025-worktree-add.sh\n> @@ -150,4 +150,13 @@ 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> +'\n> +\n>  test_done\n"},{"id":"265752","messageId":"xmqqio9w3poi.fsf@gitster.dls.corp.google.com","threadId":"39787","inReplyTo":"CAPig+cSz3xS-pdtsiw14A80m7UqdwfGLy6kRdguHSUyAjfnWSQ@mail.gmail.com","subject":"Re: [PATCH v3 23/23] checkout: retire --ignore-other-worktrees in favor of --force","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-07-07T16:20:13Z","receivedAt":"2015-07-07T16:20:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> Is receive.denyCurrentBranch worth mentioning as an argument? Although\n> pushing a branch into a non-bare repo where that branch is already\n> checked out is normally disallowed, receive.denyCurrentBranch\n> overrides the safeguard. Presumably, the user has experience and\n> knowledge to know that \"git reset --hard\" will be required to sync\n> things up.\n\nOr the user knows that he does not have a shell access to the box in\nthe first place.  I do not see much relevance to this discussion.\n\nI would not mind \"git worktree add -f\" to disable the \"no multiple\ncheckouts of the same branch\" safety, but I do not think it is\nsensible to remove \"-i-o-w\" and conflate everything into \"--force\".\nThat would force people to disable other safety measures at the same\ntime (e.g. protect local changes from differences between the\ncurrent and next branches).\n"},{"id":"265784","messageId":"CAPig+cQ_YnVbeuYN5TGaG1AyUXzBhK31LLon2RtsEhnVifVDVg@mail.gmail.com","threadId":"39787","inReplyTo":"xmqqio9w3poi.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 23/23] checkout: retire --ignore-other-worktrees in favor of --force","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-07-07T23:10:51Z","receivedAt":"2015-07-07T23:10:51Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Jul 7, 2015 at 12:20 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Eric Sunshine <sunshine@sunshineco.com> writes:\n> I would not mind \"git worktree add -f\" to disable the \"no multiple\n> checkouts of the same branch\" safety, but I do not think it is\n> sensible to remove \"-i-o-w\" and conflate everything into \"--force\".\n> That would force people to disable other safety measures at the same\n> time (e.g. protect local changes from differences between the\n> current and next branches).\n\nI'm fine with dropping this patch.\n"},{"id":"265787","messageId":"559C724B.8090708@gmail.com","threadId":"39787","inReplyTo":"xmqqlhetyszz.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 23/23] checkout: retire --ignore-other-worktrees in favor of --force","fromName":"Mark Levedahl","fromEmail":"mlevedahl@gmail.com","sentAt":"2015-07-08T00:43:55Z","receivedAt":"2015-07-08T00:43:55Z","isPatch":true,"sender":{"key":"mdl123@verizon.net","avatar":"https://avatars.githubusercontent.com/u/5302462?v=4"},"body":"On 07/06/2015 03:40 PM, Junio C Hamano wrote:\n> If you are extending the history of some branch, then you would want \n> to be on that branch. Why would you want to have another worktree that \n> will get into a confusing state once you create that commit on the \n> checked out branch in this newly created worktree? Wasn't the whole \n> point of making the primary repository aware of the secondary \n> worktrees via the \"linked checkout\" mechanism because that confusion \n> was the biggest sore point of the old contrib/workdir implementation? \n\nThe only issue I have with git-new-workdir is that git-gc in one \nworktree is unaware of what is in use in another so can prune things \naway. The linked worktrees here nicely solve that problem.\n\nThe main use I have of maintaining multiple checkouts of one branch is \nfor testing / analysis (where said tests can take days to weeks to run). \nDisallowing use of git's normal mechanism of tracking what is checked \nout in each such tree forces use of another system to do so, just \nimposing different difficulties for this use case. I note that 1) code \nmust be ADDED to git to prevent such duplicate checkouts which otherwise \ncause no difficulty to git itself, and 2) adding those checks requires \nadditional work to avoid the fallout. I have yet to hear what the upside \nof such a restriction is, I only see downsides.\n\nMark\n"},{"id":"265859","messageId":"xmqqvbduy4bm.fsf@gitster.dls.corp.google.com","threadId":"39787","inReplyTo":"CAPig+cSBp-U_jC3fcPXkZQ6kEPh7TRs2bAwKYQGGTtoGR3UYeg@mail.gmail.com","subject":"Re: [PATCH v3 18/23] checkout: retire --to option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-07-08T16:58:05Z","receivedAt":"2015-07-08T16:58:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> ... as the series stands, the remaining ugly intimate knowledge\n> between git-worktree and git-checkout is behind-the-scenes and\n> localized (not affecting the user experience).\n\nHopefully.  Let's run with what we have right now.\n"}]}