¿Cómo cd automáticamente después de git clone?

37

Quiero acceder automáticamente cdal directorio creado por el clonecomando después de hacer git clonealgo.

Importante: no quiero alterar la sintaxis del comando (por ejemplo, usar un alias / función) porque rompería las terminaciones zsh que obtengo automáticamente del Pretzoproyecto.

EDITAR : La razón por la que no elegí ninguna respuesta como correcta, es porque no se dio ninguna respuesta que cumpliera con la condición anterior.

Yo uso ZSH, pero una respuesta en cualquier otro shell también es aceptable.

Daniel K.
fuente
Me gusta la respuesta unix.stackexchange.com/questions/97920/... pero es necesario mencionar que escribir esa función en el ~/.bashrcarchivo (por ejemplo) y para mí al menos no funcionó, necesitaba arreglarlo con el reemplazo del línea:/usr/bin/git "$@" 2>&1 | tee $tmp
lcestari

Respuestas:

19

Crea una función:

gclonecd() {
  git clone "$1" && cd "$(basename "$1" .git)"
}

(Funciona para enlaces con y sin ".git")

Frederik Deweerdt
fuente
2
Me gustaría seguir usando git clonedebido a todas las herramientas que tendría que cambiar si no estuviera usando git. Hub tiene un alias como git, oh-my-zsh proporciona autocompletado, etc ...
Daniel K.
3
@Wildeyes gitno puede cambiar el directorio de trabajo de su shell, así que de cualquier manera tendrá que envolverlo en un alias / función que haga lo que quiera y lo siga con el builtin incorporado cd. Si desea llamar en hublugar de githacerlo, hágalo en la función. Si desea que solo afecte al clonecomando, verifique la acción en la función. etc.
frostschutz
Noté que eso basename [email protected]:pckujawa/pattern-rec.gitda como resultado pattern-rec.git: ¿solo dejas la extensión .git cuando clonas?
Pat
8
@Pat basenametambién toma un argumento de sufijo, por lo que puede hacer:git clone $1 && cd $(basename $1 .git)
Henrik N
17

git clonetoma un argumento adicional: el directorio a usar. Puede hacerlo clonar en el directorio de trabajo actual con git clone URL . Entonces, no hay necesidad de cambiar el directorio de trabajo; ya estas ahi

Si realmente desea que el gitcomando cambie realmente el directorio de trabajo, puede cambiarlo a una función que llame al real gitcuando sea necesario:

