Unignore-Unterverzeichnisse ignorierter Verzeichnisse in Git

99

Angenommen, ich habe ein Verzeichnis ignoriert, möchte jedoch bestimmte Unterverzeichnisse darin aufheben. Also habe ich das Setup:

/uploads/
/uploads/rubbish/
/uploads/rubbish/stuff/KEEP_ME/
/uploads/foo/
/uploads/foo/bar/lose/

Und ich möchte alles außer dem KEEP_MEVerzeichnis ignorieren . Ich würde hoffen, dass das Ignorieren ungefähr so ​​aussieht:

/uploads/*
!/uploads/rubbish/stuff/KEEP_ME/

Aber das funktioniert nicht und es gibt auch nicht mehrere Permutationen zum selben Thema.

Eine, die funktioniert, ist

/uploads/**/**/**/
!/uploads/rubbish/stuff/KEEP_ME/

Aber das fühlt sich ein wenig restriktiv und ausführlich an?

Wil
quelle
1
Der von Ihnen angegebene Code hat bei mir nicht funktioniert (mit Git Version 1.9.1). Eine, die funktioniert hat, ist / uploads / *! / Uploads / Müll / / Uploads / Müll / *! / Uploads / Müll / Zeug / Uploads / Müll / Zeug / *! / Uploads / Müll / Zeug / behalten (ähnlich wie im Beispiel in git-scm.com/docs/gitignore ). Meine Ordnerstruktur; └ README.md └ Uploads / foo / bar / lose / lose.txt └ Uploads / Müll / Zeug / keep / keep.txt
Gihanchanuka

Antworten:

119

Entsprechend dem Musterformatabschnitt der gitignore-Dokumentation :

