Git: Tab completion after colon does not work in push command

Created on 30 May 2015  路  23Comments  路  Source: git-for-windows/git

Here is a strange behavior. Tab completion works literally everywhere else except for in the following command:

$ git push origin :my-branch

Note that if I stop after typing :my and I hit TAB, the branch name is not completed. I have verified that I only have 1 branch that starts with this prefix.

The strange issue is that when I am using git through the Git SDK installer (to contribute to Git source code), inside /usr/src/git, if I do the same thing, tab completion works just fine after the colon. It's only through the release candidate / pre-release installers that it does not work (but in the former case, I launch the terminal through mingw64_shell.bat and in the latter case I use git-bash.exe).

I'm not sure what trace / diagnostics I can run to debug this issue, otherwise I'd help out. Would you mind looking into this or at least give me some debugging tips for this and I'd be happy to help you out.

pending-answer

All 23 comments

This almost sounds as if the tab completion was unable to connect automatically via SSH when run via git-bash.exe, but it works just fine when run through mingw64_shell.bat. Maybe in the former case you need a password?

My SSH keys were generated with no passphrase, so it shouldn't be a password thing.

I'm a bit confused hearing you talking about it connecting. Does git completion require communication with the remote? I figured it functioned off of the remote tracking branches, regardless of the specific URL for the remote itself.

I recall the completion taking a very long time once, leading me to the assumption that yes, it connects. I have no evidence to back up my claim, though.

I definitely know what you mean. Even when it _is_ working, it is extremely slow. It's suspect.

Since we both seem to have something to gain here, I will take a peek at the git completion script. Maybe I can answer both of our questions. I'm not well-versed with bash scripting, but I'll do what I can. I'll keep you updated.

This is what I am going to look at. Not sure what you are packaging with the installer though.
https://github.com/git/git/blob/master/contrib/completion/git-completion.bash

Well that didn't take long. I have a little bit to go on:

Looks like git completion is running git ls-remote. That would explain it. However, based on a discussion I read, it is only supposed to do this as a fallback. Perhaps the script is not running properly on the Windows build and always executes the fallback solution?

I'll keep digging and find out more detail.

Also I know why tab completion isn't working for push now.

The bash completion script uses the local refs to auto-fill in the 2nd placement argument to push. So if you've deleted your local version of a branch, and then you want to push after that to delete the branch on the remote, it will not auto-complete because the local branch was removed first.

Here is my test case:

$ git branch -df feature/my-feature
$ git push origin :feature/my-feature

In the 2nd command, auto-completion of the :feature/my-feature parameter was not working (I had to type it out manually). To try to force it to use ls-remote to auto complete, I tried this:

$ git push origin :refs/heads/feature/my-feature

However this didn't trigger it either. At this point I think we can close this issue as it doesn't seem to be related to the Windows version of Git. However, I haven't completely verified this since I do not have a linux VM or machine to test on. I will assume just based on the shell script itself that this problem happens on linux as well.

I want to reopen this issue after 3 years because I'm still running into this problem, even on the latest version of GfW. I have a linux machine now, and I was able to verify that tab completion after colon works even without a local ref present. It is able to deduce the completion from remote tracking branches (since I'm pushing to delete a branch on the remote repository that I do not have under refs/heads/. Also Ubuntu doesn't seem to be doing any remote communication with the repo to do this.

Do you have any idea on this? Contrary to my last statement, this does seem to be a Windows-only issue since Linux is working as expected.

As a test, I tried auto completing a remote branch named release/7.2.4. Doing it this way did not work:

$ git push origin :rel<TAB HERE>

However, doing it with a quote after the : did work:

$ git push origin :"rel<TAB HERE>

In the latter case, I get :"release/7.2.4 ". But the push fails here due to invalid ref (I think the quotes confuse it somehow). Should I bring this issue to the Git mailing list or is there something that can be done on the Windows side?

I wanted to bump this issue since it's still one of the issues that bugs me day to day. Label "pending-answer" is still here, but I'm not sure what question we're waiting on an answer to at this point. If the pending question is about passwords, I do everything through SSH URLs, so no password should be involved. Also Git has significantly changed since this issue was opened, so I think maybe rebooting the conversation may help.

