Git Pathspecs und wie man sie benutzt

Avatar of Adam Giese
Adam Giese am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Als ich die Dokumentation von Git-Befehlen durchsah, bemerkte ich, dass viele davon eine Option für <pathspec> hatten. Ich dachte zunächst, dies sei nur eine technische Umschreibung für „Pfad“ und ging davon aus, dass nur Verzeichnisse und Dateinamen akzeptiert werden könnten. Nachdem ich mich in das Kaninchenloch der Dokumentation vertieft hatte, fand ich heraus, dass die Pathspec-Option von Git-Befehlen weitaus mehr kann.

Die Pathspec ist der Mechanismus, den Git verwendet, um den Geltungsbereich eines Git-Befehls auf eine Teilmenge des Repositorys zu beschränken. Wenn Sie Git bereits intensiv genutzt haben, haben Sie wahrscheinlich bereits eine Pathspec verwendet, ob Sie es nun wissen oder nicht. In dem Befehl git add README.md ist beispielsweise die Pathspec README.md. Sie ist jedoch zu weitaus mehr Nuancen und Flexibilität fähig.

Warum sollten Sie also etwas über Pathspecs lernen? Da sie Teil vieler Befehle sind, werden diese Befehle mit einem Verständnis von Pathspecs wesentlich mächtiger. Mit git add können Sie nur die Dateien in einem einzelnen Verzeichnis hinzufügen. Mit git diff können Sie nur die Änderungen an Dateinamen mit der Erweiterung .scss untersuchen. Sie können git grep alle Dateien durchsuchen, mit Ausnahme derer im Verzeichnis /dist.

Zusätzlich können Pathspecs beim Schreiben allgemeinerer Git-Aliase helfen. Ich habe zum Beispiel einen Alias namens git todo, der alle Repository-Dateien nach der Zeichenkette 'todo' durchsucht. Ich möchte jedoch, dass alle Vorkommen der Zeichenkette angezeigt werden, auch wenn sie sich nicht in meinem aktuellen Arbeitsverzeichnis befinden. Mit Pathspecs werden wir sehen, wie dies möglich wird.

Datei oder Verzeichnis

Die einfachste Art, eine Pathspec zu verwenden, ist mit nur einem Verzeichnis und/oder Dateinamen. Mit git add können Sie beispielsweise Folgendes tun. ., src/ und README sind die jeweiligen Pathspecs für jeden Befehl.

git add .      # add CWD (current working directory)
git add src/   # add src/ directory
git add README # add only README directory

Sie können einem Befehl auch mehrere Pathspecs hinzufügen

git add src/ server/ # adds both src/ and server/ directories

Manchmal sehen Sie ein -- vor der Pathspec eines Befehls. Dies dient dazu, jede Mehrdeutigkeit darüber zu beseitigen, was die Pathspec und was Teil des Befehls ist.

Platzhalter

Zusätzlich zu Dateien und Verzeichnissen können Sie Muster mit *, ? und [] abgleichen. Das *-Symbol wird als Platzhalter verwendet und es gleicht / in Pfaden ab – mit anderen Worten, es durchsucht Unterverzeichnisse.

git log '*.js' # logs all .js files in CWD and subdirectories
git log '.*'   # logs all 'hidden' files and directories in CWD
git log '*/.*' # logs all 'hidden' files and directories in subdirectories

Die Anführungszeichen sind wichtig, besonders bei der Verwendung von *! Sie verhindern, dass Ihre Shell (wie bash oder ZSH) versucht, die Platzhalter selbst zu erweitern. Betrachten wir zum Beispiel, wie git ls-files Dateien mit und ohne Anführungszeichen auflistet.

# example directory structure
#
# .
# ├── package-lock.json
# ├── package.json
# └── data
#     ├── bar.json
#     ├── baz.json
#     └── foo.json

git ls-files *.json 

# package-lock.json
# package.json

git ls-files '*.json'

