Come posso aggiungere una directory vuota a un repository Git?


4268

Come posso aggiungere una directory vuota (che non contiene file) a un repository Git?


16
Sebbene non sia utile, esiste un modo per hackerare una directory vuota (davvero vuota) nel repository . checkoutTuttavia, non sarà con le versioni attuali di Git.
2

335
@due I non sono d'accordo sul fatto che non sia utile. La gerarchia di directory fa parte del progetto, quindi dovrebbe essere controllata dalla versione.
JBentley,

114
Nel mio caso, vorrei aggiungere una struttura di directory per i file tmp, ma non i file tmp stessi. In questo modo, il mio tester ha la struttura corretta (altrimenti ci sono errori) ma non intasare i miei commit con i dati tmp. Quindi sì, mi è utile!
Adam Marshall,

45
@AdamMarshall Penso che ti stia dicendo che l'hack non è utile, poiché viene ignorato dal checkout. Le directory Tmp sembrano una funzione utile per un VCS.
Quantum7,

31
Perché non avere la procedura che crea i file tmp anche creare la directory tmp?
RyPeck,

Risposte:


4128

Un altro modo per rendere una directory (quasi) vuota (nel repository) è quello di creare un .gitignorefile all'interno di quella directory che contenga queste quattro righe:

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

Quindi non è necessario ottenere l'ordine nel modo giusto nella soluzione di m104 .

Ciò offre anche il vantaggio che i file in quella directory non verranno visualizzati come "non tracciati" quando si esegue uno stato git.

Rendere persistente il commento di @GreenAsJade :

Penso che valga la pena notare che questa soluzione fa esattamente ciò che la domanda è stata posta, ma forse non è ciò che molte persone che stanno cercando questa domanda avrebbero cercato. Questa soluzione garantisce che la directory rimanga vuota. Dice "Non voglio mai veramente fare il check-in dei file qui". Al contrario di "Non ho ancora nessun file da controllare qui, ma ho bisogno della directory qui, i file potrebbero arrivare più tardi".


25
Penso che la soluzione README proposta da @JohnMee dovrebbe essere usata insieme a questa; il file .gitignore fornisce una spiegazione di ciò che vogliamo tenere fuori dal controllo della versione, mentre il file README spiega qual è lo scopo della directory, che sono entrambi informazioni molto importanti.
Pedromanoel,

18
@pedromanoel Scrivo la documentazione che inseriresti READMEall'interno del .gitignorefile (come commenti).
Carlos Campderrós,

69
individuare la differenza 1: 1.) una cartella vuota, 2.) una cartella con il file .gitignore in esso. ;-)
Peter Perháč,

6
Questo è perfetto per le cartelle della cache .
redolent il

10
Sfortunatamente, questo risulta in una directory non vuota, ha un singolo file nascosto.
Pedorro,

1091

Non puoi. Vedi le domande frequenti su Git .

Attualmente la progettazione dell'indice git (area di gestione temporanea) consente solo di elencare i file e nessuno abbastanza competente da apportare la modifica per consentire alle directory vuote di occuparsi di questa situazione abbastanza da rimediare.

Le directory vengono aggiunte automaticamente quando si aggiungono file al loro interno. Cioè, le directory non devono mai essere aggiunte al repository e non vengono tracciate da sole.

Puoi dire " git add <dir>" e aggiungerà i file lì dentro.

Se hai davvero bisogno di una directory per i checkout, devi creare un file al suo interno. .gitignore funziona bene per questo scopo; puoi lasciarlo vuoto o inserire i nomi dei file che ti aspetti di apparire nella directory.


67
Di seguito la risposta è MOLTO migliore. Il fatto che git il software di basso livello non lo consenta non mi importa tanto quanto COME usare effettivamente Git quando ho bisogno di una directory vuota. Aggiungere un 2g .gitignore mi sembra accettabile.
Amala,

1
Bene, se si desidera spostare i file in una nuova directory, non possono farlo perché git mvgit si lamenterà che la nuova directory non è sotto il controllo della versione
lulalala,

16
Puoi leggere " è impossibile, non puoi, ecc. " Su Internet per questa domanda frequente. Il .gitignoretrucco è una risposta frequente e soddisfa molte esigenze. Comunque è possibile rendere git track una directory veramente vuota , vedi la mia risposta
ofavre

2
Sebbene più ci penso, più sembra che "hash SHA della stringa vuota", se esiste, in realtà sarebbe un identificatore ben definito per un albero vuoto, a meno che non sia impossibile dire se quell'oggetto sia un albero o una chiazza.
Emil Lundberg,

21
Ho visto molti repository che usano un file vuoto chiamato .gitkeepper questo scopo.
Sukima,

759

Crea un file vuoto chiamato .gitkeepnella directory e aggiungilo.


58
Ho invece aggiunto una risposta che incoraggia a creare .keep.
Acumenus,

206
.gitkeepnon è stato prescritto da Git e indurrà le persone a indovinarne il significato, il che li porterà a ricerche su Google, che li condurranno qui. La .gitconvenzione del prefisso dovrebbe essere riservata ai file e alle directory che Git stesso utilizza.
Martedì

10
@ t-mart "La .gitconvenzione del prefisso dovrebbe essere riservata ..." Perché? Git richiede questa prenotazione?
Espiazione limitata il

9
In questo caso un file READMEo ABOUTsarebbe altrettanto buono o migliore. Lasciare una nota per il prossimo, proprio come facevamo tutti prima degli URL.
Dave,

5
Non funziona se stai scrivendo un unit test che dovrebbe testare il codice su una directory vuota ...
thebjorn,

437

È sempre possibile inserire un file README nella directory con una spiegazione del motivo per cui si desidera questa directory, altrimenti vuota, nel repository.