Any developers that can help me understand what I can do to provide more information? I'm able to reproduce this in any repository, so an actual MCVE isn't hard to find. If this is due to my Git configuration or some other environment issue (maybe .bashrc or something), I'm not sure what it could be. If configuration/environment seem likely, please let me know what I can provide that would be helpful.

Thanks once again.

You'll have to dig further, by setting GIT_TRACE=1 in your shell before tab-completing.

I set that and I don't see any output when I hit TAB to complete something... I remember this working in the past, but tab completion isn't respecting GIT_TRACE for some reason...

You can also insert export GIT_TRACE=1 into the completion script at /mingw64/share/git/completion/git-completion.bash.

It's really up to you how much effort you want to spend on addressing your issue. If you don't want to, we can just close this ticket.

Effort is required by both parties.

You are a very funny person.

export GIT_TRACE=1 did nothing. However, I did set -x to get some output. I typed this much:

git push origin HEAD :hotfix/7.2.7.11 :hotfix/7

After the 7 above, I push tab and get:

$ git push origin HEAD :hotfix/7.2.7.11 :hotfix/7+ __git_func_wrap __git_main
+ local cur words cword prev
+ _get_comp_words_by_ref -n =: cur words cword prev
+ local exclude cur_ words_ cword_
+ '[' -n = -n ']'
+ exclude==:
+ shift 2
+ __git_reassemble_comp_words_by_ref =:
+ local exclude i j first
+ exclude==:
+ cword_=7
+ '[' -z =: ']'
+ (( i=0, j=0 ))
+ (( i < 8 ))
+ first=t
+ '[' 0 -gt 0 ']'
+ words_[$j]=git
+ '[' 0 = 7 ']'
+ (( i++, j++ ))
+ (( i < 8 ))
+ first=t
+ '[' 1 -gt 0 ']'
+ '[' -n push ']'
+ '[' '' = push ']'
+ words_[$j]=push
+ '[' 1 = 7 ']'
+ (( i++, j++ ))
+ (( i < 8 ))
+ first=t
+ '[' 2 -gt 0 ']'
+ '[' -n origin ']'
+ '[' '' = origin ']'
+ words_[$j]=origin
+ '[' 2 = 7 ']'
+ (( i++, j++ ))
+ (( i < 8 ))
+ first=t
+ '[' 3 -gt 0 ']'
+ '[' -n HEAD ']'
+ '[' '' = HEAD ']'
+ words_[$j]=HEAD
+ '[' 3 = 7 ']'
+ (( i++, j++ ))
+ (( i < 8 ))
+ first=t
+ '[' 4 -gt 0 ']'
+ '[' -n : ']'
+ '[' : = : ']'
+ '[' 4 -ge 2 ']'
+ '[' -n t ']'
+ (( j-- ))
+ first=
+ words_[$j]=HEAD:
+ '[' 4 = 7 ']'
+ (( 4 < 8 - 1 ))
+ (( i++ ))
+ '[' 5 -gt 0 ']'
+ '[' -n hotfix/7.2.7.11 ']'
+ '[' '' = hotfix/7.2.7.11 ']'
+ words_[$j]=HEAD:hotfix/7.2.7.11
+ '[' 5 = 7 ']'
+ (( i++, j++ ))
+ (( i < 8 ))
+ first=t
+ '[' 6 -gt 0 ']'
+ '[' -n : ']'
+ '[' : = : ']'
+ '[' 4 -ge 2 ']'
+ '[' -n t ']'
+ (( j-- ))
+ first=
+ words_[$j]=HEAD:hotfix/7.2.7.11:
+ '[' 6 = 7 ']'
+ (( 6 < 8 - 1 ))
+ (( i++ ))
+ '[' 7 -gt 0 ']'
+ '[' -n hotfix/7 ']'
+ '[' '' = hotfix/7 ']'
+ words_[$j]=HEAD:hotfix/7.2.7.11:hotfix/7
+ '[' 7 = 7 ']'
+ cword_=3
+ (( i++, j++ ))
+ (( i < 8 ))
+ cur_=HEAD:hotfix/7.2.7.11:hotfix/7
+ '[' 4 -gt 0 ']'
+ case "$1" in
+ cur=HEAD:hotfix/7.2.7.11:hotfix/7
+ shift
+ '[' 3 -gt 0 ']'
+ case "$1" in
+ words=("${words_[@]}")
+ shift
+ '[' 2 -gt 0 ']'
+ case "$1" in
+ cword=3
+ shift
+ '[' 1 -gt 0 ']'
+ case "$1" in
+ prev=origin
+ shift
+ '[' 0 -gt 0 ']'
+ __git_main
+ local i c=1 command __git_dir __git_repo_path
+ local __git_C_args C_args_count=0
+ '[' 1 -lt 3 ']'
+ i=push
+ case "$i" in
+ command=push
+ break
+ '[' -z push ']'
+ __git_complete_command push
+ local command=push
+ local completion_func=_git_push
+ declare -f _git_push
+ declare -f _git_push
+ _git_push
+ case "$prev" in
+ case "$cur" in
+ __git_complete_remote_or_refspec
+ local cur_=HEAD:hotfix/7.2.7.11:hotfix/7 cmd=push
+ local i c=2 remote= pfx= lhs=1 no_complete_refspec=0
+ '[' push = remote ']'
+ '[' 2 -lt 3 ']'
+ i=origin
+ case "$i" in
+ remote=origin
+ break
+ '[' -z origin ']'
+ '[' 0 = 1 ']'
+ '[' origin = . ']'
+ case "$cur_" in
+ case "$COMP_WORDBREAKS" in
+ : great
+ cur_=hotfix/7.2.7.11:hotfix/7
+ lhs=0
+ case "$cmd" in
+ '[' 0 = 1 ']'
+ __git_complete_refs --remote=origin --pfx= --cur=hotfix/7.2.7.11:hotfix/7
+ local remote track pfx cur_=HEAD:hotfix/7.2.7.11:hotfix/7 'sfx= '
+ test 3 '!=' 0
+ case "$1" in
+ remote=origin
+ shift
+ test 2 '!=' 0
+ case "$1" in
+ pfx=
+ shift
+ test 1 '!=' 0
+ case "$1" in
+ cur_=hotfix/7.2.7.11:hotfix/7
+ shift
+ test 0 '!=' 0
++ __git_refs origin '' '' hotfix/7.2.7.11:hotfix/7 ' '
++ local i hash dir track=
++ local list_refs_from=path remote=origin
++ local format refs
++ local pfx= cur_=hotfix/7.2.7.11:hotfix/7 'sfx= '
++ local match=hotfix/7.2.7.11:hotfix/7
++ local fer_pfx=
++ __git_find_repo_path
++ '[' -n '' ']'
++ '[' -n '' ']'
++ '[' -n '' ']'
++ '[' -n '' ']'
++ '[' -d .git ']'
+++ git rev-parse --git-dir
++ __git_repo_path=E:/code/frontend2/source/.git/modules/Core
++ dir=E:/code/frontend2/source/.git/modules/Core
++ '[' -z origin ']'
++ __git_is_configured_remote origin
++ local remote
+++ __git_remotes
+++ __git_find_repo_path
+++ '[' -n E:/code/frontend2/source/.git/modules/Core ']'
+++ return
+++ test -d E:/code/frontend2/source/.git/modules/Core/remotes
+++ __git remote
+++ git remote
++ for remote in $(__git_remotes)
++ '[' fork = origin ']'
++ for remote in $(__git_remotes)
++ '[' origin = origin ']'
++ return 0
++ list_refs_from=remote
++ '[' remote = path ']'
++ case "$cur_" in
++ '[' remote = remote ']'
++ case "HEAD" in
++ __git for-each-ref '--format=%(refname:strip=3) ' 'refs/remotes/origin/hotfix/7.2.7.11:hotfix/7*' 'refs/remotes/origin/hotfix/7.2.7.11:hotfix/7*/**'
++ git for-each-ref '--format=%(refname:strip=3) ' 'refs/remotes/origin/hotfix/7.2.7.11:hotfix/7*' 'refs/remotes/origin/hotfix/7.2.7.11:hotfix/7*/**'
+ __gitcomp_direct ''
+ local 'IFS=
'
+ COMPREPLY=($1)
+ return 0
+ return