# data/bar.json
# data/baz.json
# data/foo.json
# package-lock.json
# package.json

Da die Shell das * im ersten Befehl erweitert, erhält git ls-files den Befehl als git ls-files package-lock.json package.json. Die Anführungszeichen stellen sicher, dass Git den Platzhalter auflöst.

Sie können auch das ?-Zeichen als Platzhalter für ein einzelnes Zeichen verwenden. Um beispielsweise entweder mp3- oder mp4-Dateien abzugleichen, können Sie Folgendes tun.

git ls-files '*.mp?'

Klammerausdrücke

Sie können auch „Klammerausdrücke“ verwenden, um ein einzelnes Zeichen aus einer Menge abzugleichen. Wenn Sie beispielsweise Übereinstimmungen zwischen TypeScript- oder JavaScript-Dateien erzielen möchten, können Sie [tj] verwenden. Dies gleicht entweder ein t oder ein j ab.

git ls-files '*.[tj]s'

Dies gleicht entweder .ts- oder .js-Dateien ab. Zusätzlich zur Verwendung von Zeichen gibt es bestimmte Zeichenkollektionen, auf die innerhalb von Klammerausdrücken verwiesen werden kann. Sie können beispielsweise [:digit:] innerhalb eines Klammerausdrucks verwenden, um eine beliebige Dezimalziffer abzugleichen, oder Sie können [:space:] verwenden, um beliebige Leerzeichen abzugleichen.

git ls-files '*.mp[[:digit:]]' # mp0, mp1, mp2, mp3, ..., mp9
git ls-files '*[[:space:]]*' # matches any path containing a space

Um mehr über Klammerausdrücke und deren Verwendung zu erfahren, lesen Sie das GNU-Handbuch.

Magische Signaturen

Pathspecs verfügen auch über das spezielle Werkzeug in ihrem Arsenal, die sogenannten „magischen Signaturen“, die zusätzliche Funktionalität für Ihre Pathspecs freischalten. Diese „magischen Signaturen“ werden durch die Verwendung von :(signatur) am Anfang Ihrer Pathspec aufgerufen. Wenn das keinen Sinn ergibt, machen Sie sich keine Sorgen: Einige Beispiele werden hoffentlich Klarheit schaffen.

top

Die top-Signatur weist Git an, das Muster vom Stammverzeichnis des Git-Repositorys anstatt vom aktuellen Arbeitsverzeichnis abzugleichen. Sie können auch die Kurzform :/ anstelle von :(top) verwenden.

git ls-files ':(top)*.js'
git ls-files ':/*.js' # shorthand

Dies listet alle Dateien in Ihrem Repository auf, die die Erweiterung .js haben. Mit der top-Signatur kann dies von jedem Unterverzeichnis in Ihrem Repository aufgerufen werden. Ich finde dies besonders nützlich beim Schreiben allgemeiner Git-Aliase!

git config --global alias.js 'ls-files -- ':(top)*.js''

Sie können git js überall in Ihrem Repository verwenden, um eine Liste aller JavaScript-Dateien in Ihrem Projekt zu erhalten.

icase

Die icase-Signatur weist Git an, bei Übereinstimmungen nicht auf die Groß- und Kleinschreibung zu achten. Dies kann nützlich sein, wenn Ihnen die Groß- und Kleinschreibung des Dateinamens egal ist – dies kann beispielsweise nützlich sein, um jpg-Dateien abzugleichen, die manchmal die Großbuchstaben-Erweiterung JPG verwenden.

git ls-files ':(icase)*.jpg'

literal

Die literal-Signatur weist Git an, alle Ihre Zeichen buchstäblich zu behandeln. Dies würde verwendet, wenn Sie Zeichen wie * und ? als sich selbst und nicht als Platzhalter behandeln möchten. Sofern Ihr Repository keine Dateinamen mit * oder ? hat, gehe ich nicht davon aus, dass diese Signatur oft verwendet wird.