39
+1, buon suggerimento, una directory vuota non ha alcun senso a meno che non venga utilizzata in futuro. Quindi crea un file README al suo interno e scrivi a cosa serve questa directory e quali file verranno inseriti in futuro. Ciò risolve entrambi i due problemi.
Saeedgnu,

63
@ilius Nonsense. Una struttura di directory contenente directory vuote può essere altamente desiderabile in molte situazioni (come un'app MVC in cui si desidera una directory di modelli ma non si è ancora arrivati ​​alla creazione di alcun modello o una directory di viste condivise a cui si prevede di aggiungere viste condivise in un secondo momento ). Inoltre, inserire un README in ognuno di questi è eccessivo in quanto è ovvio a cosa servono, ed è facile dimenticare di inserire un README in ognuno di essi. E devi ricordare di rimuovere il file README quando aggiungi altri file ad essi. Fondamentalmente, git dovrebbe sicuramente consentire directory vuote.
Jez,

20
@Jez: non sono d'accordo. Il punto è che git è progettato per controllare (e indicizzare) il codice sorgente. È importante sottolineare che l'id di un commit è un hash del contenuto. Vale a dire, deve avere dei contenuti. Non hai bisogno di un README in ogni parte dell'albero, solo nodi foglia. Se hai dei posti in cui intendi inserire il codice, ma nessun codice, e non ti prenderai nemmeno il tempo di fare eco a "posto per i modelli" >> README, allora quello che hai è un'idea, non un commit. Non è interessante git. Dire "Voglio che l'app in esecuzione abbia directory vuote XYZ" è un problema di runtime , non di origine. Gestiscilo con il tuo installatore.
Joe Atzberger,

6
@JoeAtzberger È una caratteristica mancante, non una limitazione intenzionale. Dalle domande frequenti su Git: attualmente la progettazione dell'indice Git (area di gestione temporanea) consente solo di elencare i file e nessuno abbastanza competente da apportare la modifica per consentire alle directory vuote di occuparsi di questa situazione abbastanza da rimediare.
jbo5112,

7
@ jbo5112 Sì, il "codice speciale" a cui fai riferimento è l '"installatore" che ho citato. La tua installazione di webapp deve già gestire la creazione di un database, la configurazione locale, l'estrazione di dipendenze o altre 100 operazioni, ma un paio di directory vuote sono oltre? Prova Gradle, Passeggero, Chef, un Makefile primitivo, ecc. Non vi è alcuna differenza di sicurezza tra la creazione di directory e l'altra (potenzialmente molto più complicata / pericolosa) installazione di un'app. E se davvero non hai deps, config, DB, ecc. E nessun programma di installazione, usa semplicemente README. Nessun caso richiede di fare entrambe le cose.
Joe Atzberger,

349
touch .keep

Su Linux, questo crea un file vuoto chiamato .keep. Per quello che vale, questo nome è agnostico per Git, mentre .gitkeepsarebbe specifico per Git. In secondo luogo, come ha notato un altro utente, la .gitconvenzione del prefisso dovrebbe essere riservata ai file e alle directory che Git stesso utilizza.

In alternativa, come indicato in un'altra risposta , la directory può contenere invece un descrittivo READMEo un README.mdfile .

Naturalmente ciò richiede che la presenza del file non causi l'interruzione dell'applicazione.


1
Questo è utile per una directory vuota iniziale, ma cosa succede se inizia a riempirsi di file? Quindi Git li noterà e li rivendicherà come file non tracciati. La risposta selezionata qui funziona in modo molto più elegante per consentire di mantenere una directory ma quindi ignorare in sicurezza i contenuti.
Jake Gould

14
La domanda e la preoccupazione generale predominante riguarda l'aggiunta di una directory vuota. Se in seguito ha un file residente, ovviamente eliminare il .keepfile o ignorarlo. Se invece i file nella directory devono essere ignorati, questa è una domanda completamente diversa.
Acumenus,

3
È stato suggerito che git clean -nd | sed s/'^Would remove '// | xargs -I{} touch "{}.keep"lo farà in tutte le directory vuote non tracciate.
Acumenus,

1
Non mi piace questa soluzione, è difficile indovinare cosa fa questo file. Inoltre, se stai generando file nel tuo ambiente di sviluppo (come registri o immagini, ecc.), Ciò non impedisce a questi file di essere sottoposti a versione e si sta facendo strada nella produzione, il che non è carino.
danielrvt,

1
A Windows non piacciono i file senza nome e richiede una magia speciale per raggiungere questo obiettivo (ovvero un'app terminale simile a bash o equivalente).
EntangledLoops

303

Perché dovremmo aver bisogno di cartelle vuote con versione

Cominciando dall'inizio:

Una directory vuota non può far parte di un albero nel sistema di versioning Git .

Semplicemente non verrà tracciato. Ma ci sono scenari in cui le directory vuote "versioning" possono essere significative, ad esempio:

  • impalcatura di una struttura di cartelle predefinita , rendendola disponibile per ogni utente / collaboratore del repository; o, come caso specializzato di cui sopra, creando una cartella per file temporanei , come una directory cache/o logs/, dove vogliamo fornire la cartella ma il .gitignoresuo contenuto
  • in relazione a quanto sopra, alcuni progetti non funzioneranno senza alcune cartelle (che è spesso un suggerimento di un progetto mal progettato, ma è uno scenario del mondo reale frequente e forse potrebbero esserci, diciamo, problemi di autorizzazione da affrontare).

Alcuni suggerimenti suggeriti

Molti utenti suggeriscono:

  1. Posizionamento di un READMEfile o di un altro file con alcuni contenuti per rendere la directory non vuota, oppure
  2. Creare un .gitignorefile con una sorta di "logica inversa" (cioè includere tutti i file) che, alla fine, ha lo stesso scopo dell'approccio n. 1.

Mentre entrambe le soluzioni sicuramente funzionano, le trovo incompatibili con un approccio significativo al controllo delle versioni di Git.

  • Perché dovresti mettere file fasulli o README che forse non vuoi davvero nel tuo progetto?
  • Perché usare .gitignoreper fare una cosa ( conservare i file) che è esattamente l'opposto di ciò che significa ( escludere i file), anche se è possibile?

approccio .gitkeep

Utilizzare un file vuoto chiamato .gitkeepper forzare la presenza della cartella nel sistema di controllo delle versioni.

Anche se potrebbe non sembrare una differenza così grande:

  • Si utilizza un file che ha il solo scopo di conservare la cartella. Non ci metti nessuna informazione che non vuoi mettere.

    Ad esempio, dovresti usare README come pure README con informazioni utili, non come una scusa per conservare la cartella.

    La separazione delle preoccupazioni è sempre una buona cosa e puoi ancora aggiungere un .gitignoreper ignorare i file indesiderati.

  • Denominarlo .gitkeeprende molto chiaro e semplice dal nome del file stesso (e anche ad altri sviluppatori , il che è buono per un progetto condiviso e uno degli scopi principali di un repository Git) che questo file è

    • Un file non correlato al codice (a causa del punto iniziale e del nome)
    • Un file chiaramente correlato a Git
    • Il suo scopo ( mantenere ) è chiaramente dichiarato e coerente e semanticamente opposto nel suo significato da ignorare

Adozione

Ho visto l' .gitkeepapproccio adottato da quadri molto importanti come Laravel , Angular-CLI .


8
Ti sei perso un pensiero: qual è il motivo per mantenere e svuotare la cartella (ad esempio / logs, / tmp, / uploads)? Sì, è per mantenere vuota la cartella. :) Quindi se vuoi mantenere una cartella vuota, devi ignorare i file al suo interno.
Roman,

14
@RomanAllenstein: non necessariamente. È possibile che si crei un repository con una determinata struttura che può essere popolata in seguito. Questi file verranno aggiunti al repository non appena vengono creati e sarà fastidioso iniziare a eliminare o modificare i file .gitignore (e pericoloso, perché probabilmente non ti rendi nemmeno conto che non vengono tracciati: git li sta ignorando )
blueFast,

45
@Behnam: prenderò il voto negativo, ma la mia ricerca sulla meta SO non mostra alcuna preoccupazione per le risposte dettagliate, purché forniscano dettagli e chiarezza sufficienti per essere utili per ogni lettore (e ogni livello di abilità). Tuttavia sono molto aperto a qualsiasi critica e grazie per aver dichiarato pubblicamente il motivo, lo prendo molto positivamente.
Cranio,

4
Se modifichi la tua risposta per sostituirla .gitkeepcon qualsiasi altro nome di file senza prefisso che ottieni il mio voto, penso che questa sia la risposta migliore e più istruttiva. Motivo: penso che ".git *" dovrebbe essere riservato ai file prescritti da git, mentre questo è solo un semplice segnaposto. La mia prima ipotesi quando ho visto che ad esempio un file ".gitkeep" verrebbe ignorato automaticamente (sarebbe una bella caratteristica) ma non è così, giusto?
Johnny,

5
Mi chiedo perché la gente abbia difficoltà a capire perché si vuole aggiungere cartelle "vuote" a Git. Devi iniziare da qualche parte, giusto? Quindi, di solito inizi con la struttura delle cartelle dei tuoi progetti e - ahimè - all'inizio del progetto non c'è ancora nulla. Una volta terminato il repository del progetto, i lavoratori del team possono clonare e iniziare a lavorare sulla struttura SAME.
BitTickler,

127

Come descritto in altre risposte, Git non è in grado di rappresentare directory vuote nell'area di gestione temporanea. (Vedi le FAQ di Git .) Tuttavia, se, per i tuoi scopi, una directory è abbastanza vuota se contiene .gitignoresolo un file, puoi creare .gitignorefile in directory vuote solo tramite:

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

21
Si consiglia di ignorare la directory .git: find . -name .git -prune -o -type d -empty -exec touch {}/.gitignore \;
steffen

3
Una variazione più semplice per la maggior parte delle situazioni èfind * -type d -empty -exec touch {}/.gitignore \;
akhan il

2
Poiché OS X crea un file .DS_Store in quasi tutte le directory, questo non funziona lì. L'unica soluzione (PERICOLOSA!) Che ho trovato è stata quella di eliminare prima tutti i file .DS_Store find . -name .DS_Store -exec rm {} \;e quindi utilizzare la variante preferita da questa risposta. Assicurati di eseguirlo solo nella cartella corretta!
zerweck,

1
Qualcuno sa un modo per farlo in Windows dalla riga di comando? Ho visto alcune soluzioni qui in Ruby e Python, ma mi piacerebbe una soluzione barebone se può essere gestita.
Mig82,

1
@akhan L'aggiunta di qualcosa a .gitignorenon ha influenza sulla -emptybandiera del findcomando. Il mio commento riguarda la rimozione dei .DS_Storefile in un albero di directory, quindi il -emptyflag può essere applicato.
zerweck,

68

Andy Lester ha ragione, ma se la tua directory deve solo essere vuota e non vuota vuota, puoi inserire un .gitignorefile vuoto come soluzione alternativa.

A parte questo, questo è un problema di implementazione, non un problema di progettazione dello storage Git fondamentale. Come è stato menzionato molte volte nella mailing list di Git, la ragione per cui questo non è stato implementato è che nessuno si è preoccupato abbastanza di inviargli una patch, non che non potesse o non avrebbe dovuto essere fatto.


4
Questo è esattamente quello che ho detto. Entrambi i paragrafi sono trattati nel frammento di FAQ che ho pubblicato.
Andy Lester,

1
Penso che il lato non sia interessante e utile da sapere: può essere risolto, ma non aspettartelo in qualsiasi momento presto quando c'è una soluzione così facile per la maggior parte dei casi.
wnoise,

Mi dispiace, non ho letto l'ultimo paragrafo e mentre ho letto il primo paragrafo, beh, non sono sicuro del motivo per cui ho ripetuto queste informazioni.
Aristotele Pagaltzis,

2
Naturalmente, questa risposta aggiuntiva serve a sottolineare il fatto.
Michael Johnson,

Sono arrivato qui a guardare un caso in cui la build è caduta se la directory non esiste e per impostazione predefinita è vuota, ma non deve essere vuota. Creare un .gitignore fa la cosa giusta.
Giosuè,

33

Il modo di creazione della cartella di registro di Ruby on Rails :

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

Ora la directory di registro verrà inclusa nella struttura. È molto utile durante la distribuzione, quindi non sarà necessario scrivere una routine per creare directory di registro.

I file di registro possono essere esclusi emettendo,

echo log/dev.log >> .gitignore

ma probabilmente lo sapevi.


23
Cosa c'entra questo con Ruby on Rails?
Domande Quolonel,


30

Git non tiene traccia di directory vuote. Vedi le Domande frequenti su Git per ulteriori spiegazioni. La soluzione suggerita è quella di mettere un .gitignorefile nella directory vuota. Non mi piace quella soluzione, perché .gitignoreè "nascosta" dalla convenzione Unix. Inoltre non vi è alcuna spiegazione del perché le directory siano vuote.

Suggerisco di mettere un file README nella directory vuota spiegando perché la directory è vuota e perché deve essere tracciata in Git. Con il file README in atto, per quanto riguarda Git, la directory non è più vuota.

La vera domanda è: perché hai bisogno della directory vuota in git? Di solito hai una sorta di script di compilazione che può creare la directory vuota prima di compilare / eseguire. Altrimenti, creane uno. Questa è una soluzione di gran lunga migliore rispetto a mettere directory vuote in git.

Quindi hai qualche motivo per cui hai bisogno di una directory vuota in git. Inserisci questo motivo nel file README. In questo modo altri sviluppatori (e in futuro tu) sanno perché la directory vuota deve essere lì. Saprai anche che puoi rimuovere la directory vuota quando il problema che richiede la directory vuota è stato risolto.


Per elencare ogni directory vuota, utilizzare il seguente comando:

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

Per creare i README del segnaposto in ogni directory vuota:

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

Per ignorare tutto nella directory tranne il file README, inserisci le seguenti righe nel tuo .gitignore:

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

In alternativa, puoi semplicemente escludere ogni file README dall'ignorare:

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

Per elencare tutti i README dopo che sono già stati creati:

find -name README.emptydir

28

ATTENZIONE: Questo tweak non funziona davvero come risulta. Ci dispiace per l'inconvenienza.

Post originale qui sotto:

Ho trovato una soluzione giocando con gli interni di Git!

  1. Supponi di essere nel tuo repository.
  2. Crea la tua directory vuota:

    $ mkdir path/to/empty-folder
    
  3. Aggiungilo all'indice usando un comando idraulico e l'albero vuoto SHA-1 :

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

    Digita il comando e quindi inserisci la seconda riga. Premere Entere quindi Ctrl+ Dper terminare l'immissione. Nota: il formato è in modalità [SPACE] tipo [SPACE] SHA-1hash [TAB] percorso (la scheda è importante, la formattazione della risposta non la conserva).

  4. Questo è tutto! La tua cartella vuota è nel tuo indice. Tutto quello che devi fare è impegnarti.

Questa soluzione è breve e apparentemente funziona bene ( vedi EDIT! ), Ma non è così facile da ricordare ...

L'albero vuoto SHA-1 può essere trovato creando un nuovo repository Git vuoto, cdin esso ed emissione git write-tree, che genera l'albero vuoto SHA-1.

MODIFICARE:

Sto usando questa soluzione da quando l'ho trovata. Sembra funzionare esattamente come la creazione di un sottomodulo, tranne per il fatto che nessun modulo è definito da nessuna parte. Questo porta ad errori durante l'emissione git submodule init|update. Il problema è che git update-indexriscrive la 040000 treeparte in 160000 commit.

Inoltre, qualsiasi file inserito in quel percorso non verrà mai notato da Git, poiché ritiene che appartengano ad altri repository. Questo è brutto in quanto può essere facilmente trascurato!

Tuttavia, se non hai già (e non vuoi) utilizzare alcun sottomodulo Git nel tuo repository e la cartella "vuota" rimarrà vuota o se vuoi che Git sappia della sua esistenza e ignori il suo contenuto, puoi andare con questo tweak. Seguire la solita maniera con i sottomoduli richiede più passaggi di questo tweak.


Dopo aver inserito la cartella vuota nell'indice e aver eseguito il commit, è quindi possibile git svn dcommitcon il risultato desiderato?
Espiazione limitata il

2
È improbabile che questo tweak funzioni con qualsiasi altro strumento. Come indicato nell'avvertimento e nella modifica, scoraggio di usarlo se non in un caso abbastanza limitato.
ofavre,

1
E ovviamente questo è il motivo per cui fare confusione con gli interni git è controindicato.
Casey,

@abhisekp Come è possibile?
PyRulez,

1
@PyRulez bene, nel mondo del software, nulla è impossibile. : D In realtà, ho seguito la risposta.
Abhisekp,

21

Diciamo che hai bisogno di una directory vuota chiamata tmp :

$ mkdir tmp
$ touch tmp/.gitignore
$ git add tmp
$ echo '*' > tmp/.gitignore
$ git commit -m 'Empty directory' tmp

In altre parole, è necessario aggiungere il file .gitignore all'indice prima di poter dire a Git di ignorarlo (e tutto il resto nella directory vuota).


12
Due cose: potresti semplicemente "echo '*'> tmp / .gitignore" invece di toccare, e "git commit -m" non commette le modifiche fatte dopo aver aggiunto i file all'indice.
Christoffer Hammarström,

6
Se lo fai echo bla > filenon otterrai file: File existsperché >sovrascriverà il file se è già presente o ne creerà uno nuovo se non esiste.
psyrendust

3
/bin/shpresupposto culturale! * Se "qui" è cshe la variabile noclobberè impostata, otterrai davvero file: File exists. Se qualcuno dice "Capisco", non dare per scontato che siano un idiota e rispondi "No, non lo fai". * C2.com/cgi/wiki?AmericanCulturalAssumption
clacke

1
@clacke Se qualcuno decide di usare una shell diversa rispetto a tutti gli altri, dovrebbe dichiararlo espressamente in caso di problemi. A differenza della nazionalità, ognuno ha la propria scelta libera di shell.
SeldomNeedy,

2
@SeldomNeedy Forse stanno cercando aiuto perché non sanno nemmeno che stanno usando una shell diversa rispetto a tutti gli altri.
clacke,

20

Forse l'aggiunta di una directory vuota sembra che sarebbe il percorso di minor resistenza perché hai degli script che prevedono che quella directory esista (forse perché è una destinazione per i binari generati). Un altro approccio sarebbe quello di modificare i tuoi script per creare la directory come necessario .

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

In questo esempio, è possibile archiviare un collegamento simbolico (interrotto) alla directory in modo da potervi accedere senza il prefisso ".generated" (ma questo è facoltativo).

ln -sf .generated/bin bin
git add bin

Quando vuoi ripulire l'albero dei sorgenti puoi semplicemente:

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

Se si adotta l'approccio spesso suggerito per il controllo in una cartella quasi vuota, si ha la minore complessità di eliminare il contenuto senza eliminare anche il file ".gitignore".

Puoi ignorare tutti i tuoi file generati aggiungendo quanto segue al tuo .gitignore root:

.generated

1
Nota: il collegamento simbolico che ho suggerito è "interrotto" in un checkout pulito perché la .generateddirectory inizialmente non esiste. Non sarà più rotto una volta che hai fatto la tua build.
nobar

2
Sono d'accordo in alcuni casi questa è un'ottima idea, ma in altri (come distribuire un progetto in cui hai uno scheletro altrimenti vuoto con cartelle come modelli / e viste /) vorresti che l'utente avesse queste directory a portata di mano piuttosto che dover leggere manualmente leggere i documenti, e potrebbe essere un po 'troppo aspettarsi che eseguano una sorta di script di installazione dopo aver clonato il repository. Penso che questa risposta in combinazione con la risposta README di @ john-mee dovrebbe coprire la maggior parte, se non tutti i casi.
Moopet,

14

Ho affrontato il problema anche con directory vuote. Il problema con l'utilizzo dei file segnaposto è che è necessario crearli ed eliminarli, se non sono più necessari (perché in seguito sono stati aggiunti sottodirectory o file. Con alberi di origine di grandi dimensioni la gestione di questi file segnaposto può essere ingombrante ed errore prona.

Questo è il motivo per cui ho deciso di scrivere uno strumento open source in grado di gestire automaticamente la creazione / cancellazione di tali file segnaposto. È scritto per la piattaforma .NET e funziona su Mono (.NET per Linux) e Windows.

Dai un'occhiata a: http://code.google.com/p/markemptydirs


14

Mi piacciono le risposte di @ Artur79 e @mjs, quindi ho usato una combinazione di entrambi e l'ho resa uno standard per i nostri progetti.

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

Tuttavia, solo una manciata dei nostri sviluppatori lavora su Mac o Linux. Molto lavoro su Windows e non sono riuscito a trovare un semplice one-liner equivalente per ottenere lo stesso risultato. Alcuni hanno avuto la fortuna di installare Cygwin per altri motivi, ma prescrivere Cygwin solo per questo sembrava eccessivo.

Modifica per una soluzione migliore

Quindi, dal momento che la maggior parte dei nostri sviluppatori ha già installato Ant , la prima cosa che ho pensato è stata quella di mettere insieme un file di build Ant per farlo indipendentemente dalla piattaforma. Questo può ancora essere trovato qui

Tuttavia , in seguito ho pensato che sarebbe stato meglio trasformarlo in un piccolo comando di utilità, quindi l'ho ricreato usando Python e l'ho pubblicato su PyPI qui . Puoi installarlo semplicemente eseguendo:

pip3 install gitkeep2

Ti consentirà di creare e rimuovere i .gitkeepfile in modo ricorsivo e ti consentirà inoltre di aggiungere loro dei messaggi affinché i tuoi colleghi possano capire perché tali directory sono importanti. Quest'ultimo bit è bonus. Ho pensato che sarebbe bello se i .gitkeepfile potessero essere auto-documentati.

$ gitkeep --help
Usage: gitkeep [OPTIONS] PATH

  Add a .gitkeep file to a directory in order to push them into a Git repo
  even if they're empty.

  Read more about why this is necessary at: https://git.wiki.kernel.org/inde
  x.php/Git_FAQ#Can_I_add_empty_directories.3F

Options:
  -r, --recursive     Add or remove the .gitkeep files recursively for all
                      sub-directories in the specified path.
  -l, --let-go        Remove the .gitkeep files from the specified path.
  -e, --empty         Create empty .gitkeep files. This will ignore any
                      message provided
  -m, --message TEXT  A message to be included in the .gitkeep file, ideally
                      used to explain why it's important to push the specified
                      directory to source control even if it's empty.
  -v, --verbose       Print out everything.
  --help              Show this message and exit.

Spero che lo trovi utile.


13

Non puoi e sfortunatamente non sarai mai in grado di farlo. Questa è una decisione presa dallo stesso Linus Torvald. Sa cosa è buono per noi.

C'è uno sfogo là fuori che ho letto una volta.

Ho trovato Re: Directory vuote ... , ma forse ce n'è un'altra.

Devi convivere con le soluzioni alternative ... purtroppo.


1
So che hai pubblicato questo come esempio di un cattivo argomento, ma apprezzo il link perché in realtà è un argomento ben ragionato contro il monitoraggio delle directory. ;-)
clacke il

