{"thread":{"id":"60506","subject":"[PATCH] checkout: add config variable checkout.autoDetach","startedAt":"2023-11-11T22:43:32Z","lastAt":"2023-11-14T00:48:22Z","messageCount":5,"participants":["Andy Koppe","Junio C Hamano","Phillip Wood"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"484765","messageId":"20231111224253.1923-1-andy.koppe@gmail.com","threadId":"60506","inReplyTo":null,"subject":"[PATCH] checkout: add config variable checkout.autoDetach","fromName":"Andy Koppe","fromEmail":"andy.koppe@gmail.com","sentAt":"2023-11-11T22:42:46Z","receivedAt":"2023-11-11T22:43:32Z","isPatch":true,"sender":{"key":"andy.koppe@gmail.com","avatar":"https://avatars.githubusercontent.com/u/223411?v=4"},"body":"The git-checkout command without pathspecs automatically detaches HEAD\nwhen switching to something other than a branch, whereas git-switch\nrequires the --detach option to do so.\n\nAdd configuration variable checkout.autoDetach to choose the behavior\nfor both: true for automatic detaching, false for requiring --detach.\n\nAmend their documentation and tests accordingly.\n\nSigned-off-by: Andy Koppe <andy.koppe@gmail.com>\n---\nI like to use git-switch and git-restore instead of git-checkout, and\nalso recommend them when new users ask how to switch branches or undo\nlocal changes. But I do miss git-checkout's auto-detaching, as I like\nto avoid creating local versions of remote branches when I don't intend\nto make changes to them.\n\nHence this patch, which turned out to be very simple in terms of the\nactual source change, as the checkout_opts.implicit_detach field\nalready controls the necessary functionality. That was added in commit\n7968bef06b by Nguyễn Thái Ngọc Duy, with the following explanation:\n\n> \"git checkout <commit>\" will checkout the commit in question and\n> detach HEAD from the current branch. It is naturally a right thing to\n> do once you get git references. But detached HEAD is a scary concept\n> to new users because we show a lot of warnings and stuff, and it could\n> be hard to get out of (until you know better).\n>\n> To keep switch a bit more friendly to new users, we only allow\n> entering detached HEAD mode when --detach is given.\n\nI think that makes plenty of sense, and I don't think it conflicts with\nthe config setting proposed here, as new users are unlikely to mess with\nsuch settings. In fact, the point where \"you get git references\" would\nprobably be a good time to enable checkout.autoDetach.\n\nConversely, admins might want to set checkout.autoDetach to false in the\nsystem-wide config to prevent accidental decapitation by git-checkout\nand the resulting support requests.\n\n Documentation/config/checkout.txt |  8 ++++++++\n Documentation/git-checkout.txt    |  3 +++\n Documentation/git-switch.txt      |  3 +++\n builtin/checkout.c                |  4 ++++\n t/t2020-checkout-detach.sh        | 14 ++++++++++++++\n t/t2060-switch.sh                 |  7 +++++++\n 6 files changed, 39 insertions(+)\n\ndiff --git a/Documentation/config/checkout.txt b/Documentation/config/checkout.txt\nindex a323022993..6827ee74d5 100644\n--- a/Documentation/config/checkout.txt\n+++ b/Documentation/config/checkout.txt\n@@ -17,6 +17,14 @@ and by linkgit:git-worktree[1] when `git worktree add` refers to a\n remote branch. This setting might be used for other checkout-like\n commands or functionality in the future.\n \n+checkout.autoDetach::\n+\tIf set to true, `git checkout` and `git switch` automatically detach\n+\tHEAD when switching to something other than a branch. If set to false,\n+\tthey require the `--detach` option to detach HEAD.\n++\n+If this setting is not specified, `git checkout` defaults to automatic\n+detaching, whereas `git switch` defaults to requiring `--detach`.\n+\n checkout.guess::\n \tProvides the default value for the `--guess` or `--no-guess`\n \toption in `git checkout` and `git switch`. See\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 240c54639e..23f90c15ac 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -79,6 +79,9 @@ When the `<commit>` argument is a branch name, the `--detach` option can\n be used to detach `HEAD` at the tip of the branch (`git checkout\n <branch>` would check out that branch without detaching `HEAD`).\n +\n+If the `checkout.autoDetach` config variable is set to false, the `--detach`\n+option is required even if the `<commit>` argument is not a branch name.\n++\n Omitting `<branch>` detaches `HEAD` at the tip of the current branch.\n \n 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...::\ndiff --git a/Documentation/git-switch.txt b/Documentation/git-switch.txt\nindex c60fc9c138..f6b925c43b 100644\n--- a/Documentation/git-switch.txt\n+++ b/Documentation/git-switch.txt\n@@ -83,6 +83,9 @@ $ git switch <new-branch>\n \tSwitch to a commit for inspection and discardable\n \texperiments. See the \"DETACHED HEAD\" section in\n \tlinkgit:git-checkout[1] for details.\n++\n+If the `checkout.autoDetach` configuration variable is set to true,\n+`--detach` can be omitted when the target is not a branch.\n \n --guess::\n --no-guess::\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex f02434bc15..d042638bb0 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -1205,6 +1205,10 @@ static int git_checkout_config(const char *var, const char *value,\n \t\thandle_ignore_submodules_arg(&opts->diff_options, value);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"checkout.autodetach\")) {\n+\t\topts->implicit_detach = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n \tif (!strcmp(var, \"checkout.guess\")) {\n \t\topts->dwim_new_local_branch = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh\nindex 8202ef8c74..b842b6cc89 100755\n--- a/t/t2020-checkout-detach.sh\n+++ b/t/t2020-checkout-detach.sh\n@@ -69,12 +69,26 @@ test_expect_success 'checkout ref^0 detaches' '\n \tcheck_detached\n '\n \n+test_expect_success 'checkout of tag with autoDetach=false fails' '\n+\treset &&\n+\ttest_config checkout.autoDetach false &&\n+\ttest_must_fail git checkout tag &&\n+\tcheck_not_detached\n+'\n+\n test_expect_success 'checkout --detach detaches' '\n \treset &&\n \tgit checkout --detach branch &&\n \tcheck_detached\n '\n \n+test_expect_success 'checkout --detach with autoDetach=false detaches' '\n+\treset &&\n+\ttest_config checkout.autoDetach false &&\n+\tgit checkout --detach branch &&\n+\tcheck_detached\n+'\n+\n test_expect_success 'checkout --detach without branch name' '\n \treset &&\n \tgit checkout --detach &&\ndiff --git a/t/t2060-switch.sh b/t/t2060-switch.sh\nindex e247a4735b..69ff197d11 100755\n--- a/t/t2060-switch.sh\n+++ b/t/t2060-switch.sh\n@@ -50,6 +50,13 @@ test_expect_success 'switch and detach current branch' '\n \ttest_must_fail git symbolic-ref HEAD\n '\n \n+test_expect_success 'switch with checkout.autoDetach=true' '\n+\ttest_when_finished git switch main &&\n+\ttest_config checkout.autoDetach true &&\n+\tgit switch main^{commit} &&\n+\ttest_must_fail git symbolic-ref HEAD\n+'\n+\n test_expect_success 'switch and create branch' '\n \ttest_when_finished git switch main &&\n \tgit switch -c temp main^ &&\n-- \n2.43.0-rc1\n\n"},{"id":"484768","messageId":"xmqqbkbzo6ba.fsf@gitster.g","threadId":"60506","inReplyTo":"20231111224253.1923-1-andy.koppe@gmail.com","subject":"Re: [PATCH] checkout: add config variable checkout.autoDetach","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-11-12T06:04:57Z","receivedAt":"2023-11-12T06:05:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andy Koppe <andy.koppe@gmail.com> writes:\n\n> The git-checkout command without pathspecs automatically detaches HEAD\n> when switching to something other than a branch, whereas git-switch\n> requires the --detach option to do so.\n>\n> Add configuration variable checkout.autoDetach to choose the behavior\n> for both: true for automatic detaching, false for requiring --detach.\n>\n> Amend their documentation and tests accordingly.\n>\n> Signed-off-by: Andy Koppe <andy.koppe@gmail.com>\n> ---\n\n\"switch\" was meant to be an experimental command to sort out this\nkind of UI ideas, and I think the fact that it requires a more\nexplicit \"--detach\", where experienced users might just say \"git\ncheckout that-branch^0\", has established itself as a more friendly\nand good thing to help new users.  I do not know how others react to\nthis kind of proliferation of configuration variables, but I do not\nmind this particular variable existing.\n\n"},{"id":"484770","messageId":"859a0c38-b7cd-4d6b-a4c8-c530fbe6e928@gmail.com","threadId":"60506","inReplyTo":"xmqqbkbzo6ba.fsf@gitster.g","subject":"Re: [PATCH] checkout: add config variable checkout.autoDetach","fromName":"Andy Koppe","fromEmail":"andy.koppe@gmail.com","sentAt":"2023-11-12T09:15:27Z","receivedAt":"2023-11-12T09:15:34Z","isPatch":true,"sender":{"key":"andy.koppe@gmail.com","avatar":"https://avatars.githubusercontent.com/u/223411?v=4"},"body":"On 12/11/2023 06:04, Junio C Hamano wrote:\n> Andy Koppe <andy.koppe@gmail.com> writes:\n> \n>> The git-checkout command without pathspecs automatically detaches HEAD\n>> when switching to something other than a branch, whereas git-switch\n>> requires the --detach option to do so.\n>>\n>> Add configuration variable checkout.autoDetach to choose the behavior\n>> for both: true for automatic detaching, false for requiring --detach.\n>>\n>> Amend their documentation and tests accordingly.\n>>\n>> Signed-off-by: Andy Koppe <andy.koppe@gmail.com>\n>> ---\n> \n> \"switch\" was meant to be an experimental command to sort out this\n> kind of UI ideas, and I think the fact that it requires a more\n> explicit \"--detach\", where experienced users might just say \"git\n> checkout that-branch^0\", has established itself as a more friendly\n> and good thing to help new users. \n\nI agree, but as an experienced user, I nevertheless prefer switch and \nrestore over checkout, because those are rather different tasks, and \nwith checkout you're only ever a small thinko and errant dot away from \nlosing your local changes. If switch and restore had existed first, I \ndon't think anyone would be asking for mashing them together.\n\nIncidentally, as reset is similarly overloaded, and restore can also \nreplace the forms of reset that take pathspec arguments, was there a \nsimilar plan to factor the head-moving forms of reset out into a \nseparate command? (I realise there'd be little appetite for that after \nthe switch/restore experiment.)\n\n> I do not know how others react to\n> this kind of proliferation of configuration variables, but I do not\n> mind this particular variable existing.\n\nThanks. There's also the checkout.guess variable as a closely related \nprecedent.\n\nRegards,\nAndy\n"},{"id":"484801","messageId":"0e37ee23-922c-4bbf-82c3-8f44e9216ab0@gmail.com","threadId":"60506","inReplyTo":"xmqqbkbzo6ba.fsf@gitster.g","subject":"Re: [PATCH] checkout: add config variable checkout.autoDetach","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-11-13T15:07:15Z","receivedAt":"2023-11-13T15:07:23Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"\n\nOn 12/11/2023 06:04, Junio C Hamano wrote:\n> Andy Koppe <andy.koppe@gmail.com> writes:\n> \n>> The git-checkout command without pathspecs automatically detaches HEAD\n>> when switching to something other than a branch, whereas git-switch\n>> requires the --detach option to do so.\n>>\n>> Add configuration variable checkout.autoDetach to choose the behavior\n>> for both: true for automatic detaching, false for requiring --detach.\n>>\n>> Amend their documentation and tests accordingly.\n>>\n>> Signed-off-by: Andy Koppe <andy.koppe@gmail.com>\n>> ---\n> \n> \"switch\" was meant to be an experimental command to sort out this\n> kind of UI ideas, and I think the fact that it requires a more\n> explicit \"--detach\", where experienced users might just say \"git\n> checkout that-branch^0\", has established itself as a more friendly\n> and good thing to help new users.  I do not know how others react to\n> this kind of proliferation of configuration variables, but I do not\n> mind this particular variable existing.\n\nI'm a bit wary of having a config variable that could break scripts \nrelying on the current behavior of \"git checkout\". As far as \"git \nswitch\" goes I don't particularly mind this config variable though I'm \nnot sure it is that hard to type \"--detach\" (especially with tab \ncompletion) and I do worry that we're making the UI more complex each \ntime we add something like this.\n\nBest Wishes\n\nPhillip\n"},{"id":"484833","messageId":"xmqq7cml2m98.fsf@gitster.g","threadId":"60506","inReplyTo":"0e37ee23-922c-4bbf-82c3-8f44e9216ab0@gmail.com","subject":"Re: [PATCH] checkout: add config variable checkout.autoDetach","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-11-14T00:48:19Z","receivedAt":"2023-11-14T00:48:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>> and good thing to help new users.  I do not know how others react to\n>> this kind of proliferation of configuration variables, but I do not\n>> mind this particular variable existing.\n>\n> I'm a bit wary of having a config variable that could break\n> scripts relying on the current behavior of \"git checkout\".  As far\n> as \"git switch\" goes I don't particularly mind this config\n> variable though I'm not sure it is that hard to type \"--detach\"\n> (especially with tab completion) and\n\nI do not have much sympathy myself to scripts that are not being\ndefensive enough to write \"--detach\" explicitly, but I do understand\nand share your concern as the project maintainer.\n\n> ... I do worry that we're making the UI more complex each\n> time we add something like this.\n\nThanks for saying this---this is exactly the kind of reaction I as\nexpecting to see.\n\n>\n> Best Wishes\n>\n> Phillip\n"}]}