Ein optionales Präfix "!" was das Muster negiert; Alle übereinstimmenden Dateien, die von einem vorherigen Muster ausgeschlossen wurden, werden wieder aufgenommen. Es ist nicht möglich, eine Datei erneut einzuschließen, wenn ein übergeordnetes Verzeichnis dieser Datei ausgeschlossen ist. Git listet aus Leistungsgründen keine ausgeschlossenen Verzeichnisse auf, daher haben alle Muster in enthaltenen Dateien keine Auswirkung, unabhängig davon, wo sie definiert sind. Setzen Sie einen Backslash ("\") vor das erste "!" für Muster, die mit einem wörtlichen "!" beginnen, zum Beispiel "! wichtig! .txt".

Daher muss das zuvor ausgeschlossene übergeordnete Verzeichnismuster /uploads/rubbish/stuff/keep/ausschließlich negiert werden, bevor sein Inhalt negiert wird:

#ignore everything within /uploads/ 
/uploads/*

#include everything within /uploads/rubbish/stuff/keep
!/uploads/rubbish/stuff/keep/  
!/uploads/rubbish/stuff/keep/*

Um Unterverzeichnisse aufzunehmen, /uploads/rubbish/stuff/keep/fügen Sie die dritte Zeile hinzu:

!/uploads/rubbish/stuff/keep/**/*
Kunst Shayderov
quelle
1
Welche Version von Git haben Sie verwendet? Vielleicht ist es etwas, das nur in bestimmten Versionen verfügbar ist.
Verlegen. Ich habe vergessen, dass ich diesen Kommentar gepostet habe. Ich habe es aber zum Laufen gebracht. FWIW, ich benutze nicht die führenden Schrägstriche. Ich erinnere mich nicht, ob das das Problem war. Ich benutze 1.7.2.5.
Ich habe eine globale Gitignore-Datei, in der ich alle * .zip-Dateien ignoriert habe. Für ein bestimmtes Projekt möchte ich jedoch Zip-Dateien einfügen. Ich habe diese Zeile zu diesem Projekt hinzugefügt .gitignoreund es funktioniert großartig !*.zip
!:
Ich fand es notwendig, beliebige Verzeichnisse sowohl vor als auch nach dem angegebenen Ordner explizit anzugeben, sowohl unter Ausschluss des Ordners als auch unter Einbeziehung des Unterordners . ( Vollständige Antwort ).
Josiah Yoder
Diese Methode funktioniert nicht (ab Git 2.25 - möglicherweise hat sich etwas in Git geändert). Ich habe stackoverflow.com/a/60288435/295691 unten als Korrektur gepostet .
user295691
34

Selbst wenn Sie etwas hinzufügen .gitignore, können Sie git zwingen , es dem Index hinzuzufügen

git add --force uploads/rubbish/stuff/KEEP_ME/

"KEEP_ME" scheint jedoch ein Verzeichnis zu sein und git mag normalerweise keinen leeren Ordner. Daher sollten Sie stattdessen eine "Platzhalter" -Datei-Datei hinzufügen, wenn der Ordner leer ist

git add --force uploads/rubbish/stuff/KEEP_ME/.keep_me
KingCrunch
quelle
Das einzige Problem dabei ist, dass sich dieses spezielle Beispiel auf einen globalen Gitignore bezieht, den ich hätte erwähnen sollen. Ich weiß, dass ich das Hinzufügen von Elementen erzwingen kann, aber ich muss dies tun, wenn neue Elemente hinzugefügt werden, sowie zunächst für jedes neue Repository. Stellt die .keep sicher, dass der Inhalt nicht ignoriert wird?
Wil
1
Habe einen kleinen Test gemacht. Ja, Sie müssen git add --forcefür jedes neue Element oder jeden neuen Ordner in verwenden KEEP_ME. git add -uDanach werden Updates nur hinzugefügt (wenn Sie beispielsweise eine ausführen), als wären die Dateien "nicht signiert". Das .keep_memacht nichts, es ist nur eine Datei, damit git den Ordner bearbeitet.
Commonpike
1
git add --forceist die falsche Lösung dafür. Wenn Sie ein Verzeichnis verschieben oder die Datei in ein anderes Verzeichnis verschieben, löscht gits Tracking die Datei, fügt sie jedoch nicht dem neuen Speicherort hinzu, und Sie müssen dies git add --forceerneut tun . Durch Aufheben der Zuordnung zu einem generischen Muster verfolgt git die Bewegung einer Datei innerhalb des Repos.
Merlin
Dies ist die einzige Lösung, die für mich funktioniert hat. Mein Ordner wurde NICHT ignoriert, aber ich konnte ihn auf keinen Fall hinzufügen. Dieser Weg löste es für mich.
Akito
6

Ich habe versucht herauszufinden, wie ein bestimmter Ordner eingeschlossen werden kann, wenn alle Ordner mit dem generischen Ausschluss ausgeschlossen werden

**/build

Wenn Sie das /*am Ende Ihres generischen Ausschlusses hinzufügen , schließen Sie weiterhin alle Build-Dateien aus**/build/*

Anschließend fügen Sie eine weitere Zeile hinzu, um den Pfad zu korrigieren, der eingeschlossen werden soll

!**/folder/build/* 

Lassen Sie uns einen Gitignore, der liest

**/build/* 
!**/folder/build/* 
John
quelle
2

Die Antworten von Buo-Ren Lin und John sind sehr hilfreich, aber ich musste beide kombinieren.

Wenn ich andere Unterordner sowie Dateien innerhalb von Uploads ausschließen wollte, musste ich vor dem angegebenen Ordner explizit beliebige Verzeichnisse angeben, sowohl beim Ausschließen des Ordners als auch beim Einschließen des Unterordners

**/uploads/*
!**/uploads/rubbish/
!**/uploads/rubbish/*

Ich fand es auch notwendig, sowohl den Unterordner als auch seinen Inhalt explizit wieder einzuschließen, um beide Elemente im Ordner und in den Unterordnern anzuzeigen.

Josiah Yoder
quelle
Seufzer. Kein Glück hier. Hier schon seit Stunden. Git 2.20.1
RichieHH
@ HörmannHH Tut mir leid das zu hören. Vielleicht ist es Zeit, eine neue Frage zu stellen?
Josiah Yoder
2

Die Lösung, die als die am besten bewertete Antwort dargestellt wird, ist falsch und als solche leicht nachweisbar.

Beginnen Sie damit, alles in Uploads / * zu ignorieren:

mkdir -p uploads/rubbish/stuff/KEEP_ME
touch uploads/a uploads/rubbish/a uploads/rubbish/stuff/a uploads/rubbish/stuff/KEEP_ME/a
echo '/uploads/*' >> .gitignore
git init
git add .
git commit -m "Initial commit"

Heben Sie nun das übergeordnete Verzeichnis des ignorierten Materials wie oben beschrieben auf:

echo 'uploads/rubbish/stuff/KEEP_ME/' >> .gitignore
echo 'uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Zeigt keine nicht verfolgten Dateien an.

Damit es funktioniert, müssen Sie alle Dateien unter dem uploads/Baum ( uploads/**/*nicht nur die oberste Ebene uploads/*) ignorieren und dann alle übergeordneten Verzeichnisse des Baums hinzufügen, die Sie behalten möchten

echo '/uploads/**/*' > .gitignore
echo '!/uploads/rubbish/' >> .gitignore
echo '!/uploads/rubbish/stuff' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Welches gibt:

On branch master
...
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        uploads/rubbish/stuff/KEEP_ME/a

Wenn wir früher hatten uploads/*in der .gitignoreoben, dann wird alle Zwischendateien enthalten gewesen wären als gut, so zum Beispiel uploads/rubbish/azeigen würde , oben in dem Statusbefehl auf.

user295691
quelle