1
Questa risposta sembra essere incoerente, poiché nel prossimo post sul thread di riferimento, Linus Torvald afferma di aspettarsi che dovranno aggiungere il monitoraggio delle directory: markmail.org/message/libip4vpvvxhyqbl . In effetti, dice che "gradirebbe le patch che [aggiungono supporto per il tracciamento di directory vuote]"
Patrick M

Patrick, usa anche la parola "idiota" lì. Ho il sospetto che le sue parole indirizzino le persone qui in questo thread e quindi presumo che non implementerà qualcosa di "idiota" in Git da solo.
user2334883

10

Quando aggiungi un .gitignorefile, se hai intenzione di mettere qualsiasi quantità di contenuto (che vuoi che Git ignori) potresti voler aggiungere una sola riga con solo un asterisco *per assicurarti di non aggiungere accidentalmente il contenuto ignorato .


9

Non c'è modo di convincere Git a tenere traccia delle directory, quindi l'unica soluzione è quella di aggiungere un file segnaposto all'interno della directory che Git deve tenere traccia.

Il file può essere nominato e contenere tutto ciò che vuoi, ma la maggior parte delle persone usa un file vuoto chiamato .gitkeep(sebbene alcune persone preferiscano il VCS-agnostico .keep).

Il prefisso lo .contrassegna come un file nascosto.

