Git autocomplete for custom bash functions
Asked Answered
I

3

13

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)

Infer answered 11/10, 2017 at 19:33 Comment(0)
E
14

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).

Evaginate answered 11/10, 2017 at 19:57 Comment(7)
but that doesn't autocomplete it. If I type gitpull mas<TAB> it doesn't complete to master like it should.Infer
You're right, sorry, we need to filter the choices with the compgen according to the current (prefix) word.Evaginate
This is awesome. Thank you so much!Infer
What about remote branches? If I do git pull origin <TAB><TAB> it shows all possible branches (remote and local). Your solution only handles local branches.Infer
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.)Evaginate
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/.Infer
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.Evaginate
S
4

The recommended method is by using __git_complete():

__git_complete gitpull _git_pull
Selfreliance answered 25/6, 2019 at 15:45 Comment(0)
C
1

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.

Corespondent answered 17/1, 2021 at 3:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.