git()
{
   local tmp=$(mktemp)
   local repo_name

   if [ "$1" = clone ] ; then
     /usr/bin/git "$@" | tee $tmp
     repo_name=$(awk -F\' '/Cloning into/ {print $2}' $tmp)
     rm $tmp
     printf "changing to directory %s\n" "$repo_name"
     cd "$repo_name"
   else
     /usr/bin/git "$@"
   fi
}
Kaz
fuente
Eso era exactamente lo que estaba buscando. Después de darme cuenta de que no hay ganchos internos o algo así, escribí una función casi exacta :)
Daniel K.
2
@Wildeyes Sí: tiene un /tmpvolumen que está en RAM, como lo hace cualquier Linux moderno a través de tmpfs. De todos modos, ¿por qué se preocupan por escribir en el disco, cuando se acaba de hacer un clon de git, que crea directorios y escribe quizá cientos de archivos en el disco ...
Kaz
1
Probablemente tenga razón sobre todo el asunto "nvm si escribe en el disco", solo estaba buscando guardar operaciones adicionales. Muchas gracias Kaz.
Daniel K.
3
Ten cuidado. lo es git [flags] command [arguments], por lo que pedir ciegamente cloneen cierta posición fallará.
vonbrand
1
¿Sería útil agregar el camino "real"? Me gusta: git_real_home = which git git () {... $ git_real_home "$ @" | tee $ tmp
aakoch
7

Si proporciona el nombre local del repositorio, es realmente fácil usar $ _ :

git clone git@github.com:npm/npm.git npm-local-dir && cd $_

Pero si no desea volver a escribir nombres largos, es un poco feo pero factible con sed:

git clone git@github.com:pckujawa/pattern-rec.git && 
cd `echo $_ | sed -n -e 's/^.*\/\([^.]*\)\(.git\)*/\1/p'`

EDITAR: Bueno, iba a agradecer a Manav (comentario a continuación) por el breve

git clone foo/bar && cd !$:t

pero no funciona en zsh (algo acerca de cómo zsh hace expansiones hace que no trate el primer comando como entrada !$). Tuve que buscar lo que !$:thizo ( Avanzando en Bash Shell | $ {me: -whatever} ). !$toma la última parte del comando anterior y :t"Eliminará todos los componentes principales del nombre de archivo, dejando la cola". Buena información, pero desearía poder hacerlo funcionar con zsh (lo intenté noglobsin éxito).

EDITAR: en lugar de usar sedo !$:t(que no funciona en zsh, para mí de todos modos), encontré otras dos opciones (una adaptando la respuesta https://unix.stackexchange.com/users/5685/frederik-deweerdt con https : //unix.stackexchange.com/users/129926/henrik-n's comment):

git clone git@github.com:npm/npm.git && cd $(basename $_ .git)

o

git clone git@github.com:npm/npm.git && cd ${${_%%.git*}##*/}
Palmadita
fuente
git clone foo/bar && cd !$:t
Manav
Si su URL de repositorio termina en .git, puede usar !$:t:rpara obtener el nombre de la carpeta.
Michael Stramel
2

Una solución simple para cualquier shell POSIX es especificar el directorio para clonar explícitamente (cualquier ruta del sistema de archivos) y reutilizarlo:

git clone <repository> <directory> &&
cd "$_"

y

cd -

cuando termines.

Lijadora
fuente
2

Podrías hacer algo como:

clone_check() {
  (($? != 0)) && return
  local cmd=$history[$((HISTCMD-1))]
  cmd=("${(@Q)${(z)cmd}}")
  if [[ $cmd = "git clone "* ]]; then
    local dir
    if (($#cmd == 3)); then
      dir=${cmd[3]:t}
      dir=${dir%.git}
      dir=${dir#*:}
    elif (($#cmd > 3)); then
      dir=$cmd[-1]
    else
      return
    fi
    print -r CDing into $dir > /dev/tty
    cd -- $dir
  fi
}
precmd_functions+=(clone_check)

Es bastante simplista. Es un precmdgancho (ejecutado antes de cada solicitud), que comprueba si la última línea de comando se parecía git clone .../somethingo git clone .../something dir, adivina el directorio desde allí y cd en ella.

No funciona si se ha introducido git clone foo; whatevero whatever; git clone fooo git clone --option repo...

Stéphane Chazelas
fuente
+1 Muchas gracias por el código; Lo estoy usando desde hace unos días. Acabo de notar un problema; si cierra el terminal justo después de clonar algún proyecto, la próxima vez que abra un terminal, zsh se queja con dos mensajes de error: CDing into <project>y clone_check:cd:17: no such file or directory: <project>. El error desaparece tan pronto como el último comando que ejecutó antes de cerrar el terminal es diferente $ git clone.
user938271
2

Aquí hay una adaptación de la respuesta anterior para OSX

  • mktemp requiere parámetro adicional
  • git cloneescribe STDERRpor defecto (ver esto )

Función:

function git {
   local tmp=$(mktemp -t git)
   local repo_name

   if [ "$1" = clone ] ; then
     command git "$@" --progress 2>&1 | tee $tmp
     repo_name=$(awk -F\' '/Cloning into/ {print $2}' $tmp)
     rm $tmp
     printf "changing to directory %s\n" "$repo_name"
     cd "$repo_name"
   else
     command git "$@"
   fi
}
davidhq
fuente
1
Hay 7 respuestas que muestran "arriba" la suya. Pero puede cambiar con el tiempo. Dichas referencias no tienen sentido en SE, edite su respuesta e incluya un enlace a la respuesta a la que se refería.
techraf
0

No lo recomendaría, pero podría usar esta frase:

echo 'project' | xargs -I % sh -c 'git clone https://github.com/username/%.git && cd %'

christianbundy
fuente
0

Incluya esto en su shell:

git(){
  case "$1" in clone) git-clone "${@:2}";; *) command git "$@";; esac
}
git-clone(){ 
   local tgt 
   tgt=$(command git clone "$@" 2> >(tee /dev/stderr |head -n1 | cut -d \' -f2)) ||
      return $?
   cd "$tgt"
}

Esto funciona ocultando subrepticiamente el objetivo de clonación del error estándar de git y cdentrando en el objetivo si (y solo si) la clonación fue un éxito.

Acepta todos los argumentos y opciones que hace el regular git clone.

Puede usar el git wrapper y no tener que preocuparse por sus terminaciones, o puede deshacerse del git wrapper y volver a cablear sus git cloneterminaciones git-clone.

PSkocik
fuente