85

I'm using go as a simple bash alias for git checkout branchname. The thing that I miss is the autocomplete feature that works with the full git checkout branchna... command, but not in the alias.

Is there a way to instruct Bash to "inherit" the autocomplete "driver" for another command?

Claudio
  • 4,834
  • 4
  • 26
  • 37
  • 1
    Duplicate with : http://unix.stackexchange.com/questions/4219/how-do-i-get-bash-completion-for-command-aliases – Arnaud F. Mar 26 '12 at 09:15
  • Possible duplicate of [How do I get bash completion to work with aliases?](http://stackoverflow.com/questions/342969/how-do-i-get-bash-completion-to-work-with-aliases) – phuclv May 04 '17 at 04:35
  • Related: if the alias sets a custom `git-dir` then use [this](https://unix.stackexchange.com/questions/216748/). – user202729 Oct 18 '19 at 01:33
  • @Claudio, would you consider revisiting your choice of Accepted Answer? The most-upvoted answer seemed a lot more useful to me (who came looking with exactly the same problem you had) – Brondahl Mar 04 '21 at 23:01
  • @Brondahl hey, thanks for the suggestion. I just did it. – Claudio Mar 25 '21 at 12:25

9 Answers9

108

After using complete -F:

complete -F _git_checkout go

Tabbing after go may result in:

bash: [: 1: unary operator expected

Instead of complete, use __git_complete

This is git bash completion's built-in function for this purpose.

After declaring your alias, bind the correct auto-complete function to it:

# Main git completions (prior to git 2.30, you an use _git instead of __git_main)
alias g="git"
__git_complete g __git_main

alias go="git checkout"
__git_complete go _git_checkout

alias gp="git push"
__git_complete gp _git_push
DylanYoung
  • 1,835
  • 22
  • 27
theprogrammerin
  • 1,096
  • 2
  • 8
  • 3
  • 4
    @LưuVĩnhPhúc I was having the same issue. It was because I had the `__git_complete` function in my bash-completion package (installed via homebrew with `brew install bash-completion`), which was not currently sourced in my bash profile. Had to add this line to ~/.bash_profile: `[ -f /usr/local/etc/bash_completion ] && . /usr/local/etc/bash_completion` – jangosteve Mar 24 '17 at 17:48
  • 1
    Adding __git_complete under `git checkout` alias worked like charm !!! – Rajaraman Feb 20 '20 at 08:22
  • 2
    It should be `__git_main`, not `_git`. The reason `_git` exists is for backwards compatibility only, it's basically `__git_main` wrapped. – FelipeC Oct 24 '20 at 04:10
  • And `_git` not longer works as of Git 2.30 – DylanYoung Feb 22 '21 at 23:00
  • if you want branch name completeion as well, take a look here https://levelup.gitconnected.com/upgrade-your-command-line-for-software-development-with-git-autocomplete-1fb946c14750 – Steve May 19 '21 at 14:20
46

If you can find out the completion function used by the original command, you can assign it to the alias using complete -F.

For example, on my ubuntu box, the completion function used by git checkout is _git_checkout (found in /etc/bash_complete.d/git).

Example

Before running complete -F:

[me@home]$ git checkout <TAB><TAB>
HEAD            master          origin/HEAD     origin/master

[me@home]$ alias go="git checkout"

[me@home]$$ go <TAB><TAB>
.git/                precommit_config.py  README.md            SvnSentinel/         
.gitignore           precommit.py         startcommit.py       tests/ 

After:

[me@home]$$ complete -F _git_checkout go

[me@home]$$ go <TAB><TAB>
HEAD            master          origin/HEAD     origin/master 
Shawn Chin
  • 74,316
  • 17
  • 152
  • 184
  • 1
    on ubuntu 12.04 the completions seem to live in: /etc/bash_completion.d/git and not /etc/bash_complete.d/git – Maks Oct 22 '13 at 00:26
  • 9
    If `complete -F` doesn't work for you, see the answer about `__git_complete` below http://stackoverflow.com/a/24665529/3779 – Steve Clay Oct 09 '14 at 18:24
21

On Ubuntu 18.04 (Bionic) the following works. Add something like this snippet (with your aliases) to your preferred bash configuration file e.g. .bashrc, .bash_aliases .bash_profile.

# define aliases
alias gc='git checkout'
alias gp='git pull'

# setup autocompletion
if [ -f "/usr/share/bash-completion/completions/git" ]; then
  source /usr/share/bash-completion/completions/git
  __git_complete gc _git_checkout
  __git_complete gp _git_pull
else
  echo "Error loading git completions"
fi

In general the format of the __git_complete directive is the following:

__git_complete <YOUR ALIAS> _git_<GIT COMMAND NAME>

This combines wisdom from the existing answers in a single up-to-date answer, thank you all.

adamnfish
  • 9,719
  • 4
  • 28
  • 40
  • I would just like to add that for an ssh/terminal only session, put everything in .bashrc. I had the git complete stuff in .bash_profile and the aliases in .bashrc and couldn't get it working. It wasn't until I added an `echo "profile"` / `echo "rc"` that I figured that one out. – mtonc Jun 20 '19 at 17:24
19

In Ubuntu 16.04.3 LTS, the file I needed to source was /usr/share/bash-completion/completions/git. So in .bash_custom (or .bashrc, whatever):

[ -f /usr/share/bash-completion/completions/git ] && . /usr/share/bash-completion/completions/git
__git_complete g __git_main
user202729
  • 2,317
  • 3
  • 12
  • 27
SeamusJ
  • 381
  • 5
  • 10
  • 1
    The reason of requiring manual loading is that currently Bash loads those files dynamically. So far it loads them according to their name. The file won't be loaded until you hit a Git completion, which is too late by the time `.bashrc` was read. – Franklin Yu Nov 19 '19 at 18:43
3

As somebody else answered you should use __git_complete, otherwise the script will fail.

alias g="git"
__git_complete g __git_main

alias g="gl"
__git_complete gl _git_log

But you shouldn't use _git for the main command, it's __git_main.

Unfortunately a lot of information about the completion is hidden, but you can find more on the README of my fork: git-completion.

FelipeC
  • 7,483
  • 4
  • 37
  • 33
2

To add to other excellent answers: normally you have a lot of Git aliases and it may be tedious to manually forward completions for all of them. Here's a small trick to do this automatically:

if [ -f "/usr/share/bash-completion/completions/git" ]; then
  # Enable Git completions for aliases
  . /usr/share/bash-completion/completions/git
  for a in $(alias | sed -n 's/^alias \(g[^=]*\)=.git .*/\1/p'); do
    c=$(alias $a | sed 's/^[^=]*=.git \([a-z0-9\-]\+\).*/\1/' | tr '-' '_')
    if set | grep -q "^_git_$c *()"; then
      eval "__git_complete $a _git_$c"
    fi
  done
fi
yugr
  • 13,457
  • 3
  • 37
  • 71
2

I realize you're specifically asking about bash aliases, but for those coming here looking for autocomplete in bash for complex git aliases, see here.

In particular:

# If you use complex aliases of form '!f() { ... }; f', you can use the null
# command ':' as the first command in the function body to declare the desired
# completion style.  For example '!f() { : git commit ; ... }; f' will
# tell the completion to use commit completion.  This also works with aliases
# of form "!sh -c '...'".  For example, "!sh -c ': git commit ; ... '".
DylanYoung
  • 1,835
  • 22
  • 27
1

On Linux Mint, this didn't work for me. I was getting bash: [: 1: unary operator expected .

I found the following response worked quite well - with the troubleshooting section the user provided to be quite helpful. https://superuser.com/questions/436314/how-can-i-get-bash-to-perform-tab-completion-for-my-aliases

Community
  • 1
  • 1
Mario Olivio Flores
  • 1,313
  • 14
  • 17
0

For macOS, run the following to install bash completion

 brew install bash-completion

Then add the following

[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh" 

to your .bashrc or .bash_profile

Anthony Kong
  • 29,857
  • 33
  • 139
  • 244