Un'altra idea sarebbe quella di aggiungere un READMEfile che spiega a cosa servirà la directory.


8

Come accennato, non è possibile aggiungere directory vuote, ma qui c'è una riga che aggiunge file vuoti .gitignore a tutte le directory.

ruby -e 'require "fileutils" ; Dir.glob(["target_directory","target_directory/**"]).each { |f| FileUtils.touch(File.join(f, ".gitignore")) if File.directory?(f) }'

L'ho bloccato in un Rakefile per un facile accesso.


6
Preferirei usarefind . -type d -empty -print0 | xargs --null bash -c 'for a; do { echo "*"; echo "!.gitignore"; } >>"$a/.gitignore"; done' --
Tino il

8

La soluzione di Jamie Flournoy funziona alla grande. Ecco una versione leggermente migliorata per mantenere .htaccess:

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

Con questa soluzione è possibile eseguire il commit di una cartella vuota, ad esempio /log, /tmpoppure /cachela cartella rimarrà vuota.


2
Vuole mantenere una directory vuota e non un file.
gvsrepins,

2
E ho detto che manterrà anche il .htaccess. Esempio: se un software ha una directory per i file di log (come ossido di eshop) che non dovrebbe essere accessibile via web, c'è un .htaccess nella directory. Se si inserisce il .gitignore sopra menzionato nella cartella, il .htaccess non verrà inserito e la cartella sarà accessibile via web.
Roman,

