Wie automatisch nach Git-Klon cd?

36

Ich möchte automatisch cdin das vom cloneBefehl erstellte Verzeichnis, nachdem ich git cloneetwas getan habe.

Wichtig: Ich möchte die Syntax für den Befehl nicht ändern (z. B. einen Alias ​​/ eine Funktion verwenden), da dies die zsh-Vervollständigungen stören würde, die ich automatisch aus dem PretzoProjekt erhalte .

BEARBEITEN : Der Grund, warum ich keine Antwort als richtig ausgewählt habe, ist, dass keine Antwort gegeben wurde, die der obigen Bedingung entsprach.

Ich benutze ZSH, aber eine Antwort in einer anderen Shell ist auch akzeptabel.

Daniel K.
quelle
Ich mag die Antwort unix.stackexchange.com/questions/97920/… aber es muss erwähnt werden, um diese Funktion in eine ~/.bashrcDatei zu schreiben (zum Beispiel) und für mich hat es zumindest nicht funktioniert, ich musste es mit dem Ersetzen der beheben line:/usr/bin/git "$@" 2>&1 | tee $tmp
lcestari

Antworten:

19

Erstellen Sie eine Funktion:

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

(Funktioniert für Links mit und ohne ".git")

Frederik Deweerdt
quelle
2
Ich möchte git clonewegen all der Tools, die ich ändern müsste, wenn ich sie nicht verwenden würde, weiterverwenden git. Hub ist als git aliasiert, oh-my-zsh bietet Auto-Vervollständigung, etc ...
Daniel K.
3
@Wildeyes gitkann das Arbeitsverzeichnis Ihrer Shell nicht ändern, so oder so müssen Sie es in einen Alias ​​/ eine Funktion einbinden, die genau das tut, was Sie wollen, und die eingebaute Funktion verwendet cd. Wenn Sie hubstatt anrufen möchten git, tun Sie dies in der Funktion. Wenn Sie möchten, dass es sich nur auf den cloneBefehl auswirkt , überprüfen Sie die Aktion in der Funktion. etc.
Frostschutz
Mir ist aufgefallen, dass basename [email protected]:pckujawa/pattern-rec.gitsich pattern-rec.git ergibt - lassen Sie die .git-Erweiterung einfach weg, wenn Sie klonen?
Pat
8
@Pat verwendet basenameauch ein Suffix-Argument, damit Sie Folgendes tun können:git clone $1 && cd $(basename $1 .git)
Henrik N,
17

git clonebenötigt ein zusätzliches Argument: das zu verwendende Verzeichnis. Sie können es mit in das aktuelle Arbeitsverzeichnis klonen. git clone URL . Dann müssen Sie das Arbeitsverzeichnis nicht ändern. du bist schon da.

