Gibt es eine Möglichkeit, das Git-Stammverzeichnis in einem Befehl abzurufen?


669

Mercurial bietet eine Möglichkeit, das Stammverzeichnis (das .hg enthält) über zu drucken

hg root

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


Gutes Drehbuch Emil. Ich stelle das Skript online zur Verfügung und habe die Möglichkeit zugelassen, eine Datei / ein Verzeichnis als Argument hinzuzufügen. github.com/Dieterbe/git-scripts/commit/…
Dieter_be

Auch für alle Neugierigen oder Suchenden bzr rootwurde viel in Bazaar
Kristopher Ives

Bitte beachten Sie 'gcd': Git-Aware 'cd' Relativ zum Repository- Stammverzeichnis mit automatischer Vervollständigung unter jeetworks.org/node/52 .
Micha Wiedenmann


1
@MichaWiedenmann: Der Link ist tot.
d33tah

Antworten:


1111

Ja:

git rev-parse --show-toplevel

Wenn Sie den Git-Befehl direkter replizieren möchten, können Sie einen Alias erstellen :

git config --global alias.root 'rev-parse --show-toplevel'

und jetzt git rootwird genauso funktionieren wie hg root.


Hinweis : In einem Submodul wird das Stammverzeichnis des Submoduls und nicht das übergeordnete Repository angezeigt . Wenn Sie Git> = 2.13 oder höher verwenden, können Submodule das Stammverzeichnis des Superprojekts auf eine Weise anzeigen. Wenn dein Git älter ist, siehe diese andere Antwort.


147
Ich definiere immer, git config --global alias.exec '!exec 'damit ich Dinge wie tun kann git exec make. Dies funktioniert, weil Shell-Aliase immer im Verzeichnis der obersten Ebene ausgeführt werden.
Daniel Brockman

8
Das hg rootmacht es. Es druckt das Verzeichnis der obersten Ebene Ihres ausgecheckten Repositorys aus. Es schaltet Sie nicht darauf um (und es konnte dies auch nicht tun, da das gesamte Konzept des aktuellen Verzeichnisses und Ihrer Shell zusammenwirkt).
Omnifarious

14
Kleine Einschränkung bei dieser Lösung - sie folgt allen symbolischen Verknüpfungen. Wenn Sie sich in befinden ~/my.proj/foo/barund mit diesem verbunden ~/my.projsind, werden Sie mit ~/src/my.projdem obigen Befehl zu weitergeleitet ~/src/my.proj. Könnte ein Problem sein, wenn alles, was Sie danach tun möchten, nicht baumunabhängig ist.
Franci Penov

3
Wie kann ich das aus einem Git-Hook heraus verwenden? Insbesondere mache ich einen Post-Merge-Hook und muss das eigentliche Stammverzeichnis des lokalen Git-Repos abrufen.
Derek

12
Diese Lösung (und viele andere auf dieser Seite, die ich ausprobiert habe) funktionieren nicht in einem Git-Hook. Genauer gesagt funktioniert es nicht, wenn Sie sich im Projektverzeichnis befinden .git.
Dennis

97

Die manSeite für git-config(unter Alias ) sagt:

Wenn der Alias-Erweiterung ein Ausrufezeichen vorangestellt wird, wird sie als Shell-Befehl behandelt. [...] Beachten Sie, dass Shell-Befehle aus dem Verzeichnis der obersten Ebene eines Repositorys ausgeführt werden, das nicht unbedingt das aktuelle Verzeichnis sein muss.

Unter UNIX können Sie also Folgendes tun:

git config --global --add alias.root '!pwd'