Se hai un file .htaccess che è sotto il controllo della versione, allora hai già la directory che lo contiene sotto il controllo della versione. Pertanto, il problema è già risolto: il file .gitignore diventa irrilevante.
Ponkadoodle,

1
@Wallacoloo In relazione alla domanda che hai ragione, tuttavia il file è utile, lo userò per una directory di upload come quella in cui i file devono essere protetti da .htaccess. Contrariamente alla spiegazione dei romani, il file .htaccess verrà commesso in quanto escluso dalla regola ignore. [vecchio thread, lo so]
David,

7

Costruisco sempre una funzione per verificare la struttura delle cartelle desiderata e crearla per me all'interno del progetto. Questo risolve questo problema poiché le cartelle vuote sono mantenute in Git dal proxy.

function check_page_custom_folder_structure () {
    if (!is_dir(TEMPLATEPATH."/page-customs"))
        mkdir(TEMPLATEPATH."/page-customs");    
    if (!is_dir(TEMPLATEPATH."/page-customs/css"))
        mkdir(TEMPLATEPATH."/page-customs/css");
    if (!is_dir(TEMPLATEPATH."/page-customs/js"))
        mkdir(TEMPLATEPATH."/page-customs/js");
}

Questo è in PHP, ma sono sicuro che la maggior parte delle lingue supporta la stessa funzionalità e poiché l'applicazione delle cartelle è curata dall'applicazione, le cartelle saranno sempre lì.