Wenn Sie wirklich möchten, dass der gitBefehl das Arbeitsverzeichnis ändert, können Sie ihn in eine Funktion ändern, die gitbei Bedarf den Real aufruft :

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
quelle
Genau das habe ich gesucht. Nachdem ich feststellte, dass es keine internen Hooks oder ähnliches gibt, schrieb ich eine fast exakte Funktion :)
Daniel K.
2
@Wildeyes Ja: Haben Sie ein /tmpVolume, das sich im RAM befindet, wie jedes moderne Linux über tmpfs. Wie auch immer, warum sollte es Ihnen etwas ausmachen, auf die Festplatte zu schreiben, wenn Sie gerade einen Git-Klon durchgeführt haben, der Verzeichnisse erstellt und vielleicht Hunderte von Dateien auf die Festplatte schreibt ...
Kaz
1
Sie haben wahrscheinlich Recht mit der ganzen Sache "nvm, wenn es auf Festplatte schreibt", ich habe nur versucht, zusätzliche Operationen zu sparen. Vielen Dank, Kaz.
Daniel K.
3
Achtung. es ist git [flags] command [arguments]so blind gefragt clonein bestimmter position wird scheitern.
Vonbrand
1
Würde das Hinzufügen des "echten" Pfades helfen? Beispiel: git_real_home = which git git () {... $ git_real_home "$ @" | tee $ tmp
aakoch
7

Wenn Sie den lokalen Namen des Repos angeben, ist die Verwendung von $ _ ganz einfach :

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

Aber wenn Sie keine langen Namen erneut eingeben möchten, ist es ein wenig hässlich, aber mit sed machbar:

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

EDIT: Nun, ich wollte Manav (Kommentar unten) für die knappe danken

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

Aber es funktioniert nicht in zsh (etwas darüber, wie zsh Erweiterungen ausführt, bewirkt, dass es den ersten Befehl nicht als Eingabe für behandelt !$). Ich musste nachsehen, was passiert ist!$:t ( Fortschreiten in der Bash-Shell | $ {me: -whatever} ). !$Ergreift den letzten Teil des vorherigen Befehls und entfernt :talle führenden Dateinamenskomponenten, wobei der Schwanz übrig bleibt. Gute Informationen, aber ich wünschte, ich könnte sie mit zsh zum Laufen bringen (ich habe es noglobohne Erfolg versucht ).

BEARBEITEN: Anstatt sedoder zu verwenden !$:t(was in zsh sowieso nicht funktioniert), habe ich zwei andere Optionen gefunden (eine, die die Antwort von https://unix.stackexchange.com/users/5685/frederik-deweerdt mit https anpasst) : //unix.stackexchange.com/users/129926/henrik-ns Kommentar):

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

oder

git clone git@github.com:npm/npm.git && cd ${${_%%.git*}##*/}
Klopfen
quelle
git clone foo/bar && cd !$:t
Manav
Wenn Ihre Repo-URL auf endet .git, können Sie verwenden !$:t:r, um den Ordnernamen abzurufen.
Michael Stramel
2

Eine einfache Lösung für jede POSIX-Shell besteht darin, das Verzeichnis anzugeben, in das explizit geklont werden soll (beliebiger Dateisystempfad) und es erneut zu verwenden:

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

und

cd -

wenn du fertig bist.

Sander
quelle
2

Sie könnten etwas tun wie:

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 ist ziemlich simpel. Es ist ein precmdHook (der vor jeder Eingabeaufforderung ausgeführt wird), der prüft, ob die letzte Befehlszeile so aussah git clone .../somethingoder git clone .../something dir, errate das Verzeichnis von dort und cd hinein.

Es funktioniert nicht, wenn Sie eingegeben haben git clone foo; whateveroder whatever; git clone foooder git clone --option repo...

Stéphane Chazelas
quelle
+1 Vielen Dank für den Code; Ich benutze es seit ein paar Tagen. Ich habe gerade ein Problem bemerkt; Wenn Sie das Terminal direkt nach dem Klonen eines Projekts schließen und das nächste Mal ein Terminal öffnen, beklagt sich zsh mit zwei Fehlermeldungen: CDing into <project>und clone_check:cd:17: no such file or directory: <project>. Der Fehler verschwindet, sobald sich der letzte Befehl, den Sie vor dem Schließen des Terminals ausgeführt haben, von unterscheidet $ git clone.
user938271
2

Hier ist eine Anpassung der obigen Antwort für OSX

  • mktemp erfordert zusätzliche Parameter
  • git cloneschreibt STDERRstandardmäßig an (siehe dies )

Funktion:

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
quelle
1
Es gibt 7 Antworten, die "über" Ihren angezeigt werden. Aber es kann sich im Laufe der Zeit ändern. Solche Verweise machen in SE keinen Sinn. Bitte bearbeiten Sie Ihre Antwort und fügen Sie einen Link zu der Antwort hinzu, auf die Sie sich bezogen haben.
Techraf
0

Ich würde es nicht empfehlen, aber Sie könnten diesen Einzeiler verwenden:

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

christianbundy
quelle
0

Fügen Sie dies in Ihre Shell ein:

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

Dies funktioniert, indem das Klon-Ziel heimlich von seinem Standardfehler befreit wird und cdin das Ziel eingedrungen wird, wenn (und nur dann) das Klonen erfolgreich war.

Es akzeptiert alle Argumente und Optionen, die der Reguläre git cloneausführt.

Entweder können Sie den Git-Wrapper verwenden und müssen sich nicht um Ihre Fertigstellungen kümmern, oder Sie können den Git-Wrapper loswerden und Ihre git cloneFertigstellungen neu verkabeln git-clone.

PSkocik
quelle