2
Wenn Sie also einen "git root" -Befehl haben, wie können Sie diesen in einen Alias ​​einfügen? Wenn ich es in meine .zshrceinfüge und `alias cg =" cd $ (git root) "definiere, wird der $ () - Teil zur Quellzeit ausgewertet und zeigt immer auf ~ / dotfiles, da sich dort mein zshrc befindet .
Zelk

2
@cormacrelf Du legst es nicht in einen Shell-Alias. Sie können es in eine Shell-Funktion oder ein Skript einfügen.
Conrad Meyer

4
@cormacrelf Setzen Sie es in einfache Anführungszeichen anstatt in doppelte Anführungszeichen, dann wird es nicht zur Definitionszeit, sondern zur Laufzeit erweitert.
Clacke

3
@ Mechanicalnail Wirklich? Was würden Sie also von einem externen Repo erwarten?
Alois Mahdal

1
@AloisMahdal eigentlich für mich scheitert es nicht außerhalb eines Repos, es meldet einfach das cwd.
Justinpitts

90

Wurde --show-toplevelerst kürzlich hinzugefügt git rev-parseoder warum erwähnt es niemand?

Von der git rev-parseManpage:

   --show-toplevel
       Show the absolute path of the top-level directory.

1
Vielen Dank für den Hinweis; Ohne Ihre Hilfe wäre es für mich schwer zu erraten, git-rev-parseda der Name darauf hindeutet, dass es um die Verarbeitung von Revisionsspezifikationen geht. Übrigens würde ich mich über eine git --work-treeähnliche Arbeit freuen git --exec-path[=<path>]: "Wenn kein Pfad angegeben wird, druckt git die aktuelle Einstellung"; Zumindest, IMO, wäre es ein logischer Ort, nach einer solchen Funktion zu suchen.
imz - Ivan Zakharyaschev

4
Insbesondere können Sie root = rev-parse --show-toplevelin Ihrer gitconfig einen Alias erstellen.
Mechanische Schnecke

2
Mit anderen Worten, Sie können git config --global alias.root "rev-parse --show-toplevel"und werden dann git rootin der Lage sein, die Arbeit zu erledigen
Unpolarität

@ RyanTheLeach git rev-parse --show-toplevelfunktioniert, als ich es in einem Submodul ausprobiert habe. Es gibt das Root-Verzeichnis des Git-Submoduls aus. Was druckt es für Sie?
wisbucky

2
Ich war verwirrt, warum diese Antwort die oberste Antwort duplizierte. Es stellt sich heraus, dass die Top-Antwort von --show-cdupbis --show-top-levelim Februar 2011 bearbeitet wurde (nachdem diese Antwort eingereicht wurde).
wisbucky

54

Wie wäre es mit " git rev-parse --git-dir"?

F:\prog\git\test\copyMerge\dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git

Die --git-dirOption scheint zu funktionieren.

Von der git rev-parse-Handbuchseite :

--git-dir

    Show $GIT_DIR if defined else show the path to the .git directory.

Sie können es in diesem git setup-shSkript in Aktion sehen .

Wenn Sie sich in einem Submodul-Ordner mit Git> = 2.13 befinden , verwenden Sie :

git rev-parse --show-superproject-working-tree

Wenn Sie verwenden git rev-parse --show-toplevel, stellen Sie sicher, dass es mit Git 2.25+ (Q1 2020) ist .


3
Oh, warte, das war knapp, aber es bekommt das eigentliche Git-Verzeichnis, nicht die Basis des Git-Repo. Das .git-Verzeichnis könnte sich auch an einer anderen Stelle befinden, sodass ich nicht genau danach gesucht habe.
Wojo

2
Richtig, ich sehe jetzt, wonach Sie tatsächlich gesucht haben. --show-cdup ist dann besser geeignet. Ich lasse meine Antwort, um den Unterschied zwischen den beiden Optionen zu veranschaulichen.
VonC

2
Es scheint auch, dass dieser Befehl einen relativen Pfad angibt, .gitwenn Sie sich bereits im Stammverzeichnis befinden. (Zumindest auf msysgit.)
Blair Holloway

2
+1, dies ist die einzige Antwort, die die ursprüngliche Frage "Holen Sie sich das Verzeichnis, das das .git-Verzeichnis enthält?" Beantwortet. Es ist amüsant zu sehen, dass das OP selbst erwähnt, dass sich das .git-Verzeichnis möglicherweise an einer anderen Stelle befindet.
FabienAndre

1
Dies ist die einzige Lösung, die unter Windows funktioniert UND bei Verwendung von Git-Submodulen (z. B. c: \ repositories \ myrepo \ .git \ modules \ mysubmodule) ein analysierbares Ergebnis liefert. Dies macht es zur robustesten Lösung, insbesondere in einem wiederverwendbaren Skript.
Chriskelly

36

Um hier eine einfache Antwort zu schreiben, damit wir sie verwenden können

git root

Um den Job zu erledigen, konfigurieren Sie einfach Ihr Git mit

git config --global alias.root "rev-parse --show-toplevel"

und dann möchten Sie vielleicht Folgendes zu Ihrem hinzufügen ~/.bashrc:

alias cdroot='cd $(git root)'

so dass Sie einfach verwenden können cdroot, um an die Spitze Ihres Repos zu gelangen.


Sehr schön! Letztendlich praktisch!
Scravy

Eine tolle Antwort, danke!
AVarf

26

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


7
Eine andere Möglichkeit ist, es zu zitieren : cd "$(git rev-parse --show-cdup)". Dies funktioniert, weil cd ""Sie nirgendwohin und nicht zurück gelangen $HOME. Und es wird empfohlen, trotzdem $ () -Aufrufe in Anführungszeichen zu setzen, falls sie etwas mit Leerzeichen ausgeben (in diesem Fall jedoch nicht, dass dieser Befehl dies tut).
ctrueden

Diese Antwort funktioniert auch dann gut, wenn Sie das Verzeichnis über einen Symlink in Ihr Git-Repo geändert haben . Einige der anderen Beispiele funktionieren nicht wie erwartet, wenn sich Ihr Git-Repo unter einem Symlink befindet, da sie das Stammverzeichnis des Git relativ zu Bashs nicht auflösen $PWD. In diesem Beispiel wird die Wurzel von git relativ zu $PWDstatt aufgelöst realpath $PWD.
Damien Ó Ceallaigh

16

Verwenden Sie diese Kombination aus readlink und git rev-parse, um den absoluten Pfad des aktuellen Git-Stammverzeichnisses zu berechnen, beispielsweise zur Verwendung in einem Shell-Skript:

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

git-rev-parse --show-cdupgibt Ihnen die richtige Anzahl von "..", um von Ihrem cwd zur Wurzel zu gelangen, oder die leere Zeichenfolge, wenn Sie sich an der Wurzel befinden. Stellen Sie dann "./" voran, um den leeren Zeichenfolgenfall zu behandeln, und verwenden Sie ihn readlink -f, um in einen vollständigen Pfad zu übersetzen.

Sie können auch eine erstellen git-root in Ihrem PATH Befehl 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 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 rennen git root, um die Wurzel Ihres aktuellen Baums zu erhalten. Beachten Sie, dass Sie im Shell-Skript "-e" verwenden, um das Beenden der Shell zu veranlassen, wenn die Rev-Analyse fehlschlägt, damit Sie den Exit-Status und die Fehlermeldung ordnungsgemäß abrufen können, wenn Sie sich nicht in einem Git-Verzeichnis befinden.


2
Ihre Beispiele werden unterbrochen, wenn der git-Verzeichnispfad "root" Leerzeichen enthält. Verwenden Sie immer "$(git rev-parse ...)"anstelle von Hacks wie ./$(git rev-parse ...).
Mikko Rantalainen

readlink -ffunktioniert bei BSD nicht gleich. In diesem SO finden Sie Problemumgehungen. Die Python-Antwort wird wahrscheinlich funktionieren, ohne etwas zu installieren : python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$(git rev-parse --show-cdup)".
Bluu

16

Wie andere angemerkt haben, ist der Kern der Lösung die Verwendung git rev-parse --show-cdup. Es gibt jedoch einige Randfälle, die behandelt werden müssen:

  1. Wenn das cwd bereits die Wurzel des Arbeitsbaums ist, gibt der Befehl eine leere Zeichenfolge aus.
    Tatsächlich wird eine leere Zeile erzeugt, aber die Befehlsersetzung entfernt den Zeilenumbruch. Das Endergebnis ist eine leere Zeichenfolge.

    In den meisten Antworten wird empfohlen, der Ausgabe ./ein Präfix voranzustellen, damit eine leere Ausgabe entsteht, "./"bevor sie eingespeist wird cd.

  2. Wenn GIT_WORK_TREE auf einen Speicherort festgelegt ist, der nicht das übergeordnete Element des CWD ist, kann die Ausgabe ein absoluter Pfadname sein.

    Das Voranstellen ./ist in dieser Situation falsch. Wenn a ./einem absoluten Pfad vorangestellt wird, wird es zu einem relativen Pfad (und sie beziehen sich nur auf denselben Speicherort, wenn cwd das Stammverzeichnis des Systems ist).

  3. Die Ausgabe kann Leerzeichen enthalten.

    Dies gilt wirklich nur im zweiten Fall, hat aber eine einfache Lösung: Verwenden Sie doppelte Anführungszeichen um die Befehlssubstitution (und alle nachfolgenden Verwendungen des Werts).

Wie andere Antworten angemerkt haben, können wir dies tun cd "./$(git rev-parse --show-cdup)", aber dies bricht im Fall der zweiten Kante (und im Fall der dritten Kante, wenn wir die doppelten Anführungszeichen weglassen).

Viele Shells werden cd ""als No-Op behandelt, sodass wir dies für diese Shells tun können cd "$(git rev-parse --show-cdup)"(die doppelten Anführungszeichen schützen die leere Zeichenfolge als Argument im Fall der ersten Kante und bewahren Leerzeichen im Fall der dritten Kante). Laut POSIX ist das Ergebnis von cd ""nicht spezifiziert, daher ist es möglicherweise am besten, diese Annahme zu vermeiden.

Eine Lösung, die in allen oben genannten Fällen funktioniert, erfordert einen Test. Explizit gemacht, könnte es so aussehen:

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

cdFür den Fall der ersten Kante wird Nein ausgeführt .

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

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

Warum verwenden Sie nicht einfach "git config --global --add alias.root '! Pwd'" und einen Shell-Alias ​​gitroot = 'cd git root', den die obige Antwort verwendet?
Jason Axelson

1
Die Verwendung eines Alias ​​ist möglicherweise nicht möglich, z. B. wenn Sie ein Skript erstellen möchten und sich nicht auf einen benutzerdefinierten Alias ​​verlassen können.
Blueyed

1
Submodule sind ein weiterer Eckfall.
Ryan The Leach

14

Nur für den Fall, dass Sie diesen Pfad dem Git selbst zuführen, 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)

12

Kurze Lösungen, die mit Submodulen, in Hooks und innerhalb des .gitVerzeichnisses funktionieren

Hier ist die kurze Antwort, die die meisten wollen:

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

Dies funktioniert überall in einem Git-Arbeitsbaum (einschließlich innerhalb des .gitVerzeichnisses), setzt jedoch voraus, dass Repository-Verzeichnisse aufgerufen werden .git(dies ist die Standardeinstellung). Bei Submodulen geht dies zum Stammverzeichnis des äußersten Repositorys.

Wenn Sie zum Stammverzeichnis des aktuellen Submoduls gelangen möchten, verwenden Sie:

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

Um einen Befehl in Ihrem Submodul-Stammverzeichnis einfach auszuführen , fügen Sie unter [alias]in Folgendes .gitconfighinzu:

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

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

Robuste Lösung, die unterschiedlich benannte oder externe .gitoder $GIT_DIRVerzeichnisse unterstützt.

Beachten Sie, dass dies $GIT_DIRmöglicherweise auf eine externe Stelle verweist (und nicht aufgerufen werden kann .git), weshalb weitere Überprüfungen erforderlich sind.

Setzen Sie dies in Ihre .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 git_root(nach der Shell neu zu starten: exec bash)


Dieser Code wird bei der Robust-Bash-Funktion überprüft , um das Stammverzeichnis eines Git-Repositorys zu finden . Suchen Sie dort nach Updates.
Tom Hale

Nett. Komplexer als das, was ich vor 7 Jahren vorgeschlagen habe ( stackoverflow.com/a/958125/6309 ), aber immer noch +1
VonC

1
Die kürzere Lösung in dieser Richtung ist: (root=$(git rev-parse --git-dir)/ && cd ${root%%/.git/*} && git rev-parse && pwd)Dies gilt jedoch nicht für externe $GIT_DIRs, die einen anderen Namen haben als.git
Tom Hale

Ich frage mich, ob dies die mehreren Arbeitsbäume berücksichtigt, die jetzt in Git 2.5+ ( stackoverflow.com/a/30185564/6309 ) möglich sind
VonC

Ihr Kommentar-Link zu "Robuste Bash-Funktion, um die Wurzel zu finden ..." gibt jetzt eine 404.
ErikE

8

Um die "git config" zu ändern, antworten Sie nur ein wenig:

git config --global --add alias.root '!pwd -P'

und den Weg bereinigen lassen. Sehr schön.


7

Wenn Sie nach einem guten Alias ​​suchen, um dies zu tun, und nicht in die Luft jagen, cdwenn Sie nicht in einem Git-Verzeichnis sind:

alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'


6

Dieser Shell-Alias ​​funktioniert unabhängig davon, ob Sie sich in einem Git-Unterverzeichnis oder auf der obersten Ebene befinden:

alias gr='[ ! -z `git rev-parse --show-toplevel` ] && cd `git rev-parse --show-toplevel || pwd`'

aktualisiert, um moderne Syntax anstelle von Backticks zu verwenden:

alias gr='[ ! -z $(git rev-parse --show-toplevel) ] && cd $(git rev-parse --show-toplevel || pwd)'

5
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'

Alles andere schlägt irgendwann fehl, entweder im Home-Verzeichnis oder einfach nur kläglich. Dies ist der schnellste und kürzeste Weg, um zum GIT_DIR zurückzukehren.


Es scheint, als wäre 'git rev-parse --git-dir' die sauberste Lösung.
Stabledog

3
Dies schlägt fehl, wenn $GIT_DIRes mit .git-Files und vom Arbeitsbaum getrennt wird gitdir: SOMEPATH. Folglich schlägt dies auch für Submodule fehl, die $GIT_DIRenthalten .git/modules/SUBMODULEPATH.
Tino

5

Hier ist ein Skript, das ich geschrieben habe und das beide Fälle behandelt: 1) Repository mit einem Arbeitsbereich, 2) nacktes Repository.

https://gist.github.com/jdsumsion/6282953

git-root (ausführbare Datei in Ihrem Pfad):

#!/bin/bash
GIT_DIR=`git rev-parse --git-dir` &&
(
  if [ `basename $GIT_DIR` = ".git" ]; then
    # handle normal git repos (with a .git dir)
    cd $GIT_DIR/..
  else
    # handle bare git repos (the repo IS a xxx.git dir)
    cd $GIT_DIR
  fi
  pwd
)

Hoffentlich ist das hilfreich.


1
Keith, danke für den Vorschlag, ich habe das Skript beigefügt.
Jdsumsion

Ich habe die Top-Antwort tatsächlich positiv bewertet, weil mir klar wurde, dass die git execIdee in nicht nackten Repositories hilfreicher ist. Dieses Skript in meiner Antwort behandelt jedoch den bloßen und den nicht bloßen Fall korrekt, was für jemanden von Nutzen sein könnte. Daher lasse ich diese Antwort hier.
Jdsumsion

1
Dies schlägt jedoch innerhalb von git submodules fehl, wo so $GIT_DIRetwas enthalten ist /.git/modules/SUBMODULE. Sie gehen auch davon aus, dass das .gitVerzeichnis im nicht bloßen Fall Teil des Arbeitsbaums ist.
Tino

4
$ git config alias.root '!pwd'
# then you have:
$ git root

Dieser Alias ​​schlägt als global fehl. Verwenden Sie stattdessen (in ~ / .gitconfig): [alias] findroot = "!f () { [[ -d ".git" ]] && echo "Found git in [pwd ]" && exit 0; cd .. && echo "IN pwd" && f;}; f"
FractalSpace

warum abstimmen? Bitte markieren Sie Fehler oder schlagen Sie stattdessen Verbesserungen vor.
FractalSpace

1
Bei mir git config --global alias.root '!pwd'funktioniert. Ich konnte keinen Fall erkennen, in dem es sich anders verhält als die nicht globale Variante. (Unix, Git 1.7.10.4) Übrigens: Sie findrootbenötigen eine /.git, um eine endlose Rekursion zu vermeiden.
Tino

4

Seit Git 2.13.0 wird eine neue Option zum Anzeigen des Pfads des Root-Projekts unterstützt, die auch dann funktioniert, wenn sie innerhalb eines Submoduls verwendet wird:

git rev-parse --show-superproject-working-tree

git-scm.com/docs/… . Interessant. Ich muss das verpasst haben. +1
VonC

3
Warnung: "Gibt nichts aus, wenn das aktuelle Repository von keinem Projekt als Submodul verwendet wird."
VonC

Danke für den Kommentar! Das hatte ich nicht bemerkt.
Jordi Vilalta Prat

2

Vorkonfigurierte Shell-Aliase in Shell-Frameworks

Wenn Sie ein Shell-Framework verwenden, ist möglicherweise bereits ein Shell-Alias ​​verfügbar:

  • $ grtin oh-my-zsh (68k) ( cd $(git rev-parse --show-toplevel || echo "."))
  • $ git-rootin prezto (8.8k) (zeigt den Pfad zur Arbeitsbaumwurzel an)
  • $ g.. zimfw (1k) (ändert das aktuelle Verzeichnis in die oberste Ebene des Arbeitsbaums.)

1

Ich wollte auf Daniel Brockmans hervorragenden Kommentar eingehen.

Durch das Definieren git config --global alias.exec '!exec 'können Sie Dinge tun, wie zum git exec makeBeispiel man git-config:

Wenn der Alias-Erweiterung ein Ausrufezeichen vorangestellt wird, wird sie als Shell-Befehl behandelt. [...] Beachten Sie, dass Shell-Befehle aus dem Verzeichnis der obersten Ebene eines Repositorys ausgeführt werden, das nicht unbedingt das aktuelle Verzeichnis sein muss.

Es ist auch praktisch zu wissen, dass $GIT_PREFIXdies der Pfad zum aktuellen Verzeichnis relativ zum Verzeichnis der obersten Ebene eines Repositorys ist. Aber zu wissen, dass es nur die halbe Miete ist. Die Erweiterung der Shell-Variablen macht die Verwendung ziemlich schwierig. Also schlage ich vor, bash -cwie folgt zu verwenden:

git exec bash -c 'ls -l $GIT_PREFIX'

Andere Befehle sind:

git exec pwd
git exec make

1

Falls jemand eine POSIX-kompatible Methode benötigt, ohne eine gitausführbare Datei zu benötigen :

git-root::

#$1: Path to child directory
git_root_recurse_parent() {
    # Check if cwd is a git root directory
    if [ -d .git/objects -a -d .git/refs -a -f .git/HEAD ] ; then
        pwd
        return 0
    fi

    # Check if recursion should end (typically if cwd is /)
    if [ "${1}" = "$(pwd)" ] ; then
        return 1
    fi

    # Check parent directory in the same way
    local cwd=$(pwd)
    cd ..
    git_root_recurse_parent "${cwd}"
}

git_root_recurse_parent

Wenn Sie die Funktionalität nur als Teil eines Skripts verwenden möchten, entfernen Sie den Shebang und ersetzen Sie die letzte git_root_recurse_parentZeile durch:

git_root() {
    (git_root_recurse_parent)
}

Vorsichtsmaßnahme: Wenn dies in einem Git-Repo NICHT aufgerufen wird, endet die Rekursion überhaupt nicht.
AH

@AH Die zweite ifAnweisung sollte überprüfen, ob Sie das Verzeichnis in der Rekursion geändert haben. Wenn es im selben Verzeichnis verbleibt, wird davon ausgegangen, dass Sie irgendwo stecken bleiben (z. B. /), und die Rekursion wird gebremst. Der Fehler ist behoben und sollte nun wie erwartet funktionieren. Vielen Dank für den Hinweis.
Swalog

0

Musste das heute selbst lösen. Es wurde in C # gelöst, da ich es für ein Programm brauchte, aber ich denke, es kann leicht umgeschrieben werden. Betrachten Sie diese Public Domain.

public static string GetGitRoot (string file_path) {

    file_path = System.IO.Path.GetDirectoryName (file_path);

    while (file_path != null) {

        if (Directory.Exists (System.IO.Path.Combine (file_path, ".git")))
            return file_path;

        file_path = Directory.GetParent (file_path).FullName;

    }

    return null;

}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.