remote - git tutorial




Wie kann ich einem Git-Repository ein leeres Verzeichnis hinzufügen? (19)

Warum brauchen wir leere versionierte Ordner

Das wichtigste zuerst:

Ein leeres Verzeichnis kann nicht Teil eines Baums unter dem Git-Versionssystem sein .

Es wird einfach nicht verfolgt. Es gibt jedoch Szenarien, in denen "Versionierung" leerer Verzeichnisse nützlich sein kann, zum Beispiel:

  • eine vordefinierte Ordnerstruktur einrichten und diese Struktur jedem Benutzer / Mitwirkenden des Repositorys zur Verfügung stellen; oder, als Spezialfall der obigen .gitignore , das Erstellen eines Ordners für temporäre Dateien , wie zum Beispiel cache/ oder logs/ .gitignore , in dem der Ordner, jedoch .gitignore dessen Inhalt .gitignore
  • In Bezug auf den Überblick funktionieren einige Projekte nicht ohne einige Ordner (was oft ein Hinweis auf ein schlecht entworfenes Projekt ist, aber es ist ein häufiges reales Szenario und möglicherweise gibt es möglicherweise Berechtigungsprobleme).

Einige empfohlene Problemumgehungen

Viele Benutzer empfehlen:

  1. Platzieren einer README Datei oder einer anderen Datei mit etwas Inhalt, um das Verzeichnis nicht leer zu machen, oder
  2. Erstellen einer .gitignore Datei mit einer Art "umgekehrter Logik" (dh, um alle Dateien .gitignore ), die am Ende den gleichen Zweck der Annäherung # 1 .gitignore .

Während beide Lösungen sicherlich funktionieren, finde ich sie mit einer sinnvollen Herangehensweise an die Git-Versionierung nicht konsistent.

  • Warum sollten Sie falsche Dateien oder READMEs einfügen, die Sie möglicherweise nicht in Ihrem Projekt haben möchten?
  • Warum sollten Sie .gitignore , um etwas (das Aufbewahren von Dateien) .gitignore , das .gitignore das Gegenteil von dem ist, für das es gedacht ist (mit Ausnahme von Dateien), obwohl dies möglich ist?

.gitkeep Ansatz

Verwenden Sie eine leere Datei mit dem Namen .gitkeep , um die Anwesenheit des Ordners im Versionierungssystem zu erzwingen.

Obwohl es vielleicht keinen so großen Unterschied gibt:

  • Sie verwenden eine Datei mit dem einzigen Zweck, den Ordner zu behalten. Sie geben dort keine Informationen an, die Sie nicht hinzufügen möchten.

    Beispielsweise sollten Sie READMEs als READMEs mit nützlichen Informationen verwenden, nicht als Entschuldigung, um den Ordner zu behalten.

    Die Trennung von Bedenken ist immer eine gute Sache, und Sie können immer noch einen .gitignore hinzufügen, um unerwünschte Dateien zu ignorieren.

  • Die Benennung .gitkeep macht es aus dem Dateinamen selbst (und auch für andere Entwickler , was für ein gemeinsames Projekt und eine der .gitkeep eines Git-Repositorys ist) sehr klar und unkompliziert, dass es sich um diese Datei handelt

    • Eine Datei, die nicht mit dem Code zusammenhängt (aufgrund des führenden Punkts und des Namens)
    • Eine Datei, die eindeutig mit Git zusammenhängt
    • Sein Zweck ( Keep ) ist klar angegeben und konsistent und in seiner Bedeutung semantisch zu ignorieren

Annahme

Ich habe gesehen, wie .gitkeep von sehr wichtigen Frameworks wie Laravel und Angular-CLI .

Wie kann ich ein leeres Verzeichnis (das keine Dateien enthält) zu einem Git-Repository hinzufügen?


Andy Lester hat Recht, aber wenn Ihr Verzeichnis nur leer und nicht leer sein muss, können Sie eine leere .gitignore Datei als Umgehungslösung .gitignore .

Abgesehen davon ist dies ein Implementierungsproblem und kein grundlegendes Git-Speicherdesignproblem. Wie schon oft in der Git-Mailing-Liste erwähnt wurde, wurde dies nicht implementiert, weil sich niemand darum gekümmert hat, einen Patch einzureichen, nicht, dass er dies nicht tun könnte oder sollte.


