Hi Rolf, On Sat, May 05, 2012 at 12:24:38PM +0800, Rolf Leggewie wrote: > After all is said and done, though, the bash-completion remains > inconsistent and thus broken. It's great that your life is > currently more convenient but in the end you are relying on broken > behaviour. Well, git's completion script is consistent with itself: whenever there is no matching subcommand, option, parameter for an option, or ref, it falls back to filename completion. I wouldn't consider this behavior as broken. > Affected commands: > git log > git diff > git whatchanged > git branch (why offer tags OR files here at all) While files and tags make no sense for 'git branch' itself, completing them can be helpful to construct the name of a new branch. I did the following at dayjob just the other day: # there are route_calculation.c and .h files in that project, and # there were some nasty bugs in there $ git branch ro<TAB> # which gave me $ git branch route_calculation. # just deleted the '.' and completed the new branch name by hand $ git branch route_calculation_fixes Anyway, I see two ways to fix this if we want to be anal, but none of them is actually applicable: - When registering _git() as the completion function for the git command, we specify some options to tell Bash to do filename completion when we can't find any matches to the word to be completed. Recent Bash versions provide the 'compopt' builtin to allow modifying completion options for the currently executed completion. We could do a 'compopt +o bashdefault +o default' to disable the filename completion fallback wherever we deem it inappropriate. 'compopt' was introduced in Bash 4.0, but unfortunately msysgit still includes an older version, so this is a no go. - We don't specify the options to ask Bash to fall back to filename completion when registering _git(). This will disable filename completion for the whole git completion script, so we must roll our own helper functions to do filename completion, which we would invoke wherever filename completion is explicitly desired. This should work on any Bash version, but would inherently include some fork()+exec()s, adding significant delays especially on msysgit. > Unaffected programs, i.e. working correctly: > git commit > [...] You haven't tried it hard enough ;) $ git commit --fixup=e<TAB> editor.c entry.c environment.c exec_cmd.c exec_cmd.o editor.o entry.o environment.o exec_cmd.h although at that point only a commit is accepted. > Some consistency would be great. In a perfect world bash-completion > ought to work on all possible completion targets but at the same > time it should exclude all that make no sense, too. Neither of the > two seems to be currently the case. Yeah, in that perfect world 'git rm <TAB>', 'git bisect -- <TAB>', and 'git log -- <TAB>' whould offer only tracked files, 'git (add|commit) <TAB>' only modified or untracked files, and 'git diff <TAB>' would read your mind to find out whether you want to diff a ref or a file, etc. etc. But you miss an important point here: users expect the completion to be pretty fast, because delays are quite noticeable and annoying while typing a command. So there's a trade-off between correctness and usability. Unfortunately, in the real world all that filtering costs a great deal, so git's completion script does that only if it can be done cheaply (e.g. 'git rebase --<TAB>' won't offer you '--abort' and '--continue' if you're not in the middle of an ongoing rebase). And as pointed out above, something might be nonsense for a command, but still be useful for the user. Best, Gábor -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html