Hopefully this is helpful. I have no idea how to understand the behavior from this output. Let's see if you can reciprocate my effort this time. Of course, I am always open to more reasonable requests for information.

I'll spend as much time on this as you did, this time. So... let's see, this all looks quite obvious to me (and should look obvious to you, too, apart from the COMP parts that are unintuitive). And yes, it tries to complete the command in

  • __git_complete_refs --remote=origin --pfx= --cur=hotfix/7.2.7.11:hotfix/7

... oops, I now probably spent as much time as you did to produce this trace (but you did not read it, obviously).

But since I am already reading it: it is quite interesting to see that toward the end, there is a git for-each-ref call that should have produced something. Obviously, it fails to find your ref:

++ git for-each-ref '--format=%(refname:strip=3) ' 'refs/remotes/origin/hotfix/7.2.7.11:hotfix/7' 'refs/remotes/origin/hotfix/7.2.7.11:hotfix/7/**'

And this is where you could direct your further investigation.

Sorry I have a real job that keeps me busy. I don't have the time to fix your bugs for you, unfortunately. I'm glad you find everything so obvious. Should make this trivial for you to fix.

@rcdailey you continue to misunderstand how Git for Windows is run. This is not my bug to fix. It is yours. This is open source, baby. It's only working for you as well as you make it.