Das Hinzufügen eines leeren Verzeichnisses scheint der Pfad des geringsten Widerstandes zu sein, da Sie über Skripts verfügen, die das Verzeichnis als vorhanden betrachten (möglicherweise weil es ein Ziel für generierte Binärdateien ist). Ein anderer Ansatz wäre, Ihre Skripts so zu ändern, dass das Verzeichnis nach Bedarf erstellt wird .

mkdir --parents .generated/bin ## create a folder for storing generated binaries
mv myprogram1 myprogram2 .generated/bin ## populate the directory as needed

In diesem Beispiel können Sie einen (defekten) symbolischen Link zum Verzeichnis einchecken, sodass Sie ohne das Präfix ".generated" darauf zugreifen können (dies ist jedoch optional).

ln -sf .generated/bin bin
git add bin

Wenn Sie Ihren Quellbaum bereinigen möchten, können Sie einfach:

rm -rf .generated ## this should be in a "clean" script or in a makefile

Wenn Sie den oft vorgeschlagenen Ansatz des Eincheckens in einem fast leeren Ordner anwenden, haben Sie die geringere Komplexität, den Inhalt zu löschen, ohne auch die Datei ".gitignore" zu löschen.

Sie können alle generierten Dateien ignorieren, indem Sie Folgendes in Ihrem Root-.gitignore hinzufügen:

.generated

Das kann und kann ich leider nicht. Dies ist eine Entscheidung, die Linus Torvald selbst getroffen hat. Er weiß, was für uns gut ist.

Irgendwo da draußen, wo ich einmal gelesen habe, gibt es ein Wort.

Ich habe Re: Leere Verzeichnisse gefunden .. , aber vielleicht gibt es noch ein anderes.

Sie müssen mit den Problemumgehungen leben ... leider.


Du kannst nichtDies ist eine beabsichtigte Entwurfsentscheidung der Git-Betreuer. Grundsätzlich dient ein Quellcode-Verwaltungssystem wie Git dazu, Quellcode zu verwalten, und leere Verzeichnisse sind kein Quellcode. Git wird auch oft als Content-Tracker bezeichnet. Leere Verzeichnisse sind auch nicht Inhalt (im Gegenteil), also werden sie nicht verfolgt.


Eine andere Möglichkeit, ein Verzeichnis leer zu lassen (im Repository), besteht im Erstellen einer .gitignore Datei in diesem Verzeichnis, das diese vier Zeilen enthält:

# Ignore everything in this directory
*
# Except this file
!.gitignore

Dann müssen Sie die Reihenfolge nicht so festlegen, wie Sie es bei m104 tun müssen.

Dies hat auch den Vorteil, dass Dateien in diesem Verzeichnis nicht als "unaufgezeichnet" angezeigt werden, wenn Sie einen Git-Status ausführen.

@GreenAsJade Kommentar dauerhaft machen:

Ich denke, es ist erwähnenswert, dass diese Lösung genau das tut, was die Frage stellt, aber vielleicht ist es nicht das, wonach viele Leute suchen, die diese Frage betrachten. Diese Lösung garantiert, dass das Verzeichnis leer bleibt. Es heißt "Ich möchte wirklich nie, dass Dateien hier eingecheckt werden". Im Gegensatz zu "Ich habe noch keine Dateien zum Einchecken hier, aber ich brauche das Verzeichnis hier, die Dateien können später kommen".


Git verfolgt keine leeren Verzeichnisse. Weitere Informationen finden Sie in den Git-FAQs . Die empfohlene Problemumgehung besteht darin, eine .gitignore Datei im leeren Verzeichnis .gitignore . .gitignore Lösung gefällt mir nicht, da der .gitignore von der Unix-Konvention "versteckt" wird. Es gibt auch keine Erklärung, warum die Verzeichnisse leer sind.

Ich schlage vor, eine README-Datei in das leere Verzeichnis zu legen und zu erklären, warum das Verzeichnis leer ist und warum es in Git verfolgt werden muss. Wenn die README-Datei vorhanden ist, ist das Verzeichnis für Git nicht mehr leer.

