{"thread":{"id":"45134","subject":"[PATCH] completion: complete modified files for checkout with '--'","startedAt":"2017-02-13T23:35:12Z","lastAt":"2017-02-15T22:45:56Z","messageCount":12,"participants":["cornelius.weig@tngtech.com","SZEDER Gábor","Cornelius Weig","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"311472","messageId":"20170213233359.11149-1-cornelius.weig@tngtech.com","threadId":"45134","inReplyTo":null,"subject":"[PATCH] completion: complete modified files for checkout with '--'","fromName":"","fromEmail":"cornelius.weig@tngtech.com","sentAt":"2017-02-13T23:33:59Z","receivedAt":"2017-02-13T23:35:12Z","isPatch":true,"sender":{"key":"cornelius.weig@tngtech.com","avatar":null},"body":"From: Cornelius Weig <cornelius.weig@tngtech.com>\n\nThe command line completion for git-checkout bails out when seeing '--'\nas an isolated argument. For git-checkout this signifies the start of a\nlist of files which are to be checked out. Checkout of files makes only\nsense for modified files, therefore completion can be a bit smarter:\nInstead of bailing out, offer modified files for completion.\n\nSigned-off-by: Cornelius Weig <cornelius.weig@tngtech.com>\n---\n contrib/completion/git-completion.bash | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6c6e1c7..d6523fd 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1059,7 +1059,10 @@ _git_bundle ()\n \n _git_checkout ()\n {\n-\t__git_has_doubledash && return\n+\t__git_has_doubledash && {\n+\t\t__git_complete_index_file \"--modified\"\n+\t\treturn\n+\t}\n \n \tcase \"$cur\" in\n \t--conflict=*)\n-- \n2.10.2\n\n"},{"id":"311482","messageId":"CAM0VKj=d+hAiF6_8TLuJfccNiPtHyg9F6zESA8SuTEeaLsrw4Q@mail.gmail.com","threadId":"45134","inReplyTo":"20170213233359.11149-1-cornelius.weig@tngtech.com","subject":"Re: [PATCH] completion: complete modified files for checkout with '--'","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2017-02-14T00:50:36Z","receivedAt":"2017-02-14T00:50:44Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Tue, Feb 14, 2017 at 12:33 AM,  <cornelius.weig@tngtech.com> wrote:\n> From: Cornelius Weig <cornelius.weig@tngtech.com>\n>\n> The command line completion for git-checkout bails out when seeing '--'\n> as an isolated argument. For git-checkout this signifies the start of a\n> list of files which are to be checked out. Checkout of files makes only\n> sense for modified files,\n\nNo, there is e.g. 'git checkout that-branch this-path', too.\n\n\n> therefore completion can be a bit smarter:\n> Instead of bailing out, offer modified files for completion.\n>\n> Signed-off-by: Cornelius Weig <cornelius.weig@tngtech.com>\n> ---\n>  contrib/completion/git-completion.bash | 5 ++++-\n>  1 file changed, 4 insertions(+), 1 deletion(-)\n>\n> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\n> index 6c6e1c7..d6523fd 100644\n> --- a/contrib/completion/git-completion.bash\n> +++ b/contrib/completion/git-completion.bash\n> @@ -1059,7 +1059,10 @@ _git_bundle ()\n>\n>  _git_checkout ()\n>  {\n> -       __git_has_doubledash && return\n> +       __git_has_doubledash && {\n> +               __git_complete_index_file \"--modified\"\n> +               return\n> +       }\n>\n>         case \"$cur\" in\n>         --conflict=*)\n> --\n> 2.10.2\n>\n"},{"id":"311580","messageId":"4f8a0aaa-4ce1-d4a6-d2e1-28aac7209c90@tngtech.com","threadId":"45134","inReplyTo":"CAM0VKj=d+hAiF6_8TLuJfccNiPtHyg9F6zESA8SuTEeaLsrw4Q@mail.gmail.com","subject":"Re: [PATCH] completion: complete modified files for checkout with '--'","fromName":"Cornelius Weig","fromEmail":"cornelius.weig@tngtech.com","sentAt":"2017-02-14T21:13:35Z","receivedAt":"2017-02-14T21:13:43Z","isPatch":true,"sender":{"key":"cornelius.weig@tngtech.com","avatar":null},"body":"On 02/14/2017 01:50 AM, SZEDER Gábor wrote:\n> On Tue, Feb 14, 2017 at 12:33 AM,  <cornelius.weig@tngtech.com> wrote:\n>> From: Cornelius Weig <cornelius.weig@tngtech.com>\n>>\n>> The command line completion for git-checkout bails out when seeing '--'\n>> as an isolated argument. For git-checkout this signifies the start of a\n>> list of files which are to be checked out. Checkout of files makes only\n>> sense for modified files,\n> \n> No, there is e.g. 'git checkout that-branch this-path', too.\n\nVery true. Thanks for prodding me to this palpable oversight.\n\nMy error was to aim for a small improvement. I think the correct\napproach is to improve the overall completion of git-checkout. IMHO it\nis a completion bug that after giving a ref, completion will still offer\nrefs, e.g.\n$ git checkout HEAD <TAB><TAB> --> list of refs\n\nAs far as I can see, giving two refs to checkout is always an error. The\ncorrect behavior in the example above would be to offer paths instead.\n\nI'll follow up with an improved version which considers these cases.\n\n"},{"id":"311581","messageId":"20170214212404.31469-2-cornelius.weig@tngtech.com","threadId":"45134","inReplyTo":"20170214212404.31469-1-cornelius.weig@tngtech.com","subject":"[PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"","fromEmail":"cornelius.weig@tngtech.com","sentAt":"2017-02-14T21:24:04Z","receivedAt":"2017-02-14T21:24:59Z","isPatch":true,"sender":{"key":"cornelius.weig@tngtech.com","avatar":null},"body":"From: Cornelius Weig <cornelius.weig@tngtech.com>\n\nGit-checkout completes words starting with '--' as options and other\nwords as refs. Even after specifying a ref, further words not starting\nwith '--' are completed as refs, which is invalid for git-checkout.\n\nThis commit ensures that after specifying a ref, further non-option\nwords are completed as paths. Four cases are considered:\n\n - If the word contains a ':', do not treat it as reference and use\n   regular revlist completion.\n - If no ref is found on the command line, complete non-options as refs\n   as before.\n - If the ref is HEAD or @, complete only with modified files because\n   checking out unmodified files is a noop.\n   This case also applies if no ref is given, but '--' is present.\n - If a ref other than HEAD or @ is found, offer only valid paths from\n   that revision.\n\nNote that one corner-case is not covered by the current implementation:\nif a refname contains a ':' and is followed by '--' the completion would\nnot recognize the valid refname.\n\nSigned-off-by: Cornelius Weig <cornelius.weig@tngtech.com>\n---\n contrib/completion/git-completion.bash | 39 +++++++++++++++++++++++++++-------\n 1 file changed, 31 insertions(+), 8 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 4ab119d..df46f62 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1068,7 +1068,7 @@ _git_bundle ()\n \n _git_checkout ()\n {\n-\t__git_has_doubledash && return\n+\tlocal i c=2 ref=\"\" seen_double_dash=\"\"\n \n \tcase \"$cur\" in\n \t--conflict=*)\n@@ -1081,13 +1081,36 @@ _git_checkout ()\n \t\t\t\"\n \t\t;;\n \t*)\n-\t\t# check if --track, --no-track, or --no-guess was specified\n-\t\t# if so, disable DWIM mode\n-\t\tlocal flags=\"--track --no-track --no-guess\" track=1\n-\t\tif [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n-\t\t\ttrack=''\n-\t\tfi\n-\t\t__gitcomp_nl \"$(__git_refs '' $track)\"\n+\t\twhile [ $c -lt $cword ]; do\n+\t\t\ti=\"${words[c]}\"\n+\t\t\tcase \"$i\" in\n+\t\t\t--) seen_double_dash=1 ;;\n+\t\t\t-*|?*:*) ;;\n+\t\t\t*) ref=\"$i\"; break ;;\n+\t\t\tesac\n+\t\t\t((c++))\n+\t\tdone\n+\n+\t\tcase \"$ref,$seen_double_dash,$cur\" in\n+\t\t,,*:*)\n+\t\t    __git_complete_revlist_file\n+\t\t    ;;\n+\t\t,,*)\n+\t\t\t# check for --track, --no-track, or --no-guess\n+\t\t\t# if so, disable DWIM mode\n+\t\t\tlocal flags=\"--track --no-track --no-guess\" track=1\n+\t\t\tif [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n+\t\t\t\ttrack=''\n+\t\t\tfi\n+\t\t\t__gitcomp_nl \"$(__git_refs '' $track)\"\n+\t\t\t;;\n+\t\t,1,*|@,*|HEAD,*)\n+\t\t\t__git_complete_index_file \"--modified\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\t__git_complete_tree_file \"$ref\" \"$cur\"\n+\t\t\t;;\n+\t\tesac\n \t\t;;\n \tesac\n }\n-- \n2.10.2\n\n"},{"id":"311582","messageId":"20170214212404.31469-1-cornelius.weig@tngtech.com","threadId":"45134","inReplyTo":"4f8a0aaa-4ce1-d4a6-d2e1-28aac7209c90@tngtech.com","subject":"[PATCH v2 1/2] completion: extract utility to complete paths from tree-ish","fromName":"","fromEmail":"cornelius.weig@tngtech.com","sentAt":"2017-02-14T21:24:03Z","receivedAt":"2017-02-14T21:25:02Z","isPatch":true,"sender":{"key":"cornelius.weig@tngtech.com","avatar":null},"body":"From: Cornelius Weig <cornelius.weig@tngtech.com>\n\nThe function __git_complete_revlist_file understands how to complete a\npath such as 'topic:ref<TAB>'. In that case, the revision (topic) and\nthe path component (ref) are both part of the same word. However,\nsome cases require that the revision is specified elsewhere than the\ncurrent word for completion, such as 'git checkout topic ref<TAB>'.\n\nIn order to allow callers to specify the revision, extract a utility\nfunction to complete paths from a tree-ish object. The utility will be\nused later to implement path completion for git-checkout.\n\nSigned-off-by: Cornelius Weig <cornelius.weig@tngtech.com>\n---\n contrib/completion/git-completion.bash | 73 +++++++++++++++++++---------------\n 1 file changed, 41 insertions(+), 32 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6c6e1c7..4ab119d 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -442,6 +442,46 @@ __git_compute_merge_strategies ()\n \t__git_merge_strategies=$(__git_list_merge_strategies)\n }\n \n+# __git_complete_tree_file requires 2 argument:\n+# 1: the the tree-like to look at for completion\n+# 2: the path component to complete\n+__git_complete_tree_file ()\n+{\n+\tlocal pfx ls ref=\"$1\" cur_=\"$2\"\n+\tcase \"$cur_\" in\n+\t?*/*)\n+\t\tpfx=\"${cur_%/*}\"\n+\t\tcur_=\"${cur_##*/}\"\n+\t\tls=\"$ref:$pfx\"\n+\t\tpfx=\"$pfx/\"\n+\t\t;;\n+\t*)\n+\t\tls=\"$ref\"\n+\t\t;;\n+\tesac\n+\n+\tcase \"$COMP_WORDBREAKS\" in\n+\t*:*) : great ;;\n+\t*)   pfx=\"$ref:$pfx\" ;;\n+\tesac\n+\n+\t__gitcomp_nl \"$(git --git-dir=\"$(__gitdir)\" ls-tree \"$ls\" 2>/dev/null \\\n+\t\t\t\t| sed '/^100... blob /{\n+\t\t\t\t\t\t   s,^.*\t,,\n+\t\t\t\t\t\t   s,$, ,\n+\t\t\t\t\t   }\n+\t\t\t\t\t   /^120000 blob /{\n+\t\t\t\t\t\t   s,^.*\t,,\n+\t\t\t\t\t\t   s,$, ,\n+\t\t\t\t\t   }\n+\t\t\t\t\t   /^040000 tree /{\n+\t\t\t\t\t\t   s,^.*\t,,\n+\t\t\t\t\t\t   s,$,/,\n+\t\t\t\t\t   }\n+\t\t\t\t\t   s/^.*\t//')\" \\\n+\t\t\t\t\"$pfx\" \"$cur_\" \"\"\n+}\n+\n __git_complete_revlist_file ()\n {\n \tlocal pfx ls ref cur_=\"$cur\"\n@@ -452,38 +492,7 @@ __git_complete_revlist_file ()\n \t?*:*)\n \t\tref=\"${cur_%%:*}\"\n \t\tcur_=\"${cur_#*:}\"\n-\t\tcase \"$cur_\" in\n-\t\t?*/*)\n-\t\t\tpfx=\"${cur_%/*}\"\n-\t\t\tcur_=\"${cur_##*/}\"\n-\t\t\tls=\"$ref:$pfx\"\n-\t\t\tpfx=\"$pfx/\"\n-\t\t\t;;\n-\t\t*)\n-\t\t\tls=\"$ref\"\n-\t\t\t;;\n-\t\tesac\n-\n-\t\tcase \"$COMP_WORDBREAKS\" in\n-\t\t*:*) : great ;;\n-\t\t*)   pfx=\"$ref:$pfx\" ;;\n-\t\tesac\n-\n-\t\t__gitcomp_nl \"$(git --git-dir=\"$(__gitdir)\" ls-tree \"$ls\" 2>/dev/null \\\n-\t\t\t\t| sed '/^100... blob /{\n-\t\t\t\t           s,^.*\t,,\n-\t\t\t\t           s,$, ,\n-\t\t\t\t       }\n-\t\t\t\t       /^120000 blob /{\n-\t\t\t\t           s,^.*\t,,\n-\t\t\t\t           s,$, ,\n-\t\t\t\t       }\n-\t\t\t\t       /^040000 tree /{\n-\t\t\t\t           s,^.*\t,,\n-\t\t\t\t           s,$,/,\n-\t\t\t\t       }\n-\t\t\t\t       s/^.*\t//')\" \\\n-\t\t\t\"$pfx\" \"$cur_\" \"\"\n+\t\t__git_complete_tree_file \"$ref\" \"$cur_\"\n \t\t;;\n \t*...*)\n \t\tpfx=\"${cur_%...*}...\"\n-- \n2.10.2\n\n"},{"id":"311585","messageId":"xmqq8tp88nnj.fsf@gitster.mtv.corp.google.com","threadId":"45134","inReplyTo":"20170214212404.31469-2-cornelius.weig@tngtech.com","subject":"Re: [PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-02-14T21:31:44Z","receivedAt":"2017-02-14T21:31:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"cornelius.weig@tngtech.com writes:\n\n> From: Cornelius Weig <cornelius.weig@tngtech.com>\n>\n> Git-checkout completes words starting with '--' as options and other\n> words as refs. Even after specifying a ref, further words not starting\n> with '--' are completed as refs, which is invalid for git-checkout.\n>\n> This commit ensures that after specifying a ref, further non-option\n> words are completed as paths. Four cases are considered:\n>\n>  - If the word contains a ':', do not treat it as reference and use\n>    regular revlist completion.\n>  - If no ref is found on the command line, complete non-options as refs\n>    as before.\n>  - If the ref is HEAD or @, complete only with modified files because\n>    checking out unmodified files is a noop.\n>    This case also applies if no ref is given, but '--' is present.\n\nPlease at least do not do this one; a completion that is or pretends\nto be more clever than the end users will confuse them at best and\nannoy them.  Maybe the user does not recall if she touched the path\nor not, and just trying to be extra sure that it matches HEAD or\nindex by doing \"git checkout [HEAD] path<TAB>\".  Leave the \"make it\na noop\" to Git, but just allow her do so.\n\nI personally feel that \"git checkout <anything>... foo<TAB>\" should\njust fall back to the normal \"path on the filesystem\" without any\ncleverness, instead of opening a tree object or peek into the index.\n\n"},{"id":"311596","messageId":"9be8b988-f5b3-7365-ae7f-b46888253f4c@tngtech.com","threadId":"45134","inReplyTo":"xmqq8tp88nnj.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"Cornelius Weig","fromEmail":"cornelius.weig@tngtech.com","sentAt":"2017-02-14T22:13:11Z","receivedAt":"2017-02-14T22:13:21Z","isPatch":true,"sender":{"key":"cornelius.weig@tngtech.com","avatar":null},"body":"\n\nOn 02/14/2017 10:31 PM, Junio C Hamano wrote:\n> cornelius.weig@tngtech.com writes:\n> \n>> From: Cornelius Weig <cornelius.weig@tngtech.com>\n>>\n>> Git-checkout completes words starting with '--' as options and other\n>> words as refs. Even after specifying a ref, further words not starting\n>> with '--' are completed as refs, which is invalid for git-checkout.\n>>\n>> This commit ensures that after specifying a ref, further non-option\n>> words are completed as paths. Four cases are considered:\n>>\n>>  - If the word contains a ':', do not treat it as reference and use\n>>    regular revlist completion.\n>>  - If no ref is found on the command line, complete non-options as refs\n>>    as before.\n>>  - If the ref is HEAD or @, complete only with modified files because\n>>    checking out unmodified files is a noop.\n>>    This case also applies if no ref is given, but '--' is present.\n> \n> Please at least do not do this one; a completion that is or pretends\n> to be more clever than the end users will confuse them at best and\n> annoy them.  Maybe the user does not recall if she touched the path\n> or not, and just trying to be extra sure that it matches HEAD or\n> index by doing \"git checkout [HEAD] path<TAB>\".  Leave the \"make it\n> a noop\" to Git, but just allow her do so.\n\nHmm.. I'm a bit reluctant to let go of this just yet, because it was my\noriginal motivation for the whole patch. I admit that it may be\nconfusing to not get completion in your example. However, I think that\nonce acquainted with the new behavior, a user who wants some files\ncleaned would start by having a look at the list of files from \"git\ncheckout HEAD <TAB><TAB>\". That's probably faster than spelling the\nfirst few characters and hit <TAB> for a file that's already clean.\nLet's hear if anybody else has an opinion about this.\n\n> I personally feel that \"git checkout <anything>... foo<TAB>\" should\n> just fall back to the normal \"path on the filesystem\" without any\n> cleverness, instead of opening a tree object or peek into the index.\n\nI was thinking about that as well, but it's not what happens for \"git\ncheckout topic:path<TAB>\". And given that \"git checkout topic path<TAB>\"\nrefers to the same object, consistency kind of demands that the tree\nobjects are opened in the latter case as well. However, because the\ndifferences to filesystem path completion are somewhat corner cases, I'm\nfine with that as long as I'm not offered ref names any longer...\n\n"},{"id":"311600","messageId":"xmqqefz075or.fsf@gitster.mtv.corp.google.com","threadId":"45134","inReplyTo":"9be8b988-f5b3-7365-ae7f-b46888253f4c@tngtech.com","subject":"Re: [PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-02-14T22:45:08Z","receivedAt":"2017-02-14T22:45:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Cornelius Weig <cornelius.weig@tngtech.com> writes:\n\n> Hmm.. I'm a bit reluctant to let go of this just yet, because it was my\n> original motivation for the whole patch. I admit that it may be\n> confusing to not get completion in your example. However, I think that\n> once acquainted with the new behavior, a user who wants some files\n> cleaned would start by having a look at the list of files from \"git\n> checkout HEAD <TAB><TAB>\". That's probably faster than spelling the\n> first few characters and hit <TAB> for a file that's already clean.\n\nI understand that \"git checkout HEAD frotz<TAB>\" that gives 47 other\npaths that all begin with \"foo\", when \"frotz27\" is the only one\namong them that you know you changed, is not very useful to narrow\nthings down.  \n\nBut it is equally irritating when you know \"frotz27\" is the only\npath that begins with \"frotz\" (after all, that is why you decided to\nstop typing after saying \"frotz\" and letting the comletion kick in)\nbut you are not certain if you touched it.  The completion being\nsilent may be an indication that it is not modified, OR it may be an\nindication that you mistyped the leading part \"frotz\", and leaves\nyou wondering.\n"},{"id":"311637","messageId":"CAM0VKjkqdto83Qo8PVbxt-2r8prQguNbAtNELxj5AmJEgugC_Q@mail.gmail.com","threadId":"45134","inReplyTo":"20170214212404.31469-2-cornelius.weig@tngtech.com","subject":"Re: [PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2017-02-15T03:11:25Z","receivedAt":"2017-02-15T03:11:33Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Tue, Feb 14, 2017 at 10:24 PM,  <cornelius.weig@tngtech.com> wrote:\n> From: Cornelius Weig <cornelius.weig@tngtech.com>\n>\n> Git-checkout completes words starting with '--' as options and other\n> words as refs. Even after specifying a ref, further words not starting\n> with '--' are completed as refs, which is invalid for git-checkout.\n\nRefs completion is never attempted for words after the disambiguating\ndouble-dash.\n\nEven when refs completion is attempted, if it is unsuccessful, i.e.\nthere is no ref that matches the current word to be completed, then\nBash falls back to standard filename completion.  No refs match\n'./<TAB>'.\n\nFurthermore, Bash performs filename completion on Alt-/ independently\nfrom any completion function.\n\nGranted, none of these will limit to only modified files...  But that\nmight be a good thing, see below.\n\n> This commit ensures that after specifying a ref, further non-option\n> words are completed as paths. Four cases are considered:\n>\n>  - If the word contains a ':', do not treat it as reference and use\n>    regular revlist completion.\n>  - If no ref is found on the command line, complete non-options as refs\n>    as before.\n>  - If the ref is HEAD or @, complete only with modified files because\n>    checking out unmodified files is a noop.\n\nHere you use \"modified\" in the 'ls-files --modified' sense, but that\ndoesn't include modifications already staged in the index, see below.\n\n>    This case also applies if no ref is given, but '--' is present.\n>  - If a ref other than HEAD or @ is found, offer only valid paths from\n>    that revision.\n>\n> Note that one corner-case is not covered by the current implementation:\n> if a refname contains a ':' and is followed by '--' the completion would\n> not recognize the valid refname.\n\nI'm not sure what you mean here.  Refnames can't contain ':'.\n\n> Signed-off-by: Cornelius Weig <cornelius.weig@tngtech.com>\n> ---\n>  contrib/completion/git-completion.bash | 39 +++++++++++++++++++++++++++-------\n>  1 file changed, 31 insertions(+), 8 deletions(-)\n>\n> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\n> index 4ab119d..df46f62 100644\n> --- a/contrib/completion/git-completion.bash\n> +++ b/contrib/completion/git-completion.bash\n> @@ -1068,7 +1068,7 @@ _git_bundle ()\n>\n>  _git_checkout ()\n>  {\n> -       __git_has_doubledash && return\n> +       local i c=2 ref=\"\" seen_double_dash=\"\"\n>\n>         case \"$cur\" in\n>         --conflict=*)\n> @@ -1081,13 +1081,36 @@ _git_checkout ()\n>                         \"\n>                 ;;\n>         *)\n> -               # check if --track, --no-track, or --no-guess was specified\n> -               # if so, disable DWIM mode\n> -               local flags=\"--track --no-track --no-guess\" track=1\n> -               if [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n> -                       track=''\n> -               fi\n> -               __gitcomp_nl \"$(__git_refs '' $track)\"\n> +               while [ $c -lt $cword ]; do\n> +                       i=\"${words[c]}\"\n> +                       case \"$i\" in\n> +                       --) seen_double_dash=1 ;;\n> +                       -*|?*:*) ;;\n> +                       *) ref=\"$i\"; break ;;\n\nI haven't tried it, but this would trigger on e.g. 'git checkout -b\nnew-feature <TAB>', wouldn't it?\n\n> +                       esac\n> +                       ((c++))\n> +               done\n> +\n> +               case \"$ref,$seen_double_dash,$cur\" in\n> +               ,,*:*)\n> +                   __git_complete_revlist_file\n> +                   ;;\n> +               ,,*)\n> +                       # check for --track, --no-track, or --no-guess\n> +                       # if so, disable DWIM mode\n> +                       local flags=\"--track --no-track --no-guess\" track=1\n> +                       if [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n> +                               track=''\n> +                       fi\n> +                       __gitcomp_nl \"$(__git_refs '' $track)\"\n> +                       ;;\n> +               ,1,*|@,*|HEAD,*)\n> +                       __git_complete_index_file \"--modified\"\n\nWhat about\n\n  $ echo \"unintentional change\" >>tracked-file && git add -u\n  $ git rm important-file\n  $ git checkout HEAD <TAB>\n\n?  It seems it will offer neither 'tracked-file' nor 'important-file',\nbut I think it should offer both.\n\n\nWe have __git_complete_index_file() for a while now, but only use it\nfor commands that accept only --options and filenames, e.g. 'add',\n'clean', 'rm'.  This would be the first case when we would use it for\na command that accept both refs and filenames.  Perhaps similar corner\ncases and the easy ways to trigger filename completion are why no one\nthought it's worth it.\n\n> +                       ;;\n> +               *)\n> +                       __git_complete_tree_file \"$ref\" \"$cur\"\n\nWell, here you could go all-in, and say that this should complete only\nfiles that are different from the version in $ref, because checking\nout files that are still the same is a noop :)\n\n> +                       ;;\n> +               esac\n>                 ;;\n>         esac\n>  }\n> --\n> 2.10.2\n>\n"},{"id":"311639","messageId":"1cff1dea-baeb-3576-ad33-04b2c5d233d8@tngtech.com","threadId":"45134","inReplyTo":"CAM0VKjkqdto83Qo8PVbxt-2r8prQguNbAtNELxj5AmJEgugC_Q@mail.gmail.com","subject":"Re: [PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"Cornelius Weig","fromEmail":"cornelius.weig@tngtech.com","sentAt":"2017-02-15T10:46:48Z","receivedAt":"2017-02-15T10:47:00Z","isPatch":true,"sender":{"key":"cornelius.weig@tngtech.com","avatar":null},"body":"Although I'm not convinced that completion of modified files is unnecessary, I'm at least persuaded that not all users would welcome such a change. Given the hint from Gabor that Alt-/ forces filesystem completion, there is even no big win in stopping to offer further refnames after one has already been given.\n\nIf you think that this would be desirable, find a revised version below. Otherwise drop it.\n\n\nOn 02/15/2017 04:11 AM, SZEDER Gábor wrote:\n> On Tue, Feb 14, 2017 at 10:24 PM,  <cornelius.weig@tngtech.com> wrote:\n>> From: Cornelius Weig <cornelius.weig@tngtech.com>\n>> Note that one corner-case is not covered by the current implementation:\n>> if a refname contains a ':' and is followed by '--' the completion would\n>> not recognize the valid refname.\n> \n> I'm not sure what you mean here.  Refnames can't contain ':'.\n\nYes, my bad. I was confusing it with the case where filename and ref name are identical.\n\n>> +               while [ $c -lt $cword ]; do\n>> +                       i=\"${words[c]}\"\n>> +                       case \"$i\" in\n>> +                       --) seen_double_dash=1 ;;\n>> +                       -*|?*:*) ;;\n>> +                       *) ref=\"$i\"; break ;;\n> \n> I haven't tried it, but this would trigger on e.g. 'git checkout -b\n> new-feature <TAB>', wouldn't it?\n\nCorrect, good eyes.\n\n> What about\n> \n>   $ echo \"unintentional change\" >>tracked-file && git add -u\n>   $ git rm important-file\n>   $ git checkout HEAD <TAB>\n> \n> ?  It seems it will offer neither 'tracked-file' nor 'important-file',\n> but I think it should offer both.\n\nIdeally yes. The latter of the two would also not work with Alt/.\n\n\n-------------------------------------------------------------------\nFrom d0e0c9af8a30dec479c393ae7fe75205c9b3b229 Mon Sep 17 00:00:00 2001\nFrom: Cornelius Weig <cornelius.weig@tngtech.com>\nDate: Tue, 14 Feb 2017 21:01:45 +0100\nSubject: [PATCH] completion: checkout: complete paths when ref given\n\nGit-checkout completes words starting with '--' as options and other\nwords as refs. Even after specifying a ref, further words not starting\nwith '--' are completed as refs, which is invalid for git-checkout.\n\nWith this commit completion suppresses refname suggestion after finding\nwhat looks like a refname. Words before a '--' not starting with a '-'\nand containing no ':' are considered to be refnames.\n\nSigned-off-by: Cornelius Weig <cornelius.weig@tngtech.com>\n---\n contrib/completion/git-completion.bash | 26 +++++++++++++++++++-------\n 1 file changed, 19 insertions(+), 7 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6c6e1c774d..42e6463b67 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1059,7 +1059,16 @@ _git_bundle ()\n \n _git_checkout ()\n {\n-\t__git_has_doubledash && return\n+\tlocal c=2 seen_ref=\"\"\n+\twhile [ $c -lt $cword ]; do\n+\t\tcase \"${words[c]}\" in\n+\t\t--) return ;;\n+\t\t-b|-B|--orphan|--branch) ((c++)) ;;\n+\t\t-*|*:*) ;;\n+\t\t*) seen_ref=\"y\" ;;\n+\t\tesac\n+\t\t((c++))\n+\tdone\n \n \tcase \"$cur\" in\n \t--conflict=*)\n@@ -1072,13 +1081,16 @@ _git_checkout ()\n \t\t\t\"\n \t\t;;\n \t*)\n-\t\t# check if --track, --no-track, or --no-guess was specified\n-\t\t# if so, disable DWIM mode\n-\t\tlocal flags=\"--track --no-track --no-guess\" track=1\n-\t\tif [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n-\t\t\ttrack=''\n+\t\tif [ -z \"$seen_ref\" ]\n+\t\tthen\n+\t\t\t# check for --track, --no-track, or --no-guess\n+\t\t\t# if so, disable DWIM mode\n+\t\t\tlocal flags=\"--track --no-track --no-guess\" track=1\n+\t\t\tif [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n+\t\t\t\ttrack=''\n+\t\t\tfi\n+\t\t\t__gitcomp_nl \"$(__git_refs '' $track)\"\n \t\tfi\n-\t\t__gitcomp_nl \"$(__git_refs '' $track)\"\n \t\t;;\n \tesac\n }\n-- \n2.11.1\n\n"},{"id":"311650","messageId":"CAM0VKjkUu2k73+PxZ2UNKrnBg0nW_za+10O7eHEgcko6BaGx6Q@mail.gmail.com","threadId":"45134","inReplyTo":"20170214212404.31469-2-cornelius.weig@tngtech.com","subject":"Re: [PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2017-02-15T14:26:44Z","receivedAt":"2017-02-15T14:26:50Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Tue, Feb 14, 2017 at 10:24 PM,  <cornelius.weig@tngtech.com> wrote:\n\n> +               *)\n> +                       __git_complete_tree_file \"$ref\" \"$cur\"\n> +                       ;;\n\nThere is one more caveat here.\n\nBoth our __git_complete_index_file() and Bash's builtin filename\ncompletion lists matching paths like this:\n\n  $ git rm contrib/co<TAB>\n  coccinelle/                        contacts/\n  completion/                        convert-grafts-to-replace-refs.sh\n\ni.e. the leading path components are not redundantly repeated.\n\nNow, with this patch in this code path the list would look like this:\n\n  $ git checkout completion-refs-speedup contrib/co<TAB>\n  contrib/coccinelle/\n  contrib/completion/\n  contrib/contacts/\n  contrib/convert-grafts-to-replace-refs.sh\n\nSee the difference?\n\nI once made a feeble attempt to make completion of the <ref>:<path>\nnotation (i.e. what you extracted into __git_complete_tree_file())\nlook like regular filename completion, but couldn't.\n\nGábor\n"},{"id":"311692","messageId":"11424310-7f76-12fe-0e56-e585ccf06aea@tngtech.com","threadId":"45134","inReplyTo":"CAM0VKjkUu2k73+PxZ2UNKrnBg0nW_za+10O7eHEgcko6BaGx6Q@mail.gmail.com","subject":"Re: [PATCH v2 2/2] completion: checkout: complete paths when ref given","fromName":"Cornelius Weig","fromEmail":"cornelius.weig@tngtech.com","sentAt":"2017-02-15T22:45:47Z","receivedAt":"2017-02-15T22:45:56Z","isPatch":true,"sender":{"key":"cornelius.weig@tngtech.com","avatar":null},"body":"On 02/15/2017 03:26 PM, SZEDER Gábor wrote:\n> On Tue, Feb 14, 2017 at 10:24 PM,  <cornelius.weig@tngtech.com> wrote:\n> \n>> +               *)\n>> +                       __git_complete_tree_file \"$ref\" \"$cur\"\n>> +                       ;;\n> \n> There is one more caveat here.\n> \n> Both our __git_complete_index_file() and Bash's builtin filename\n> completion lists matching paths like this:\n> \n>   $ git rm contrib/co<TAB>\n>   coccinelle/                        contacts/\n>   completion/                        convert-grafts-to-replace-refs.sh\n> \n> i.e. the leading path components are not redundantly repeated.\n> \n> Now, with this patch in this code path the list would look like this:\n> \n>   $ git checkout completion-refs-speedup contrib/co<TAB>\n>   contrib/coccinelle/\n>   contrib/completion/\n>   contrib/contacts/\n>   contrib/convert-grafts-to-replace-refs.sh\n> \n> See the difference?\n\nNow that you say it.. I had never noticed it though.\n\n> I once made a feeble attempt to make completion of the <ref>:<path>\n> notation (i.e. what you extracted into __git_complete_tree_file())\n> look like regular filename completion, but couldn't.\n\nCan you dig up what you tried out? Maybe somebody comes up with a good idea.\n"}]}