Technically, I am maintainer. So you should contribute, and I should only help you get fixes and enhancements integrated.

I am really sad to see that you still did not get this, after all those years.

I'm glad you find everything so obvious. Should make this trivial for you to fix.

And I have to admit that I find it sort of amazing how you can admit that others have a ton more expertise than you do, and at the same time expect them to give that expertise so freely to you, with nothing in return.

This kind of sense of entitlement is toxic, is detrimental to a healthy community, and I won't have any of it in this project.

The problem I have with you is that you're consistently rude to folks that file issues on your project. You speak to them in a condescending way. I'm not the only one that has had this problem.

I think the main issue I have with you is that you're unwilling to help, or at least speak politely to, people that only file issues and are unable to contribute. I feel like if someone reports a bug on this project, you immediately expect them to fix that issue, regardless of their personal circumstances or domain expertise. If you want to talk about a "sense of entitlement", look inwards my friend.

I'm not really interested in bickering with you. Much like I barely have time to contribute real fixes here (as much as I'd genuinely love to, not that you'd appreciate that), I also don't have time to fight with you. Nor is it productive.

I'm calling you out on this not because I feel like upsetting you, but because I really feel like you need to change this behavior. I can understand how it may feel annoying, with your level of expertise and knowledge about Git, to deal with a bunch of "newbies" all the time, that probably don't follow your templates (I'm guilty of this as well), but as hard as that may be, I still think you should follow some proper etiquette. Treat people with respect and you might get a lot more positive feedback; heck you might even get more contributions.

I'm going to be the adult here and apologize for my earlier sarcasm. I unreasonably lost my patience with you because I got fed up with the types of responses I got from you. But the better thing to do would have been to not file an issue at all.

I really hope you'll take my feedback to heart. Again, I'm not trying to attack you. I'm just sharing my feelings and overall observations the past few years. I really want this project to succeed and I think this is an important step to making that happen.

Best wishes.

I'll give you an example. One of the guys on the Git LFS project is super polite all the time. Look at his responses:

I recently filed a bug there and performed some analysis for him, and he said "thanks", he didn't tell me "Fix the bug".

I find it super easy to work with the developers there. They don't make me feel belittled because I'm not contributing real code. They genuinely try to help get some more information and facts about an issue to add it to their backlog, they don't have the immediate assumption that the bug filer will be fixing the issue. Of course, I'm sure they're very happy to get help, but they don't push it on every single person that files a bug.

Another example, Linus Torvalds. I always thought he was condescending and rude, but even _he_ admitted his behavior was undesirable to the community and vowed to improve it. If he can do it, I'm sure you can too.

I'd like to try and help in clarifying some misunderstandings about the problems of tolerance and appropriateness in our modern disparate communities, with all the confusing 'equality' expectations.

The majority of the [active English speaking] community would appear to be from North America, with a strong smattering of Europeans. One should be aware that this breadth includes lots of different cultural norms which are oft classed as being part of National identities and ideals. This cuts many ways.

Part of the issue is one of assimilation and distinction. It takes time, and effort, to decide what to do about perceived differences. Some we learn to accept, others we (as individuals in a community) choose to suppress. At the margins, it can be difficult to put ones finger on any particular issue, nor suggest practical (actionable) steps in the right direction.

It is not possible to provide perfect (or even broadly good) 'fairness' measurements (see Tutorial: 21 fairness definitions and their politics about impossibility theorems).

I think one issue here is that we are forgetting Nationality and upbringing aspects are unique to us all. In particular, a directness of approach is classed as good in Germany (and in Engineering in general).

For example: Germans, the notoriously direct and Some Differences between German and English Academic Writing Styles.

As an Engineer, who now provides advice to fellow Engineers of Profession Registration in the UK, I do see the same issues and difficulties of writing style choice, and in the past had some big difficulties myself.

A key point is to provide actionable advice rather than what can be easily seen as generalisations. In my case the key learning I took was to identify specific phrases that can be dropped into the sentence to (attempt to) defuse any misunderstanding.

The (my) very first example (back in the '80s) was for secretaries taking minutes (only male on the course) - when the chairman asks the secretary to serve coffee, and continues talking, how to take minutes and serve at the same time? The answer was the immediate interjection of the phrase "Are we taking a break then?", which immediately put the problem back to the chairman in a natural manner and defused the situation (which otherwise leads to the secretary being marked as incompetent for producing incomplete minutes).

I have extended that to ensure I pick up short interjection phrases that can be added when I feel I've written a too short a response.

I also now try to make sure I clarify what any "it" style word is actually referring too - the reader often doesn't have the prior text and misunderstands/miss-remembers what the item is, or was confused about expectations.

While the upstream Git does have a large community, Git for Windows only survives because of Dscho's commitment (though IIUC, now with a little support of his employer), which does mean that he is time poor for helping out.

Maybe what is needed is a short phrase he could use to say "Unfortunately, at the moment I don't have any available time to pursue this particular issue further. We'd welcome any additional information and feedback from your investigations." at the relevant point. It may also need a phrase to cover the need to close issues as part of the issue triage process.

Spotting these points where someone didn't say enough is worth doing if we are to communicate a bit better in this difficult medium

Thank you, @PhilipOakley, for trying to help!

I fear that in this instance, it would take more than just me picking up a couple of phrases.

Disclaimer: in the following, you might read statements that you disagree with, statements that might be written a bit more forcefully than you are comfortable with, because I really need to drive home a point that I should have driven home a long time ago, to prevent the discussion in this ticket to become that unreasonable and hot-tempered.

First, let me clarify what my employer's commitment is (at least from what I understand), followed by an explanation what it is not.

And I might add the same discussion about my commitment.

So first things first: Microsoft made a huge bet on Git. Windows' source code is maintained in Git, and it took a lot of work to get there, and it will take more work to stay there. Naturally, we are interested in the long-term viability of the project, and we are also interested in a couple of bits and pieces that probably are of lesser concern to the average developer who does not happen to work on an insanely large monorepo. Of course, to that end, we are asking the core developers for feedback and help when we get stuck, but we proved beyond doubt that we're not just asking and asking, but giving more back than we're asking for, like good open source citizens (which should go without saying, but apparently does not: if you want to guarantee the longevity of anything, don't suck out its life blood, give something back). With our own source code in Git, it is obvious that our customers take that cue and are looking into using Git themselves. Our customer obsession is legendary, so when we encounter a problem in Git which we are convinced will also hit our customers, we will try to solve it in such a way that the fix also benefits our customers. Typically we will develop these things in VFS for Git first, then port them to Git for Windows or contribute them directly to the Git project, or we start in Git for Windows, then port them simultaneously to Git and VFS for Git. Or we work directly on Git.

Having said that, Git for Windows is not a Microsoft product. I am sure that a lot of users will find that very relieving, given Microsoft's past. That means that Microsoft will never even try to control Git, or Git for Windows. The flip side is that it is no supported product, either. So not even as a paying customer can you come and demand that I or one of my colleagues fix something for you. That'd just be plain unreasonable.

As to my commitment? If there was anybody who needed any proof about my commitment to sustain Git and Git for Windows, the information is out in the open, for everybody to see. Anybody who thinks they need proof of my commitment simply did not look hard enough, and it really takes almost no effort whatsoever to figure that one out.

Does that mean that I am committed to enslave myself to every wish and whim of any random Josephine Git User?

Nope, it does not. My commitment is to the Git project. If I see a bug report that indicates what I consider to be a serious flaw in Git, I will try to allocate time to investigate and probably fix it. If I notice a problem in new versions of one of our components (e.g. OpenSSL, cURL, etc) that might cause problems when integrated into Git for Windows, I will try to work as best as I can with those projects to prevent those problems.

If I see a bug report of somebody who would be quite able to learn the ropes, and help themselves, and that bug really looks like it might affect maybe one, maybe a dozen users, not more, then I feel no obligation whatsoever to spend my evenings and nights away from my life. If users cannot be bothered to put in a bit of effort but expect me to put in all the effort, then something is wrong with them, not with me.

Even if it might be seen as reasonable to expect a software maintainer to take care of all bug fixes, and users go scot-free, it simply would not scale here.

Git for Windows v2.20.1 was downloaded almost 5 million times, and v2.21.0 is getting there (already over 2.5 million times). It is therefore safe to assume that the number of Git for Windows users is in the millions. I don't think that it would be fair for any of them to expect a single person to take care of their issues for them.

And I say "taking care for them" because at the end of the day, none of us are toddlers. We all are responsible for our own stuff. We are responsible for taking care of our needs, and if that means to set aside time to learn enough C or Bash to dig through a complete investigation of an issue, so be it. If you are not prepared to do much of anything to get your problems resolved, but expect somebody else who you neither paid nor compensated in any other way to resolve them for you, well, as far as I am concerned, then you can keep looking for that somebody. Then you are feeling unduly entitled, and to be honest, I think the Git for Windows project might be better off without you. Because there is one thing you do not want to do with a project you rely on, and that has such a small bus factor as Git for Windows. You don't want to be the one responsible for killing it.

Hi @dscho (Johannes), thanks for the many bits of clarification. It's good to hear of your view of the Microsoft commitment to Git and the scale of use of your Git for Windows (GfW).

There was one confusion I wasn't sure about in my mind, about the commitment MS has made to you (e.g. perhaps the classic 10% time for personal projects) to support your efforts on GfW, as compared to $dayjob work.

I'm sort of guessing that MS is pretty supportive, as the GfW activities are very complementary to its broader goals in being able to use Git for its Windows mega-mono-repo, and support its customers, but then again not so supportive that $dayjob suffers. (I've never quite fathomed Junio's $dayjob position at Google relative to upstream Git, but that's a separate query).

That said, there's still not that many hours in day to do everything (so not everything can get done ;-).

In terms of mollycoddling folks, I'd agree that there are limits, and for a community of 5 million downloads that's essentially zero time for most. Any effort is best applied for common good communal benefit.

Mind you, many of the GfW user base are probably less capable than we'd hope or desire, just through the 'quantity' and breadth aspects, hence the discussion about letting folk down gently (but triaged non the less), which can pay dividends.

Anyway, back to looking at the other >4Gb stuff... (I always guess that colon related stuff is because it's not valid in windows file names - I leave that issue hanging..)

Was this page helpful?
0 / 5 - 0 ratings