Die eigentliche Frage ist, warum braucht man das leere Verzeichnis in git? Normalerweise haben Sie eine Art Build-Skript, das das leere Verzeichnis vor dem Kompilieren / Ausführen erstellen kann. Wenn nicht, dann mach einen. Das ist eine weitaus bessere Lösung als leere Verzeichnisse in git zu setzen.

Sie haben also einen Grund, warum Sie ein leeres Verzeichnis in git benötigen. Setzen Sie diesen Grund in die README-Datei. Auf diese Weise wissen andere Entwickler (und zukünftig Sie), warum das leere Verzeichnis vorhanden sein muss. Sie werden auch wissen, dass Sie das leere Verzeichnis entfernen können, wenn das Problem behoben wurde, das ein leeres Verzeichnis erfordert.

Verwenden Sie den folgenden Befehl, um jedes leere Verzeichnis aufzulisten:

find -name .git -prune -o -type d -empty -print

So erstellen Sie Platzhalter-READMEs in jedem leeren Verzeichnis:

find -name .git -prune -o -type d -empty -exec sh -c \
  "echo this directory needs to be empty because reasons > {}/README.emptydir" \;

Um alles im Verzeichnis außer der README-Datei zu ignorieren, .gitignore die folgenden Zeilen in Ihr .gitignore :

