Comment cd automatiquement après le clone de git?

37

Je souhaite accéder automatiquement cdau répertoire créé par la clonecommande après git clonequelque chose.

Important: je ne souhaite pas modifier la syntaxe de la commande (par exemple, utiliser un alias / une fonction), car cela briserait les compléments zsh que je recevrais automatiquement du Pretzoprojet.

EDIT : La raison pour laquelle je n’ai retenu aucune réponse comme étant correcte, c’est qu’aucune réponse n’a été donnée qui soit conforme à la condition ci-dessus.

J'utilise ZSH, mais une réponse dans un autre shell est également acceptable.

Daniel K.
la source
J'aime la réponse unix.stackexchange.com/questions/97920/… mais il faut mentionner pour écrire cette fonction sur~/.bashrc fichier (par exemple) et pour moi au moins cela ne fonctionnait pas, je devais le corriger en remplaçant le ligne:/usr/bin/git "$@" 2>&1 | tee $tmp
lcestari

Réponses:

19

Créer une fonction:

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

(Fonctionne pour les liens avec et sans ".git")

Frederik Deweerdt
la source
2
J'aimerais continuer à utiliser à git clonecause de tous les outils que je devrais changer si je n'utilisais pas git. Hub est aliasé comme git, oh-my-zsh fournit l'auto-complétion, etc.
Daniel K.
3
@Wildeyes gitne peut pas changer le répertoire de travail de votre shell, vous devrez donc le placer dans un alias / une fonction qui fera ce que vous voulez et qui le suivra avec la commande intégrée cd. Si vous souhaitez appeler hubau lieu de git, faites-le dans la fonction. Si vous souhaitez qu'il affecte uniquement la clonecommande, vérifiez l'action dans la fonction. etc.
frostschutz
J'ai remarqué que les basename [email protected]:pckujawa/pattern-rec.gitrésultats dans pattern-rec.git - ne vous laissez pas l'extension .git lorsque vous clonez?
Pat
8
@Pat basenameprend également un argument de suffixe, vous pouvez donc:git clone $1 && cd $(basename $1 .git)
Henrik N
17

git cloneprend un argument supplémentaire: le répertoire à utiliser. Vous pouvez le faire cloner dans le répertoire de travail actuel avecgit clone URL . Ensuite, il n'est pas nécessaire de changer de répertoire de travail; vous êtes déjà là.

Si vous voulez vraiment que la gitcommande change réellement le répertoire de travail, vous pouvez la changer pour une fonction qui appelle le réel gitsi nécessaire:

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
la source
C'était exactement ce que je cherchais. Après avoir réalisé qu'il n'y avait pas de crochets internes ou quelque chose du genre, j'ai écrit une fonction presque exacte :)
Daniel K.
2
@Wildeyes Oui: avoir un /tmpvolume en RAM, comme tout Linux moderne le fait via tmpfs. Quoi qu'il en soit, pourquoi voudriez-vous écrire sur le disque, alors que vous venez de créer un clone git, qui crée des répertoires et écrit peut-être des centaines de fichiers sur le disque ...
Kaz
1
Vous avez probablement raison en ce qui concerne le problème "nvm si elle écrit sur le disque", je cherchais simplement à enregistrer des opérations supplémentaires. Merci beaucoup Kaz.
Daniel K.
3
Faites attention. il est git [flags] command [arguments], donc demander à l' aveuglette clonedans une certaine position échouera.
vonbrand
1
L'ajout du "vrai" chemin aiderait-il? Comme: git_real_home = which git git () {... $ git_real_home "$ @" | tee $ tmp
aakoch
7

Si vous fournissez le nom local du référentiel, c'est très simple avec $ _ :

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

Mais si vous ne voulez pas retaper des noms longs, c'est un peu moche mais faisable avec sed:

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

EDIT: Eh bien, je vais remercier Manav (commentaire ci-dessous) pour le terse

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

mais cela ne fonctionne pas dans zsh (quelque chose sur la façon dont zsh fait des expansions fait qu'il ne traite pas la première commande comme une entrée !$). Je devais regarder ce !$:tqui se passait ( Avancer dans le shell Bash | $ {me:-importe quoi} ). !$saisit la dernière partie de la commande précédente et :t"supprime tous les composants de nom de fichier principaux en laissant la queue". Bonne information, mais j'aimerais pouvoir le faire fonctionner avec zsh (j'ai essayé noglobsans succès).

EDIT: Au lieu d’utiliser sedor !$:t(qui ne fonctionne pas dans zsh, pour moi en tout cas), j’ai trouvé deux autres options (l’une adaptant https://unix.stackexchange.com/users/5685/frederik-deweerdt avec https : //unix.stackexchange.com/users/129926/ Commentaire dehenrik-n ):

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

ou

git clone git@github.com:npm/npm.git && cd ${${_%%.git*}##*/}
Tapoter
la source
git clone foo/bar && cd !$:t
Manav
Si votre url de dépôt se termine, .gitvous pouvez utiliser !$:t:rpour obtenir le nom du dossier.
Michael Stramel
2

Une solution simple pour tout shell POSIX consiste à spécifier le répertoire à cloner explicitement (n'importe quel chemin de système de fichiers) et à le réutiliser:

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

et

cd -

quand tu as fini.

Ponceuse
la source
2

Vous pourriez faire quelque chose comme:

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)

C'est assez simpliste. C'est un precmdcrochet (exécuté avant chaque invite), qui vérifie si la dernière ligne de commande ressemble à git clone .../somethingou git clone .../something dir, devine le répertoire à partir de celui-ci et y est inséré.

Cela ne fonctionne pas si vous entrez git clone foo; whateverou whatever; git clone fooou git clone --option repo...

Stéphane Chazelas
la source
+1 Merci beaucoup pour le code; Je l'utilise depuis quelques jours. Je viens de remarquer un problème; si vous fermez le terminal juste après le clonage d'un projet, zsh se plaint lors de la prochaine ouverture d'un terminal avec deux messages d'erreur: CDing into <project>et clone_check:cd:17: no such file or directory: <project>. L'erreur disparaît dès que la dernière commande exécutée avant la fermeture du terminal est différente de $ git clone.
user938271
2

Voici une adaptation de la réponse ci-dessus pour OSX

  • mktemp nécessite un paramètre supplémentaire
  • git cloneécrit STDERRpar défaut (voir ceci )

Une fonction:

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
la source
1
Il y a 7 réponses qui affichent "dessus" la vôtre. Mais cela peut changer avec le temps. De telles références n'ont aucun sens sur SE. Veuillez modifier votre réponse et inclure un lien vers la réponse à laquelle vous faites référence.
Techraf
0

Je ne le recommanderais pas, mais vous pouvez utiliser ce one-liner:

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

christianbundy
la source
0

Incluez ceci dans votre 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"
}

Cela fonctionne en éliminant subrepticement la cible de clonage de l'erreur standard de git et cd l'incroyant dans la cible si (et seulement si) le clonage a été un succès.

Il accepte tous les arguments et options proposés par le standard git clone.

Soit vous pouvez utiliser le wrapper git sans avoir à vous soucier de vos achèvements, soit vous pouvez vous en débarrasser et rewire vos git cloneachèvements git-clone.

PSkocik
la source