2
Solo così siamo tutti sulla stessa pagina, non lo faccio più. È una perdita di tempo. La .gitkeepconvenzione è una pratica molto migliore.
Lieve Fuzz,

Non riesco a vedere come questo possa essere una perdita di tempo. Quando TEMPLATEPATH è ovviamente dinamico non è possibile utilizzare la soluzione .gitkeep. E anche con una struttura di cartelle non dinamica dovresti aggiungere un po 'di roba in più invece di rimuovere l'ottima soluzione di controllare le directory, ad es. Controlla i permessi e chmod i file. Aggiungere un modo per contrassegnare le directory all'interno di un .gitignore globale sarebbe perfetto per me. Qualcosa come #keep / path / to / dir
Jochen Schultz,

7

Ecco un trucco, ma è divertente che funzioni (Git 2.2.1). Simile a quanto suggerito da @Teka, ma più facile da ricordare:

  • Aggiungi un sottomodulo a qualsiasi repository ( git submodule add path_to_repo)
  • Ciò aggiungerà una cartella e un file .submodules. Commetti un cambiamento.
  • Elimina il .submodulesfile e conferma la modifica.

Ora, hai una directory che viene creata quando viene eseguito il checkout. Una cosa interessante è che se guardi il contenuto dell'oggetto albero di questo file otterrai:

fatale: nome oggetto non valido b64338b90b4209263b50244d18278c0999867193

Non incoraggerei a usarlo anche se potrebbe smettere di funzionare nelle future versioni di Git. Il che potrebbe lasciare corrotto il tuo repository.


Questo in realtà funziona ma penso che confonda il diavolo di IntelliJ ...: |
rogerdpack,

Ho creato una soluzione migliore in base a questo che non dispone di questi inconvenienti: stackoverflow.com/a/58543445/277882
ntninja

7

Molti hanno già risposto a questa domanda. Basta aggiungere una versione di PowerShell qui.

Trova tutte le cartelle vuote nella directory

Aggiungi un file .gitkeep vuoto lì dentro

Get-ChildItem 'Path to your Folder' -Recurse -Directory | Where-Object {[System.IO.Directory]::GetFileSystemEntries($_.FullName).Count -eq 0} | ForEach-Object { New-Item ($_.FullName + "\.gitkeep") -ItemType file}

Nice.‌‌ ༼ ͡☉ ͜ʖ ͡☉ ༽
FiringSquadWitness

6

Se vuoi aggiungere una cartella che ospiterà molti dati transitori in più directory semantiche, un approccio è quello di aggiungere qualcosa di simile alla tua radice .gitignore ...

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

Quindi è possibile eseguire il commit di file README.md descrittivi (o file vuoti, non importa, purché sia ​​possibile indirizzarli in modo univoco come *.mdin questo caso) in ciascuna directory per assicurarsi che tutte le directory rimangano parte del repository ma il i file (con estensioni) vengono ignorati. LIMITAZIONE: .i nomi di directory non sono consentiti!

Puoi riempire tutte queste directory con file xml / images o qualsiasi altra cosa e aggiungere più directory /app/data/nel tempo man mano che le esigenze di archiviazione per la tua app si sviluppano (con i file README.md che servono a masterizzare in una descrizione di ciò per cui ogni directory di archiviazione è destinata Esattamente).

Non è necessario modificare ulteriormente .gitignoreo decentralizzare creando un nuovo .gitignoreper ogni nuova directory. Probabilmente non è la soluzione più intelligente ma è concisa dal punto di vista gitignore e funziona sempre per me. Bello e semplice! ;)

inserisci qui la descrizione dell'immagine


6

Un modo semplice per farlo è quello di aggiungere un .gitkeepfile alla directory che desideri (attualmente) vuota.

Vedi questa risposta SOF per ulteriori informazioni - il che spiega anche perché alcune persone trovano confusa la convenzione concorrente di aggiungere un file .gitignore (come indicato in molte risposte qui).


4

Aggiungendo un'altra opzione alla mischia.

Supponendo che tu voglia aggiungere una directory a gitquella, per tutti gli scopi correlati git, dovrebbe rimanere vuota e non avere mai il suo contenuto monitorato, .gitignorecome suggerito più volte qui, farà il trucco.

Il formato, come detto, è:

*
!.gitignore

Ora, se vuoi un modo per farlo dalla riga di comando, in un colpo solo, mentre all'interno della directory che vuoi aggiungere, puoi eseguire:

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

Io stesso ho uno script di shell che uso per fare questo. Assegna un nome allo script come desideri e aggiungilo da qualche parte nel percorso di inclusione oppure fai riferimento direttamente a:

#!/bin/bash

dir=''

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

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

Con questo, puoi eseguirlo dall'interno della directory che desideri aggiungere o fare riferimento alla directory poiché è il primo e unico parametro:

$ ignore_dir ./some/directory

Un'altra opzione (in risposta a un commento di @GreenAsJade), se si desidera tenere traccia una cartella vuota che MAGGIO contengono file monitorati in futuro, ma sarà vuoto, per ora, è possibile ommit il *dal .gitignorefile e verificare che in. In sostanza, tutti i file sta dicendo è "non ignorare me ", ma per il resto, la directory è vuota e monitorati.

Il tuo .gitignorefile sarebbe simile a:

!.gitignore

Ecco fatto, controlla quello e hai una directory vuota, ma tracciata, in cui puoi tracciare i file in un secondo momento.

Il motivo per cui suggerisco di mantenere una riga nel file è che fornisce lo .gitignorescopo. Altrimenti, qualcuno lungo la linea potrebbe pensare di rimuoverlo. Potrebbe essere utile inserire un commento sopra la riga.


4

A volte devi avere a che fare con librerie o software scritti male, che hanno bisogno di una directory "reale" vuota ed esistente. Mettere un semplice .gitignoreo .keeppotrebbe romperli e causare un bug. Quanto segue potrebbe aiutare in questi casi, ma nessuna garanzia ...

Innanzitutto creare la directory necessaria:

mkdir empty