path/to/emptydir/*
!path/to/emptydir/README.emptydir
path/to/otheremptydir/*
!path/to/otheremptydir/README.emptydir

Alternativ können Sie einfach jede README-Datei von der Ignorierung ausschließen:

path/to/emptydir/*
path/to/otheremptydir/*
!README.emptydir

So listen Sie jedes README auf, nachdem es bereits erstellt wurde:

find -name README.emptydir

Ich habe das Problem auch mit leeren Verzeichnissen konfrontiert. Das Problem bei der Verwendung von Platzhalter-Dateien besteht darin, dass Sie sie erstellen und löschen müssen, wenn sie nicht mehr erforderlich sind (weil später Unterverzeichnisse oder Dateien hinzugefügt wurden. Bei der Verwaltung großer Platzbäume können diese Platzhalter-Dateien umständlich und fehlerhaft sein.) anfällig.

Aus diesem Grund habe ich mich entschlossen, ein Open Source-Tool zu schreiben, mit dem das Erstellen / Löschen solcher Platzhalter-Dateien automatisch verwaltet werden kann. Es ist für die .NET-Plattform geschrieben und läuft unter Mono (.NET für Linux) und Windows.

Schauen Sie einfach unter http://code.google.com/p/markemptydirs


So erstellen Sie Ruby on Rails- Protokollordner:

mkdir log && touch log/.gitkeep && git add log/.gitkeep

Nun wird das Protokollverzeichnis in die Baumstruktur aufgenommen. Es ist sehr nützlich bei der Bereitstellung, sodass Sie keine Routine schreiben müssen, um Protokollverzeichnisse zu erstellen.

Die Logfiles können durch Ausgabe herausgehalten werden,

echo log/dev.log >> .gitignore

Aber das wussten Sie wahrscheinlich.


Wenn Sie eine .gitignore Datei hinzufügen, und wenn Sie eine beliebige Menge Inhalt .gitignore (die Git ignorieren soll), möchten Sie möglicherweise eine einzelne Zeile mit einem Sternchen * hinzufügen, um sicherzustellen, dass Sie keine Inhalte wurden versehentlich ignoriert.


Wie in anderen Antworten beschrieben, kann Git keine leeren Verzeichnisse in seinem Bereitstellungsbereich darstellen. (Siehe Git-FAQ .) Wenn ein Verzeichnis für Ihre Zwecke jedoch leer genug ist, wenn es nur eine .gitignore Datei enthält, können Sie .gitignore Dateien nur in leeren Verzeichnissen erstellen.

find . -type d -empty -exec touch {}/.gitignore \;

WARNUNG: Diese Optimierung funktioniert nicht wirklich, wie sich herausstellt. Entschuldigung für die Unannehmlichkeiten.

Originalbeitrag unten:

Ich habe beim Spielen mit Git-Interna eine Lösung gefunden!

  1. Angenommen, Sie befinden sich in Ihrem Repository.
  2. Erstellen Sie ein leeres Verzeichnis:

    $ mkdir path/to/empty-folder
    
  3. Fügen Sie es mit einem Installationsbefehl und dem leeren Baum SHA-1 zum Index hinzu:

    $ git update-index --index-info
    040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904    path/to/empty-folder
    

    Geben Sie den Befehl ein und geben Sie die zweite Zeile ein. Drücken Sie die Eingabetaste und dann Strg + D, um Ihre Eingabe zu beenden. Hinweis: Das Format ist der Modus [SPACE] -Typ [SPACE] SHA-1hash [TAB] (der Tab ist wichtig, die Antwortformatierung behält ihn nicht bei).

  4. Das ist es! Ihr leerer Ordner befindet sich in Ihrem Index. Alles was Sie tun müssen, ist zu begehen.

Diese Lösung ist kurz und funktioniert anscheinend gut ( siehe EDITIEREN! ), Aber es ist nicht so leicht zu merken ...

Der leere Baum SHA-1 kann gefunden werden, indem ein neues leeres Git-Repository erstellt wird, cd hinein und der git write-tree , der den leeren Baum SHA-1 ausgibt.

BEARBEITEN:

Ich verwende diese Lösung, seit ich sie gefunden habe. Es scheint genau so zu funktionieren wie das Erstellen eines Submoduls, nur dass an keiner Stelle ein Modul definiert ist. Dies führt zu Fehlern bei der Ausgabe von git submodule init|update . Das Problem ist, dass git update-index den 040000 tree in den 160000 commit umschreibt.

Außerdem wird jede unter diesem Pfad platzierte Datei von Git nicht bemerkt, da sie der Meinung ist, dass sie zu einem anderen Repository gehört. Dies ist unangenehm, da es leicht übersehen werden kann!

Wenn Sie jedoch nicht bereits Git-Submodule in Ihrem Repository verwenden (und auch nicht verwenden) und der "leere" Ordner leer bleibt oder wenn Sie möchten, dass Git von seiner Existenz erfährt und dessen Inhalt ignoriert, können Sie dies tun dieser Tweak. Um mit Submodulen den üblichen Weg zu gehen, sind mehr Schritte erforderlich, als dies der Fall ist.


Es gibt keine Möglichkeit, Git zum Verfolgen von Verzeichnissen zu veranlassen. Daher besteht die einzige Lösung darin, eine Platzhalterdatei in dem Verzeichnis hinzuzufügen, das Git verfolgen soll.

Die Datei kann beliebig benannt werden und enthält alles, was Sie möchten. Die meisten Benutzer verwenden jedoch eine leere Datei mit dem Namen .gitkeep(obwohl einige Benutzer die VCS-Agnostic bevorzugen .keep).

Das Präfix .markiert es als versteckte Datei.

Eine andere Idee wäre, eine READMEDatei hinzuzufügen , die erklärt, wofür das Verzeichnis verwendet wird.


Hinzufügen einer weiteren Option zum Kampf.

Angenommen, Sie möchten zu gitdiesem Zweck ein Verzeichnis hinzufügen, das für alle damit verbundenen Zwecke gitleer bleiben sollte und niemals dessen Inhalt verfolgt werden soll. Dies wird, .gitignorewie hier schon mehrmals vorgeschlagen , als Trick ausgeführt.

Das Format ist wie erwähnt:

*
!.gitignore

Wenn Sie eine Möglichkeit haben möchten, dies über die Befehlszeile zu tun, können Sie auf einen Schlag innerhalb des Verzeichnisses, das Sie hinzufügen möchten, Folgendes ausführen:

$ echo "*" > .gitignore && echo '!.gitignore' >> .gitignore && git add .gitignore

Ich selbst habe ein Shell-Skript, das ich dazu benutze. Benennen Sie das Skript, wie Sie möchten, und fügen Sie es entweder in Ihrem Include-Pfad hinzu oder verweisen Sie direkt darauf:

#!/bin/bash

dir=''

if [ "$1" != "" ]; then
    dir="$1/"
fi

echo "*" > $dir.gitignore && \
echo '!.gitignore' >> $dir.gitignore && \
git add $dir.gitignore

Damit können Sie es entweder innerhalb des Verzeichnisses ausführen, das Sie hinzufügen möchten, oder das Verzeichnis als ersten und einzigen Parameter referenzieren:

$ ignore_dir ./some/directory

Eine weitere Option (in Reaktion auf einen Kommentar von @GreenAsJade), wenn Sie einen leeren Ordner verfolgen mögen , die MAI - Dateien in der Zukunft enthält , verfolgt, aber jetzt leer sein, können Sie die ommit *aus der .gitignoreDatei, und prüfen Sie, dass in. Im Grunde sagt die Datei nur "Ignoriere mich nicht ", aber ansonsten ist das Verzeichnis leer und wird verfolgt.

Ihre .gitignoreDatei würde folgendermaßen aussehen:

!.gitignore

Das ist es, checken Sie das ein und Sie haben ein leeres, aber nachverfolgtes Verzeichnis, in dem Sie Dateien zu einem späteren Zeitpunkt nachverfolgen können.

Ich schlage vor, diese eine Zeile in der Datei zu behalten, weil sie den .gitignoreZweck hat. Andernfalls könnte jemand in der Leitung denken, es zu entfernen. Es kann hilfreich sein, wenn Sie einen Kommentar oberhalb der Zeile platzieren.


Wenn Sie einen Ordner hinzufügen möchten, in dem viele transiente Daten in mehreren semantischen Verzeichnissen gespeichert werden, besteht die Möglichkeit, dem Stamm .gitignore so etwas hinzuzufügen.

/app/data/**/*.* !/app/data/**/*.md

