10

In my .bash_profile, I have a lot of functional shortcuts for git. For example:

function gitpull() {
    branch="$1"

    if [[ -z $branch ]]; then
        current_branch=`git symbolic-ref -q --short HEAD`
        git pull origin $current_branch;
    elif [[ -n $branch && $branch == "m" ]]; then
        git pull origin master;
    else
        git pull origin $branch;
    fi;
}

However, when I'm typing this in the terminal, I want it to autocomplete git branches. How do I do this? (I already am using .git-completion.bash)

randomir
  • 17,989
  • 1
  • 40
  • 55
Nxt3
  • 1,970
  • 4
  • 30
  • 52

3 Answers3

12

Manually-crafted bash completion is as simple as this:

# our handler that returns choices by populating Bash array COMPREPLY
# (filtered by the currently entered word ($2) via compgen builtin)
_gitpull_complete() {
    branches=$(git branch -l | cut -c3-)
    COMPREPLY=($(compgen -W "$branches" -- "$2"))
}

# we now register our handler to provide completion hints for the "gitpull" command
complete -F _gitpull_complete gitpull

After sourcing the above commands:

$ gitpull <TAB>
asd     master  qwe     zxc
$ gitpull m<TAB>
$ gitpull master

The ultimate reference on bash completion is (of course) the section on Programmable Completion in the bash manual, but a nice introduction is given on "Debian Administration" page (part 1 and a more important part 2).

randomir
  • 17,989
  • 1
  • 40
  • 55
  • 1
    but that doesn't autocomplete it. If I type `gitpull mas` it doesn't complete to `master` like it should. – Nxt3 Oct 11 '17 at 20:03
  • 1
    You're right, sorry, we need to filter the choices with the `compgen` according to the current (prefix) word. – randomir Oct 11 '17 at 20:38
  • 2
    This is awesome. Thank you so much! – Nxt3 Oct 11 '17 at 20:45
  • What about remote branches? If I do `git pull origin ` it shows all possible branches (remote and local). Your solution only handles local branches. – Nxt3 Oct 11 '17 at 20:50
  • 1
    You can add `-a` to `git branch -l` to also list remote branches. However, in that case, you'll probably need to filter names a little bit differently then just with `cut` (you might get `-> local/branch`, etc.) – randomir Oct 11 '17 at 20:58
  • Is there a good resource on how to write our own completion? You're right. All of the remote branches look something like `remotes/origin/branchname`. So, I need to get rid of the `remotes/`. – Nxt3 Oct 12 '17 at 13:53
  • 1
    I've added some refs to my answer. Be sure to check that intro (part 2). It may be a bit dated, but it's still valid. – randomir Oct 12 '17 at 14:01
3

The recommended method is by using __git_complete():

__git_complete gitpull _git_pull
FelipeC
  • 9,123
  • 4
  • 44
  • 38
0

With Git 2.31 (Q1 2021), the bash completion (in contrib/) is updated to make it easier for end-users to add completion for their custom "git" subcommands.

Thank to FelipeC (who wrote a previous answer on that same page)

See commit 5a067ba, commit 0e02bdc, commit 810df0e, commit 7f94b78 (30 Dec 2020) by Felipe Contreras (felipec).
(Merged by Junio C Hamano -- gitster -- in commit f9fb906, 15 Jan 2021)

completion: add proper public __git_complete

Signed-off-by: Felipe Contreras

When __git_complete was introduced, it was meant to be temporarily, while a proper guideline for public shell functions was established (tentatively _GIT_complete), but since that never happened, people in the wild started to use __git_complete, even though it was marked as not public.

Eight years is more than enough wait, let's mark this function as public, and make it a bit more user-friendly.

So that instead of doing:

__git_complete gk __gitk_main

The user can do:

__git_complete gk gitk

And instead of:

__git_complete gf _git_fetch

Do:

__git_complete gf git_fetch

Backwards compatibility is maintained.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250