Come cd automaticamente dopo il clone di git?


37

Voglio automaticamente cdla directory creata dal clonecomando dopo aver fatto git clonequalcosa.

Importante: non voglio alterare la sintassi del comando (ad es. Usare un alias / funzione) perché interromperebbe i completamenti zsh che ottengo automaticamente dal Pretzoprogetto.

EDIT : il motivo per cui non ho scelto una risposta come corretta, è perché non è stata data alcuna risposta che soddisfacesse la condizione sopra.

Uso ZSH, ma è accettabile anche una risposta in qualsiasi altra shell.


Mi piace la risposta unix.stackexchange.com/questions/97920/… ma è necessario menzionare per scrivere quella funzione su ~/.bashrcfile (ad esempio) e per me almeno non ha funzionato, ho dovuto ripararlo con la sostituzione del linea:/usr/bin/git "$@" 2>&1 | tee $tmp
lcestari,

Risposte:


19

Crea una funzione:

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

(Funziona per collegamenti sia con che senza ".git")


2
Vorrei continuare a utilizzare a git clonecausa di tutti gli strumenti che avrei dovuto cambiare se non stessi usando git. L'hub è alias come git, oh-my-zsh fornisce il completamento automatico, ecc ...
Daniel K.

3
@Wildeyes gitnon può cambiare la directory di lavoro della tua shell, quindi in entrambi i casi dovrai avvolgerla in un alias / funzione che fa quello che vuoi e lo segue con l'integrato cd. Se vuoi chiamare hubinvece di git, fallo nella funzione. Se si desidera che influisca solo sul clonecomando, verificare l'azione nella funzione. ecc.
frostschutz,

Ho notato che il basename git@github.com:pckujawa/pattern-rec.gitrisultato è pattern-rec.git - quando clonate lasci semplicemente l'estensione .git?
Pat

8
@Pat basenameaccetta anche un argomento suffisso, quindi puoi fare:git clone $1 && cd $(basename $1 .git)
Henrik N

17

git cloneaccetta un ulteriore argomento: la directory da usare. Puoi farlo clonare nella directory di lavoro corrente con git clone URL . Quindi, non è necessario cambiare la directory di lavoro; ci sei già.

Se vuoi davvero che il gitcomando cambi effettivamente la directory di lavoro, puoi cambiarlo in una funzione che chiama il reale gitquando necessario:

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
}

Era esattamente quello che stavo cercando. Dopo aver realizzato che non ci sono hook interni o qualcosa del genere, ho scritto una funzione quasi esatta :)
Daniel K.,

2
@Wildeyes Sì: ha un /tmpvolume che si trova nella RAM, come qualsiasi Linux moderno fa tramite tmpfs. Ad ogni modo, perché dovresti preoccuparti di scrivere sul disco, quando hai appena fatto un clone git, che crea directory e scrive forse centinaia di file sul disco ...
Kaz

1
Probabilmente hai ragione sull'intera faccenda "nvm se scrive su disco", stavo solo cercando di salvare operazioni extra. Grazie mille Kaz.
Daniel K.

3
Stai attento. sì git [flags] command [arguments], così ciecamente chiedere clonein una certa posizione fallirà.
vonbrand,

1
L'aggiunta del percorso "reale" sarebbe di aiuto? Mi piace: git_real_home = which git git () {... $ git_real_home "$ @" | tee $ tmp
aakoch

7

Se si fornisce il nome locale del repository, è davvero facile usare $ _ :

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

Ma se non vuoi riscrivere nomi lunghi, è un po 'brutto ma fattibile con sed:

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

EDIT: Beh, stavo per ringraziare Manav (commento sotto) per il terse

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

ma non funziona in zsh (qualcosa su come zsh fa le espansioni fa sì che non tratti il ​​primo comando come input per !$). Ho dovuto cercare cosa ha !$:tfatto ( Avanzando in Bash Shell | $ {me: -whatever} ). !$prende l'ultima parte del comando precedente e :t"Rimuovi tutti i componenti principali del nome file, lasciando la coda." Buone informazioni, ma vorrei poterlo far funzionare con zsh (ho provato noglobsenza successo).

EDIT: Invece di usare sedo !$:t(che non funziona in zsh, per me comunque), ho trovato altre due opzioni (una adattando https://unix.stackexchange.com/users/5685/frederik-deweerdt la risposta con https : //unix.stackexchange.com/users/129926/ commento di Henry -n):

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

o

git clone git@github.com:npm/npm.git && cd ${${_%%.git*}##*/}

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

Se l'URL del repository termina, .gitè possibile utilizzare !$:t:rper ottenere il nome della cartella.
Michael Stramel,

2

Una soluzione semplice per qualsiasi shell POSIX è specificare la directory in cui clonare esplicitamente (qualsiasi percorso del filesystem) e riutilizzarla:

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

e

cd -

quando hai fatto.


2

Potresti fare qualcosa del tipo:

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)

È abbastanza semplicistico. È un precmdhook (eseguito prima di ogni prompt), che controlla se appariva l'ultima riga di comando git clone .../somethingo git clone .../something dir, indovina la directory da quella e cd in essa.

Non funziona se hai inserito git clone foo; whatevero whatever; git clone fooo git clone --option repo...


+1 Grazie mille per il codice; Lo sto usando da alcuni giorni. Ho appena notato un problema; se chiudi il terminale subito dopo aver clonato un progetto, la prossima volta che apri un terminale, zsh si lamenta con due messaggi di errore: CDing into <project>e clone_check:cd:17: no such file or directory: <project>. L'errore scompare non appena l'ultimo comando eseguito prima della chiusura del terminale è diverso $ git clone.
user938271

2

Ecco un adattamento della risposta sopra per OSX

  • mktemp richiede un parametro aggiuntivo
  • git clonescrive per STDERRimpostazione predefinita (vedi questo )

Funzione:

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
}

1
Ci sono 7 risposte che visualizzano "sopra" le tue. Ma potrebbe cambiare nel tempo. Tali riferimenti non hanno senso su SE, modifica la tua risposta e includi un link alla risposta a cui ti riferivi.
techraf,

0

Io non lo consiglio, ma si poteva utilizzare questo one-liner:

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


0

Includilo nella 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"
}

Questo funziona facendo sparpagliare furtivamente il bersaglio della clonazione dall'errore standard di git e cd'penetrare nel bersaglio se (e solo se) la clonazione ha avuto successo.

Accetta tutti gli argomenti e le opzioni che fa il normale git clone.

O puoi usare il wrapper git e non devi preoccuparti dei tuoi completamenti, oppure puoi sbarazzarti del wrapper git e ricollegare i tuoi git clonecompletamenti git-clone.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.