Dann können Sie *.mdin jedem Verzeichnis deskriptive README.md-Dateien (oder leere Dateien, egal wie sie in diesem Fall eindeutig angegeben werden können) festschreiben, um sicherzustellen, dass die Verzeichnisse alle Teil des Repos bleiben Dateien (mit Erweiterungen) werden ignoriert. EINSCHRÄNKUNG: .In den Verzeichnisnamen sind keine erlaubt!

Sie können alle diese Verzeichnisse mit xml / images-Dateien oder anderen Dateien füllen und mit der /app/data/Zeit weitere Verzeichnisse hinzufügen, wenn der Speicher für Ihre App erforderlich ist (mit den README.md-Dateien, die dazu dienen, eine Beschreibung des jeweiligen Speicherverzeichnisses zu brennen genau).

Es ist nicht erforderlich, Ihr .gitignoreSystem weiter zu ändern oder zu dezentralisieren, indem Sie .gitignorefür jedes neue Verzeichnis ein neues erstellen . Wahrscheinlich nicht die klügste Lösung, aber es ist knapp bei Gititore und funktioniert immer für mich. Schön und einfach! ;)


Hier ist ein Hack, aber es ist lustig, dass es funktioniert (Git 2.2.1). Ähnlich dem, was @Teka vorschlug, aber leichter zu merken:

  • Hinzufügen eines Submoduls zu einem beliebigen Repository ( git submodule add path_to_repo)
  • Dadurch werden ein Ordner und eine Datei hinzugefügt .submodules. Änderung vornehmen
  • .submodulesDatei löschen und die Änderung übernehmen.

Jetzt haben Sie ein Verzeichnis, das beim Auschecken von Commit erstellt wird. Eine interessante Sache ist jedoch, dass wenn Sie sich den Inhalt des Baumobjekts dieser Datei ansehen, erhalten Sie:

fatal: Kein gültiger Objektname b64338b90b4209263b50244d18278c0999867193

Ich würde es jedoch nicht ermutigen, es zu verwenden, da es in zukünftigen Versionen von Git möglicherweise nicht mehr funktioniert. Dadurch kann Ihr Repository beschädigt werden.


Manchmal habe ich Repositorys mit Ordnern, die immer nur Dateien enthalten, die als "Inhalt" betrachtet werden. Das sind also keine Dateien, die mir wichtig sind, wenn sie versioniert werden, und sollten daher niemals festgeschrieben werden. Mit der .gitignore-Datei von Git können Sie ganze Verzeichnisse ignorieren. Es gibt jedoch Zeiten, in denen ein Ordner im Repo von Vorteil wäre. Hier ist eine hervorragende Lösung, um dieses Bedürfnis zu erfüllen.

Was ich in der Vergangenheit getan habe, ist, eine .gitignore -Datei in das Stammverzeichnis meines Repos zu setzen und dann den Ordner auszuschließen, wie dies zutrifft:

/app/some-folder-to-exclude
/another-folder-to-exclude/*

Diese Ordner werden jedoch nicht Teil des Repos. Sie könnten dort etwas wie eine README-Datei hinzufügen. Dann müssen Sie jedoch Ihrer Anwendung mitteilen, dass sie sich nicht um die Verarbeitung von README-Dateien kümmern muss.

Wenn Ihre App davon abhängig ist, ob die Ordner vorhanden sind (obwohl leer), können Sie dem betreffenden Ordner einfach eine .gitignore-Datei hinzufügen und zwei Ziele erreichen:

Sagen Sie Git, dass sich im Ordner eine Datei befindet, die Git zum Repo hinzufügt. Bitten Sie Git, den Inhalt dieses Ordners zu ignorieren, abzüglich dieser Datei. Hier ist die .gitignore-Datei, die Sie in Ihre leeren Verzeichnisse einfügen können:

*
!.gitignore

Die erste Zeile (*) weist Git an, alles in diesem Verzeichnis zu ignorieren. Die zweite Zeile weist Git an, die .gitignore-Datei nicht zu ignorieren. Sie können diese Datei in jeden leeren Ordner füllen, den Sie dem Repository hinzufügen möchten.


Manchmal müssen Sie mit schlecht geschriebenen Bibliotheken oder Software umgehen, die ein "echtes" leeres und vorhandenes Verzeichnis benötigen. Ein einfaches setzen .gitignoreoder .keepkönnte sie brechen und einen Fehler verursachen. Das Folgende kann in diesen Fällen helfen, aber keine Garantie ...

Erstellen Sie zuerst das benötigte Verzeichnis:

mkdir empty

Dann fügen Sie einen beschädigten symbolischen Link zu diesem Verzeichnis hinzu (aber in jedem anderen Fall als dem oben beschriebenen Anwendungsfall verwenden Sie bitte eine READMEmit einer Erklärung):

ln -s .this.directory empty/.keep

Um Dateien in diesem Verzeichnis zu ignorieren, können Sie sie in Ihrem Stammverzeichnis hinzufügen .gitignore:

echo "/empty" >> .gitignore

Um die ignorierte Datei hinzuzufügen, verwenden Sie einen Parameter, um sie zu erzwingen:

git add -f empty/.keep

Nach dem Festschreiben befindet sich in Ihrem Index ein beschädigter symbolischer Link, und git erstellt das Verzeichnis. Der unterbrochene Link hat einige Vorteile, da er keine reguläre Datei ist und auf keine reguläre Datei verweist. Also passt es sogar zu dem Teil der Frage "(der keine Dateien enthält)", nicht nach der Absicht, sondern nach der Bedeutung, denke ich:

find empty -type f

Dieser Befehl zeigt ein leeres Ergebnis, da in diesem Verzeichnis keine Dateien vorhanden sind. Die meisten Anwendungen, die alle Dateien in einem Verzeichnis erhalten, sehen diesen Link normalerweise nicht, zumindest wenn sie eine "Datei existiert" oder ein "lesbar" haben. Sogar einige Skripte finden dort keine Dateien:

$ php -r "var_export(glob('empty/.*'));"
array (
  0 => 'empty/.',
  1 => 'empty/..',
)

Ich empfehle jedoch dringend, diese Lösung nur unter besonderen Umständen zu verwenden. Ein gutes, READMEin ein leeres Verzeichnis geschriebenes ist normalerweise eine bessere Lösung. (Und ich weiß nicht, ob dies mit einem Windows-Dateisystem funktioniert ...)


touch .keep

Unter Linux wird eine leere Datei mit dem Namen .keep . Dieser Name wird gegenüber .gitkeep bevorzugt, da der erstere für Git agnostisch ist, während der letztere für Git spezifisch ist. Zweitens sollte, wie ein anderer Benutzer bemerkt hat, die .git Präfixkonvention für Dateien und Verzeichnisse reserviert sein, die Git selbst verwendet.

Wie in einer anderen answer , kann das Verzeichnis README.md stattdessen eine beschreibende README.md oder README.md Datei enthalten .

Dies setzt natürlich voraus, dass das Vorhandensein der Datei nicht dazu führt, dass Ihre Anwendung beschädigt wird.





git-add