7

I am using Git with git-completion and everything works fine with a single exception: when I do

git p some_remote [TAB]

I get as autocomplete suggestions the files in the current directory (wrong). p is a Git alias:

$ cat ~/.gitconfig
[alias]
    p = push

Still, when I do:

git push some_remote [TAB]

I get as suggestions the branches in the current repository (correct). In both cases the completion for some_remote works correctly.

What is the reason for this?

adrianp
  • 2,289
  • 4
  • 21
  • 43
  • This is now fixed (April 2014, Git 2.0): see [my revised answer below](http://stackoverflow.com/a/20218023/6309). – VonC Jul 05 '14 at 14:15
  • As a variant on this, if your alias looks like this: `git config --global alias.p "push origin"` (so it also includes a default remote), tab completion breaks and still tries to offer remotes instead of skipping to branches. To fix this, define your own replacement function in `~/.profile` after sourcing git-completion.bash: `_git_p() { _git_branch; }` (where "p" matches the name of your git alias.) This will cause bash to treat your alias the same as the `branch` command. After this, `git p[tab]` will suggest branches, instead of remotes. See also: https://stackoverflow.com/q/11453807/70876 – beporter Oct 23 '15 at 14:59

2 Answers2

9

It's a bug!

git-completion.bash does go through your git aliases, wiring each up to the right completion function.

But then four of those—the functions for git push, fetch, pull, and remote—delegate to __git_complete_remote_or_refspec(), which starts like this:

__git_complete_remote_or_refspec ()
{
    local cur_="$cur" cmd="${words[1]}"
    ...

$words is just the list of tokens from the command line, and a few lines down, it starts checking $cmd without expanding aliases, for example:

case "$cmd" in
fetch)
  # ...
pull|remote)
  # ...


As far as I can tell, Gábor Szeder first reported this two years ago in a thread about making completion work with shell aliases.

He mentioned it again in 2012 in reply to a patch from Felipe Contreras (@felipec). Last month, Felipe announced his fork of git, which actually has a self-contained patch for this: b7b6be72.

I don't know if that's been submitted upstream, but in the meantime... if you want to test it out, apply the patch to your git-completion.bash:

curl https://github.com/felipec/git/commit/b7b6be72d60d.diff |
  patch -d [directory containing git-completion.bash]
  # useful options for patch: --verbose --dry-run

If you don't know where your current git-completion.bash lives, try declare -F:

dirname "$(shopt -s extdebug; declare -F __git_complete | awk '{ print $3 }')"

(After patching git-completion.bash, it'll prompt you for the location of git-completion.zsh to apply the second hunk... you can just hit ^C to skip it.)

chrisk
  • 1,636
  • 2
  • 10
  • 10
  • Interesting, and more precise than my answer. +1 – VonC Dec 03 '13 at 03:44
  • As you need to source `git-completion.sh`, it's probably easier to just `cat .bashrc` or similar :) Anyway, this works, thanks; hope that they will push it upstream. – adrianp Dec 03 '13 at 07:23
3

Update April 2014, for Git 2.0:

The commit 880111c (Felipe Contreras (felipec)) now includes:

completion: fix completing args of aliased "push", "fetch", etc.

Some commands need the first word to determine the actual action that is being executed, however, the command is wrong when we use an alias, for example 'alias.p=push', if we try to complete 'git p origin <TAB>', the result would be wrong because __git_complete_remote_or_refspec() doesn't know where it came from.

So let's override words[1], so the alias 'p' is override by the actual command, 'push'.


git-completion doesn't seem to work well with git alias or regular alias.

For instance, if you had defined an alias 'gp' for 'git push', as in "How do I get bash completion to work with aliases?", you could type:

__git_complete gp _git_push

Maybe something similar exist for git aliases, as in this script.

Community
  • 1
  • 1
VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
  • 2
    `__git_complete gp _git_push` does not seem to work well for me; it suggests the name of the remote correctly, but then it goes on suggesting the same remote names instead of branches. I already have implemented a variant of your second suggestion, and while it works, it's not perfect because: 1. it's not consistent with my existing git aliases and 2. it's buggy, i.e., it starts suggesting remote/ branch names only after inputting the first letter (I use vim-like completion in bash). – adrianp Nov 26 '13 at 14:15
  • @adrianp that would be for a regular alias, not a git alias though – VonC Nov 26 '13 at 14:17
  • Yes, I understood that :) – adrianp Nov 26 '13 at 14:18
  • @adrianp ok. Some more tests are in order, then. – VonC Nov 26 '13 at 14:18
  • I can confirm on Git 2.4.0 that this is still an issue (confirmed that my `git-complete.bash` has the code added by `880111c`). Are there any relevant GH issues where discussion about this issue is happening? I can't seem to find any other than this with at the least a workaround. – Bailey Parker May 22 '15 at 15:21