1014 Stimmen

Gibt es eine Möglichkeit, das git Root-Verzeichnis mit einem einzigen Befehl zu erhalten?

Mercurial hat eine Möglichkeit, das Root-Verzeichnis (das .hg enthält) über

hg root

Gibt es etwas Äquivalentes in Git, um das Verzeichnis zu erhalten, das das .git-Verzeichnis enthält?

28voto

Karl Punkte 678

Wenn Sie sich bereits in der obersten Ebene oder nicht in einem Git-Repository befinden cd $(git rev-parse --show-cdup) wird Sie nach Hause bringen (nur cd). cd ./$(git rev-parse --show-cdup) ist eine Möglichkeit, dies zu beheben.

22voto

Tom Hale Punkte 32065

Kurze Lösungen, die mit Untermodulen, in Hooks und innerhalb der .git Verzeichnis

Hier ist die kurze Antwort, die sich die meisten wünschen werden:

r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"

Dies funktioniert überall in einem Git-Arbeitsbaum (auch innerhalb der .git Verzeichnis), geht aber davon aus, dass das/die Repository-Verzeichnis(e) .git (dies ist die Standardeinstellung). Bei Untermodulen geht dies an das Stammverzeichnis des am weitesten außen liegenden Repositorys.

Wenn Sie zur Wurzel des aktuellen Submoduls gelangen wollen, verwenden Sie:

echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))

Zur einfachen Ausführung eines Befehls in Ihrem Submodul Root, unter [alias] in Ihrem .gitconfig , hinzufügen:

sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"

Dies ermöglicht Ihnen, auf einfache Weise Dinge zu tun wie git sh ag <string>

Robuste Lösung, die unterschiedlich benannte oder externe .git o $GIT_DIR Verzeichnisse.

Beachten Sie, dass $GIT_DIR kann irgendwo nach außen zeigen (und nicht als .git ), weshalb eine weitere Überprüfung erforderlich ist.

Legen Sie dies in Ihr .bashrc :

# Print the name of the git working tree's root directory
function git_root() {
  local root first_commit
  # git displays its own error if not in a repository
  root=$(git rev-parse --show-toplevel) || return
  if [[ -n $root ]]; then
    echo $root
    return
  elif [[ $(git rev-parse --is-inside-git-dir) = true ]]; then
    # We're inside the .git directory
    # Store the commit id of the first commit to compare later
    # It's possible that $GIT_DIR points somewhere not inside the repo
    first_commit=$(git rev-list --parents HEAD | tail -1) ||
      echo "$0: Can't get initial commit" 2>&1 && false && return
    root=$(git rev-parse --git-dir)/.. &&
      # subshell so we don't change the user's working directory
    ( cd "$root" &&
      if [[ $(git rev-list --parents HEAD | tail -1) = $first_commit ]]; then
        pwd
      else
        echo "$FUNCNAME: git directory is not inside its repository" 2>&1
        false
      fi
    )
  else
    echo "$FUNCNAME: Can't determine repository root" 2>&1
    false
  fi
}

# Change working directory to git repository root
function cd_git_root() {
  local root
  root=$(git_root) || return 1  # git_root will print any errors
  cd "$root"
}

Führen Sie es durch Eingabe von git_root (nachdem Sie Ihre Shell neu gestartet haben: exec bash )

18voto

Chris Johnsen Punkte 199970

