¿Git autocompletar en alias de bash?

82

Lo estoy usando gocomo un alias bash simple para git checkout branchname. Lo que extraño es la función de autocompletar que funciona con el git checkout branchna...comando completo , pero no en el alias.

¿Hay alguna forma de instruir a Bash para que "herede" el "controlador" de autocompletar para otro comando?

Claudio
fuente
1
Duplicar con: unix.stackexchange.com/questions/4219/…
Arnaud F.
Relacionado: si el alias establece un personalizado git-dir, use esto .
user202729

Respuestas:

46

Si puede averiguar la función de finalización utilizada por el comando original, puede asignarla al alias utilizando complete -F.

Por ejemplo, en mi caja de ubuntu, la función de finalización utilizada por git checkoutes _git_checkout(que se encuentra en /etc/bash_complete.d/git).

Ejemplo

Antes de correr 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/ 

Después:

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

[me@home]$$ go <TAB><TAB>
HEAD            master          origin/HEAD     origin/master 
Shawn Chin
fuente
1
en ubuntu 12.04 las terminaciones parecen vivir en: /etc/bash_completion.d/git y no /etc/bash_complete.d/git
Maks
8
Si complete -Fno funciona para usted, vea la respuesta a __git_completecontinuación stackoverflow.com/a/24665529/3779
Steve Clay
97

Después de usar complete -F:

complete -F _git_checkout go

Tabular después gopuede resultar en:

bash: [: 1: unary operator expected

En lugar de complete, usa__git_complete

Esta es la función incorporada de git bash complete para este propósito.

Después de declarar su alias, vincule la función de autocompletar correcta:

alias g="git"
__git_complete g _git

alias go="git checkout"
__git_complete go _git_checkout

alias gp="git push"
__git_complete gp _git_push
theprogrammerin
fuente
3
@ LưuVĩnhPhúc Estaba teniendo el mismo problema. Fue porque tenía la __git_completefunción en mi paquete de finalización de bash (instalado a través de homebrew con brew install bash-completion), que actualmente no se encontraba en mi perfil de bash. Tuve que agregar esta línea a ~ / .bash_profile:[ -f /usr/local/etc/bash_completion ] && . /usr/local/etc/bash_completion
jangosteve
¡Agregar __git_complete bajo git checkoutalias funcionó de maravilla !
Rajaraman
Debería serlo __git_main, no _git. La razón que _gitexiste es solo por compatibilidad con versiones anteriores, básicamente está __git_mainenvuelto.
FelipeC
18

En Ubuntu 16.04.3 LTS, el archivo que necesitaba obtener era /usr/share/bash-completion/completions/git. Entonces en .bash_custom(o .bashrc, lo que sea):

[ -f /usr/share/bash-completion/completions/git ] && . /usr/share/bash-completion/completions/git
__git_complete g __git_main
SeamusJ
fuente
1
La razón de requerir la carga manual es que actualmente Bash carga esos archivos dinámicamente. Hasta ahora los carga según su nombre. El archivo no se cargará hasta que llegue a la finalización de Git, que es demasiado tarde para el momento en que .bashrcse leyó.
Franklin Yu
17

En Ubuntu 18.04 (Bionic) funciona lo siguiente. Añadir algo como este fragmento (con sus alias) a su configuración preferida de fiesta de archivo, por ejemplo .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

En general, el formato de la __git_completedirectiva es el siguiente:

__git_complete <YOUR ALIAS> _git_<GIT COMMAND NAME>

Esto combina la sabiduría de las respuestas existentes en una única respuesta actualizada, gracias a todos.

maldito pez
fuente
Solo me gustaría agregar eso para una sesión ssh / terminal solo, poner todo en .bashrc. Tenía las cosas completas de git en .bash_profile y los alias en .bashrc y no pude hacer que funcionara. No fue hasta que agregué un echo "profile"/ echo "rc"que lo descubrí.
mtonc
2

Para agregar a otras excelentes respuestas: normalmente tiene muchos alias de Git y puede ser tedioso reenviar manualmente las finalizaciones para todos ellos. Aquí hay un pequeño truco para hacer esto automáticamente:

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
fuente
1

Para macOS, ejecute lo siguiente para instalar la finalización de bash

 brew install bash-completion

Luego agregue lo siguiente

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

a su .bashrc o .bash_profile

Anthony Kong
fuente
1

En Ubuntu 20.04 agrego esto a ~/.bashrc

source /usr/share/bash-completion/completions/git
alias g='git'
__git_complete g _git
alias go='git checkout'
__git_complete go _git_checkout
Matt Janssen
fuente
1

Como alguien más respondió, debe usar __git_complete, de lo contrario, el script fallará.

alias g="git"
__git_complete g __git_main

alias g="gl"
__git_complete gl _git_log

Pero no debes usarlo _gitpara el comando principal, es __git_main.

Desafortunadamente, hay mucha información oculta sobre la finalización, pero puede encontrar más en el archivo README de mi fork: git-deployment .

FelipeC
fuente
0

Me doy cuenta de que está preguntando específicamente sobre los alias de bash, pero para aquellos que vienen aquí en busca de autocompletar en bash para alias de git complejos, consulte aquí .

En 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
fuente