Quindi aggiungi un collegamento simbolico interrotto a questa directory (ma in qualsiasi altro caso diverso dal caso d'uso sopra descritto, utilizza un READMEcon una spiegazione):

ln -s .this.directory empty/.keep

Per ignorare i file in questa directory, è possibile aggiungerlo nella radice .gitignore:

echo "/empty" >> .gitignore

Per aggiungere il file ignorato, utilizzare un parametro per forzarlo:

git add -f empty/.keep

Dopo il commit hai un link simbolico interrotto nel tuo indice e git crea la directory. Il collegamento interrotto presenta alcuni vantaggi, poiché non è un file normale e non indica alcun file normale. Quindi si adatta anche alla parte della domanda "(che non contiene file)", non per l'intenzione ma per il significato, immagino:

find empty -type f

Questo comando mostra un risultato vuoto, poiché in questa directory non sono presenti file. Quindi la maggior parte delle applicazioni, che ottengono tutti i file in una directory di solito non vedono questo link, almeno se fanno un "file esiste" o un "è leggibile". Anche alcuni script non troveranno alcun file lì:

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

Ma consiglio vivamente di usare questa soluzione solo in circostanze speciali, una buona scrittura READMEin una directory vuota è di solito una soluzione migliore. (E non so se questo funziona con un filesystem di Windows ...)


4

Leggendo le risposte di @ofavre e @ stanislav-bashkyrtsev usando riferimenti a sottomodulo GIT rotti per creare le directory GIT, sono sorpreso che nessuno abbia ancora suggerito questo semplice emendamento dell'idea per rendere il tutto sano e sicuro:

Invece di hackerare un sottomodulo falso in GIT , basta aggiungerne uno vuoto .

Immettere: https://gitlab.com/empty-repo/empty.git

Un repository GIT con esattamente un commit:

commit e84d7b81f0033399e325b8037ed2b801a5c994e0
Author: Nobody <none>
Date: Thu Jan 1 00:00:00 1970 +0000

Nessun messaggio, nessun file impegnato.

uso

Per aggiungere una directory vuota al repository GIT:

git submodule add https://gitlab.com/empty-repo/empty.git path/to/dir

Per convertire tutte le directory vuote esistenti in sottomoduli:

find . -type d -empty -delete -exec git submodule add -f https://gitlab.com/empty-repo/empty.git \{\} \;

Git memorizzerà l'ultimo hash di commit durante la creazione del riferimento del sottomodulo, quindi non devi preoccuparti di me (o GitLab) che lo utilizza per iniettare file dannosi. Purtroppo non ho trovato alcun modo per forzare l'ID commit utilizzato durante il checkout, quindi dovrai verificare manualmente che l'ID commit di riferimento siae84d7b81f0033399e325b8037ed2b801a5c994e0 utilizzando git submodule statusdopo aver aggiunto il repository.

Non è ancora una soluzione nativa, ma probabilmente il meglio che possiamo avere senza che qualcuno metta le mani davvero , molto sporco nella base di codice GIT.

Appendice: ricreare questo commit

Dovresti essere in grado di ricreare questo commit esatto usando (in una directory vuota):

# Initialize new GIT repository
git init

# Set author data (don't set it as part of the `git commit` command or your default data will be stored as “commit author”)
git config --local user.name "Nobody"
git config --local user.email "none"

# Set both the commit and the author date to the start of the Unix epoch (this cannot be done using `git commit` directly)
export GIT_AUTHOR_DATE="Thu Jan 1 00:00:00 1970 +0000"
export GIT_COMMITTER_DATE="Thu Jan 1 00:00:00 1970 +0000"

# Add root commit
git commit --allow-empty --allow-empty-message --no-edit

La creazione di commit GIT riproducibili è sorprendentemente difficile ...


3

Non puoi. Questa è una decisione di progettazione intenzionale da parte dei manutentori di Git. Fondamentalmente, lo scopo di un sistema di gestione del codice sorgente come Git è la gestione del codice sorgente e le directory vuote non sono codice sorgente. Git è anche spesso descritto come un tracker di contenuti e, di nuovo, le directory vuote non sono dei contenuti (al contrario, in realtà), quindi non vengono monitorate.


60
Contesto questo punto di vista. La struttura è contenuto e tutto ciò che chiami contribuisce al contenuto.
ThomasH,

20
Un file vuoto non è né codice sorgente né contenuto. È solo un nome. Eppure Git seguirà felicemente i file vuoti. Non penso che sia stata una decisione di progettazione intenzionale far rifiutare a Git di tenere traccia di directory vuote. Penso che il tracciamento di directory vuote sia una funzione che semplicemente non è necessaria il 99% delle volte, quindi non si sono preoccupati di fare il lavoro extra necessario per farlo funzionare correttamente. Git può farlo se qualcuno vuole la funzionalità abbastanza male per implementarla. Dubito che i manutentori di Git sarebbero contrari a una tale patch se fosse eseguita correttamente.
Dan Molding,

1
@TobyAllen ecco il link FAQ aggiornato La risposta principale è anche ciò che è raccomandato dalle FAQ con istruzioni più precise.
Daniel Da Cunha,

3
È una funzione mancante (e bassa priorità), non una limitazione intenzionale. Dalle domande frequenti su Git: attualmente la progettazione dell'indice Git (area di gestione temporanea) consente solo di elencare i file e nessuno abbastanza competente da apportare la modifica per consentire alle directory vuote di occuparsi di questa situazione abbastanza da rimediare.
jbo5112,

Non sono davvero d'accordo. Posso trovare vari motivi per cui voglio tenere traccia di una cartella vuota. Ad esempio, sto sviluppando un framework PHP MVC molto leggero per i miei progetti. Ho cartelle specifiche per posizionare modelli, viste, ecc. Quando creo un nuovo sito basato sul mio framework, quelle cartelle sono vuote poiché non ci sono modelli o viste per impostazione predefinita, ma ho bisogno che la cartella esista, altrimenti il ​​mio framework ha vinto non funziona!
Gladen,

2

Puoi salvare questo codice come create_readme.php ed eseguire il codice PHP dalla directory principale del tuo progetto Git.

> php create_readme.php

Aggiungerà i file README a tutte le directory vuote in modo che tali directory vengano quindi aggiunte all'indice.

<?php
    $path = realpath('.');
    $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path),       RecursiveIteratorIterator::SELF_FIRST);
    foreach($objects as $name => $object){
        if ( is_dir($name) && ! is_empty_folder($name) ){
            echo "$name\n" ;
            exec("touch ".$name."/"."README");
        }
    }

    function is_empty_folder($folder) {
        $files = opendir($folder);
        while ($file = readdir($files)) {
            if ($file != '.' && $file != '..')
                return true; // Not empty
            }
        }
?>

Quindi fa

git commit -m "message"
git push
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.