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?
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?
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
)
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:
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
.
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).
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:-.}"
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 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.