git log ':(literal)*.js' # returns log for the file '*.js'

glob

Als ich begann, Pathspecs zu lernen, bemerkte ich, dass Platzhalter anders funktionierten, als ich es gewohnt war. Typischerweise sehe ich ein einzelnes Sternchen * als Platzhalter, das nichts durch Verzeichnisse hindurch abgleicht, und aufeinanderfolgende Sternchen (**) als „tiefen“ Platzhalter, der Namen durch Verzeichnisse hindurch abgleicht. Wenn Sie diesen Stil von Platzhaltern bevorzugen, können Sie die glob-Magische Signatur verwenden!

Dies kann nützlich sein, wenn Sie eine feinere Kontrolle darüber wünschen, wie Sie Ihre Projektverzeichnisstruktur durchsuchen. Als Beispiel sehen Sie sich an, wie diese beiden git ls-files-Befehle ein React-Projekt durchsuchen.

git ls-files ':(glob)src/components/*/*.jsx' # 'top level' jsx components
git ls-files ':(glob)src/components/**/*.jsx' # 'all' jsx components

attr

Git hat die Fähigkeit, „Attribute“ für bestimmte Dateien festzulegen. Sie können diese Attribute mit einer .gitattributes-Datei festlegen.

# .gitattributes

src/components/vendor/*  vendored # sets 'vendored' attribute
src/styles/vendor/*      vendored

Die Verwendung der attr-Magischen Signatur kann Attributanforderungen für Ihre Pathspec festlegen. Wir könnten beispielsweise die oben genannten Dateien aus einem Vendor ignorieren wollen.

git ls-files ':(attr:!vendored)*.js' # searches for non-vendored js files
git ls-files ':(attr:vendored)*.js'  # searches for vendored js files

exclude

Zuletzt gibt es die „exclude“-Magische Signatur (Kurzform :! oder :^). Diese Signatur funktioniert anders als die übrigen magischen Signaturen. Nachdem alle anderen Pathspecs aufgelöst wurden, werden alle Pathspecs mit einer exclude-Signatur aufgelöst und dann aus den zurückgegebenen Pfaden entfernt. Sie können beispielsweise alle Ihre .js-Dateien durchsuchen und dabei die Testdateien .spec.js ausschließen.

git grep 'foo' -- '*.js' ':(exclude)*.spec.js' # search .js files excluding .spec.js
git grep 'foo' -- '*.js' ':!*.spec.js' .       # shorthand for the same

Kombinieren von Signaturen

Es gibt nichts, das Sie davon abhält, mehrere magische Signaturen in einer einzigen Pathspec zu verwenden! Sie können mehrere Signaturen verwenden, indem Sie Ihre magischen Wörter durch Kommas innerhalb Ihrer Klammern trennen. Sie können beispielsweise Folgendes tun, wenn Sie vom Basisverzeichnis Ihres Repositorys aus abgleichen möchten (mit top), nicht auf Groß- und Kleinschreibung achten möchten (mit icase), nur den entwickelten Code verwenden möchten (Vendor-Dateien mit attr ignorieren) und glob-ähnliche Platzhalter verwenden möchten (mit glob).

git ls-files -- ':(top,icase,glob,attr:!vendored)src/components/*/*.jsx'

Die einzigen beiden magischen Signaturen, die Sie nicht kombinieren können, sind glob und literal, da beide beeinflussen, wie git mit Platzhaltern umgeht. Dies wird im Git-Glossar mit vielleicht meinem Lieblingssatz erwähnt, den ich je in einer Dokumentation gelesen habe.

Glob-Magie ist mit Literal-Magie inkompatibel.


Pathspecs sind ein integraler Bestandteil vieler Git-Befehle, aber ihre Flexibilität ist nicht sofort zugänglich. Indem Sie lernen, wie man Platzhalter und magische Signaturen verwendet, können Sie Ihre Beherrschung der Git-Befehlszeile vervielfachen.