Wie bereits erwähnt, besteht der Kern der Lösung in der Verwendung von git rev-parse --show-cdup . Allerdings gibt es ein paar Randfälle, die zu berücksichtigen sind:

  1. Wenn cwd bereits die Wurzel des Arbeitsbaums ist, gibt der Befehl eine leere Zeichenkette aus.
    Eigentlich wird eine Leerzeile erzeugt, aber die Befehlssubstitution entfernt den Zeilenumbruch am Ende. Das Endergebnis ist eine leere Zeichenkette.

    Die meisten Antworten schlagen vor, die Ausgabe mit ./ so dass eine leere Ausgabe zu "./" bevor sie an cd .

  2. Wenn GIT_WORK_TREE auf einen Ort gesetzt ist, der nicht der Elternteil von cwd ist, kann die Ausgabe ein absoluter Pfadname sein.

    Vorangestellte ./ in dieser Situation falsch ist. Wenn ein ./ einem absoluten Pfad vorangestellt wird, wird er zu einem relativen Pfad (und sie verweisen nur dann auf denselben Ort, wenn cwd das Wurzelverzeichnis des Systems ist).

  3. Die Ausgabe kann Leerzeichen enthalten.

    Dies gilt eigentlich nur für den zweiten Fall, aber es gibt eine einfache Lösung: Verwenden Sie doppelte Anführungszeichen um die Befehlssubstitution (und alle nachfolgenden Verwendungen des Wertes).

Wie bereits in anderen Antworten erwähnt, können wir Folgendes tun cd "./$(git rev-parse --show-cdup)" , aber das bricht im zweiten Randfall (und im dritten Randfall, wenn wir die Anführungszeichen weglassen).

Viele Muscheln behandeln cd "" als ein No-op, so dass wir für diese Muscheln Folgendes tun können cd "$(git rev-parse --show-cdup)" (die doppelten Anführungszeichen schützen im ersten Fall die leere Zeichenkette als Argument und im dritten Fall die Leerzeichen). POSIX sagt, dass das Ergebnis von cd "" ist nicht spezifiziert, daher ist es vielleicht am besten, diese Annahme zu vermeiden.

Eine Lösung, die in allen oben genannten Fällen funktioniert, erfordert eine Art von Test. Explizit durchgeführt, könnte er so aussehen:

cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"

Nein cd wird für den ersten Grenzfall durchgeführt.

Wenn es akzeptabel ist, die cd . für den ersten Randfall, dann kann die Bedingung in der Erweiterung des Parameters erfolgen:

cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"

17voto

Nick Volynkin Punkte 12712

Nur für den Fall, dass Sie diesen Pfad an Git selbst weitergeben, verwenden Sie :/

# this adds the whole working tree from any directory in the repo
git add :/

# and is equal to
git add $(git rev-parse --show-toplevel)

17voto

Emil Sit Punkte 21922

Um den absoluten Pfad des aktuellen Git-Root-Verzeichnisses zu berechnen, z. B. zur Verwendung in einem Shell-Skript, verwenden Sie diese Kombination aus readlink und git rev-parse:

gitroot=$(readlink -f ./$(git rev-parse --show-cdup))

git-rev-parse --show-cdup gibt Ihnen die richtige Anzahl von ".. "s, um von Ihrem cwd zum Stammverzeichnis zu gelangen, oder die leere Zeichenfolge, wenn Sie sich im Stammverzeichnis befinden. Stellen Sie dann "./" voran, um den Fall der leeren Zeichenkette zu behandeln und verwenden Sie readlink -f in einen vollständigen Pfad zu übersetzen.

Sie könnten auch eine git-root Befehl in Ihrem PATH als Shell-Skript, um diese Technik anzuwenden:

cat > ~/bin/git-root << EOF
#!/bin/sh -e
cdup=$(git rev-parse --show-cdup)
exec readlink -f ./$cdup
EOF
chmod 755 ~/bin/git-root

(Das obige Skript kann in ein Terminal eingefügt werden, um git-Root zu erstellen und Ausführungsbits zu setzen; das eigentliche Skript befindet sich in den Zeilen 2, 3 und 4).

Und dann könnten Sie die git root um die Wurzel des aktuellen Baums zu erhalten. Beachten Sie, dass Sie im Shell-Skript "-e" verwenden, um die Shell zum Beenden zu veranlassen, wenn rev-parse fehlschlägt, so dass Sie den Exit-Status und die Fehlermeldung korrekt erhalten können, wenn Sie sich nicht in einem Git-Verzeichnis befinden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X