¿Cómo puedo agregar un directorio vacío a un repositorio de Git?

4268

¿Cómo puedo agregar un directorio vacío (que no contiene archivos) a un repositorio de Git?

Laurie Young
fuente
16
Si bien no es útil, hay una manera de piratear un directorio vacío (realmente vacío) en su repositorio . Sin checkoutembargo, no lo hará con las versiones actuales de Git.
tiwo
335
@tiwo, por mi parte, no estoy de acuerdo con que no sea útil. Su jerarquía de directorios es parte de su proyecto, por lo que debe ser controlada por la versión.
JBentley
114
En mi caso, me gustaría agregar una estructura de directorio para archivos tmp, pero no los archivos tmp en sí. Al hacer esto, mi probador tiene la estructura correcta (de lo contrario, hay errores) pero no obstruyo mis confirmaciones con datos tmp. ¡Entonces sí, me es útil!
Adam Marshall
45
@ AdamMarshall Creo que tiwo estaba diciendo que el truco no es útil, ya que el proceso de pago lo ignora. Los directorios Tmp suenan como una característica útil para un VCS.
Quantum7
31
¿Por qué no tener el procedimiento que crea los archivos tmp también crea el directorio tmp?
RyPeck

Respuestas:

4128

Otra forma de hacer que un directorio permanezca (casi) vacío (en el repositorio) es crear un .gitignorearchivo dentro de ese directorio que contenga estas cuatro líneas:

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

Entonces no tiene que hacer el pedido correctamente como debe hacerlo en la solución de m104 .

Esto también brinda el beneficio de que los archivos en ese directorio no se mostrarán como "sin seguimiento" cuando realice un estado git.

Hacer persistente el comentario de @GreenAsJade :

Creo que vale la pena señalar que esta solución hace precisamente lo que pidió la pregunta, pero tal vez no sea lo que muchas personas que estaban viendo esta pregunta habrían estado buscando. Esta solución garantiza que el directorio permanezca vacío. Dice "Realmente nunca quiero que se verifiquen los archivos aquí". A diferencia de "Todavía no tengo ningún archivo para registrar aquí, pero necesito el directorio aquí, los archivos pueden llegar más tarde".

Jamie Flournoy
fuente
25
Creo que la solución README propuesta por @JohnMee debería usarse junto con esta; el archivo .gitignore proporciona una explicación de lo que queremos mantener fuera del control de versión, mientras que el archivo README explica cuál es el propósito del directorio, que son dos piezas de información muy importantes.
pedromanoel
18
@pedromanoel Escribo la documentación que pondría en el READMEinterior del .gitignorearchivo (como comentarios).
Carlos Campderrós
69
detecta la diferencia 1: 1.) una carpeta vacía, 2.) una carpeta con el archivo .gitignore. ;-)
Peter Perháč
66
Esto es perfecto para las carpetas de caché .
olor a
10
Desafortunadamente, esto da como resultado un directorio no vacío, tiene un solo archivo oculto.
pedorro
1091

No puedes Consulte las preguntas frecuentes de Git .

Actualmente, el diseño del índice git (área de preparación) solo permite que se enumeren los archivos, y nadie lo suficientemente competente como para realizar el cambio para permitir directorios vacíos se ha preocupado lo suficiente por esta situación para remediarlo.

Los directorios se agregan automáticamente al agregar archivos dentro de ellos. Es decir, los directorios nunca tienen que agregarse al repositorio y no se rastrean por sí mismos.

Puede decir " git add <dir>" y agregará archivos allí.

Si realmente necesita que exista un directorio en las cajas, debe crear un archivo en él. .gitignore funciona bien para este propósito; puede dejarlo vacío o completar los nombres de los archivos que espera que aparezcan en el directorio.

Andy Lester
fuente
67
La siguiente respuesta es MUCHO mejor. El hecho de que git el software de bajo nivel no lo permita no me importa tanto como CÓMO usar Git cuando necesito un directorio vacío. Agregar un .gitignore de 2 líneas me parece aceptable.
Amala
1
Bueno, si uno quiere mover archivos a un nuevo directorio, no puede hacerlo, git mvya que git se quejará de que el nuevo directorio no está bajo control de versión
lulalala
16
Puede leer " es imposible, no puede, etc. " en todo el Internet para esta pregunta frecuente. El .gitignoretruco es una respuesta frecuente y satisface muchas necesidades. Sin embargo , ES posible hacer que git track sea un directorio realmente vacío , vea mi respuesta
ofavre
2
Aunque cuanto más lo pienso, más se siente como "hash SHA de la cadena vacía", si existe, en realidad sería un identificador bien definido para un árbol vacío, a menos que sea imposible saber si ese objeto es un árbol o una gota
Emil Lundberg
21
He visto muchos repositorios que usan un archivo vacío llamado .gitkeeppara este propósito.
Sukima
759

Cree un archivo vacío llamado .gitkeepen el directorio y agréguelo.

Artur79
fuente
58
He agregado una respuesta alentadora para crear en su .keeplugar.
Acumenus
206
.gitkeepno ha sido prescrito por Git y hará que la gente adivine su significado, lo que los llevará a las búsquedas en Google, que los llevará aquí. La .gitconvención de prefijo debe reservarse para los archivos y directorios que usa Git.
Martes
10
@ t-mart "La .gitconvención de prefijos debe reservarse ..." ¿Por qué? ¿Git solicita esta reserva?
Expiación limitada el
99
En este caso, un archivo READMEo ABOUTsería igual de bueno o mejor. Dejando una nota para el próximo tipo, tal como todos solíamos hacerlo antes de las URL.
Dave
55
No funciona si usted está escribiendo una prueba de unidad que debe probar el código en un directorio vacío ...
thebjorn
437

Siempre puede poner un archivo README en el directorio con una explicación de por qué quiere este directorio, de lo contrario está vacío, en el repositorio.

John Mee
fuente
39
+1, buena sugerencia, un directorio vacío no tiene ningún sentido a menos que se vaya a utilizar en el futuro. Así que cree un archivo README dentro de él y escriba para qué sirve este directorio, y qué archivos se colocarán allí en el futuro. Eso resuelve los dos problemas.
saeedgnu
63
@ilius Tonterías. Una estructura de directorio que contenga directorios vacíos puede ser muy deseable en muchas situaciones (como una aplicación MVC donde desea un directorio de modelos pero aún no ha logrado crear ningún modelo, o un directorio de vistas compartidas al que planea agregar vistas compartidas, más adelante). ) Además, poner un README en cada uno de estos es excesivo ya que es obvio para qué están allí, y es fácil olvidar poner un README en cada uno de ellos. Y debe recordar eliminar el archivo README cuando agregue otros archivos. Básicamente, git definitivamente debería permitir directorios vacíos.
Jez
20
@Jez: no estoy de acuerdo. El punto es que git está diseñado para controlar (e indexar) el código fuente. Es importante destacar que la identificación de un commit es un hash de los contenidos. Es decir, debe tener contenidos. No necesita un archivo README en cada parte del árbol, solo en los nodos hoja. Si tiene lugares donde tiene la intención de poner código, pero no tiene código, y ni siquiera se tomará el tiempo para repetir "lugar para modelos" >> README, entonces lo que tiene es una idea, no una confirmación. No es de interés para git. Decir "Quiero que la aplicación en ejecución tenga directorios XYZ vacíos" es un problema de tiempo de ejecución , no un problema de origen. Manejarlo con su instalador.
Joe Atzberger
66
@JoeAtzberger Es una característica que falta, no una limitación intencional. De las preguntas frecuentes de Git: actualmente, el diseño del índice Git (área de preparación) solo permite que se enumeren los archivos, y nadie lo suficientemente competente como para realizar el cambio para permitir directorios vacíos se ha preocupado lo suficiente por esta situación para remediarla.
jbo5112
77
@ jbo5112 Sí, el "código especial" al que se refiere es el "instalador" que mencioné. Su instalación de aplicación web ya tiene que manejar la creación de una base de datos, configuración local, dependencias de extracción u otras 100 operaciones, pero ¿hay un par de directorios vacíos más allá? Pruebe gradle, pasajeros, chef, un Makefile primitivo, etc. No hay diferencia de seguridad entre crear directorios y el otro trabajo (potencialmente mucho más complicado / peligroso) de instalar una aplicación. Y si realmente no tiene deps, config, DB, etc., y no tiene instalador, simplemente use el archivo README. Ningún caso requiere que hagas ambas cosas.
Joe Atzberger
349
touch .keep

En Linux, esto crea un archivo vacío llamado .keep. Por lo que vale, este nombre es independiente de Git, mientras .gitkeepque sería específico de Git. En segundo lugar, como ha notado otro usuario, la .gitconvención de prefijos debe reservarse para los archivos y directorios que usa Git.

Alternativamente, como se señaló en otra respuesta , el directorio puede contener un archivo descriptivo READMEo un README.mdarchivo .

Por supuesto, esto requiere que la presencia del archivo no haga que su aplicación se rompa.

Acumenus
fuente
1
Esto es bueno para un directorio básico inicial, pero ¿qué pasa si comienza a llenarse de archivos? Entonces Git los notará y los reclamará como archivos sin seguimiento. La respuesta seleccionada aquí funciona de manera mucho más elegante para permitir que uno mantenga un directorio pero luego ignore los contenidos de manera segura.
JakeGould
14
La pregunta y la preocupación general predominante es agregar un directorio vacío. Si luego tiene un archivo residente, obviamente elimine el .keeparchivo o simplemente ignórelo. Si, en cambio, los archivos en el directorio deben ser ignorados, esa es una pregunta completamente diferente.
Acumenus
3
Se sugirió que git clean -nd | sed s/'^Would remove '// | xargs -I{} touch "{}.keep"haría esto en todos los directorios vacíos sin seguimiento.
Acumenus
1
No me gusta esta solución, es difícil adivinar qué hace este archivo. Además, si está generando archivos en su entorno de desarrollo (como registros o imágenes, etc.), esto no impide que esos archivos se versionen y lleguen a producción, lo que no es agradable.
danielrvt
1
A Windows no le gustan los archivos sin nombre y requiere magia especial para lograr esto (también conocido como una aplicación de terminal similar a bash o equivalente).
EntangledLoops
303

¿Por qué necesitaríamos carpetas versionadas vacías?

Lo primero es lo primero:

Un directorio vacío no puede ser parte de un árbol bajo el sistema de versiones Git .

Simplemente no será rastreado. Pero hay escenarios en los que "versionar" directorios vacíos puede ser significativo, por ejemplo:

  • andamiaje de una estructura de carpetas predefinida , haciéndola disponible para todos los usuarios / contribuyentes del repositorio; o, como un caso especializado de lo anterior, crear una carpeta para archivos temporales , como a cache/o logs/directorios, donde queremos proporcionar la carpeta pero .gitignoresu contenido
  • En relación con lo anterior, algunos proyectos no funcionarán sin algunas carpetas (que a menudo es un indicio de un proyecto mal diseñado, pero es un escenario frecuente en el mundo real y tal vez podría haber, por ejemplo, problemas de permisos para abordar).

Algunas soluciones sugeridas

Muchos usuarios sugieren:

  1. Colocando un README archivo u otro archivo con algún contenido para que el directorio no esté vacío, o
  2. Crear un .gitignorearchivo con una especie de "lógica inversa" (es decir, para incluir todos los archivos) que, al final, cumple el mismo propósito del enfoque n. ° 1.

Si bien ambas soluciones seguramente funcionan , las encuentro inconsistentes con un enfoque significativo para el control de versiones de Git.

  • ¿Por qué se supone que debes poner archivos falsos o README que quizás no quieras en tu proyecto?
  • ¿Por qué usar .gitignorepara hacer algo ( mantener archivos) que es exactamente lo contrario de lo que está destinado ( excluyendo archivos), aunque sea posible?

enfoque de gitkeep

Use un archivo vacío llamado.gitkeep para forzar la presencia de la carpeta en el sistema de versiones.

Aunque parezca que no es una gran diferencia:

  • Utiliza un archivo que tiene el único propósito de mantener la carpeta. No pones ninguna información que no quieras poner.

    Por ejemplo, debe usar README como, bueno, README con información útil, no como una excusa para mantener la carpeta.

    La separación de preocupaciones siempre es algo bueno, y aún puede agregar una .gitignorepara ignorar los archivos no deseados.

  • Al nombrarlo, .gitkeepes muy claro y directo desde el nombre de archivo en sí (y también para otros desarrolladores , lo cual es bueno para un proyecto compartido y uno de los propósitos centrales de un repositorio Git) de que este archivo es

    • Un archivo no relacionado con el código (debido al punto inicial y al nombre)
    • Un archivo claramente relacionado con Git
    • Su propósito ( mantener ) está claramente establecido y es consistente y semánticamente opuesto en su significado de ignorar

Adopción

He visto el .gitkeepenfoque adoptado por marcos muy importantes como Laravel , Angular-CLI .

Cráneo
fuente
8
Te perdiste un pensamiento: ¿cuál es la razón para mantener una carpeta vacía (por ejemplo, / logs, / tmp, / uploads)? Sí, es para mantener la carpeta vacía. :) Entonces, si desea mantener una carpeta vacía, debe ignorar los archivos que contiene.
Romano
14
@RomanAllenstein: no necesariamente. Podría ser que cree un repositorio con una estructura determinada que se pueda completar más tarde. Esos archivos se agregarán al repositorio tan pronto como se creen, y será molesto comenzar a eliminar o editar archivos .gitignore (y peligroso, porque probablemente ni siquiera se dé cuenta de que no se están rastreando: git los ignora) )
blueFast
45
@Behnam: Tomaré el voto negativo, pero mi investigación sobre el meta del SO no muestra preocupación por las respuestas detalladas, siempre que brinden suficientes detalles y claridad para ser útiles para cada lector (y cada nivel de habilidad). Todavía estoy muy abierto a cualquier crítica y gracias por haber declarado la razón públicamente, lo tomo muy positivamente.
Cranio
44
Si edita su respuesta para reemplazarla .gitkeepcon cualquier otro nombre de archivo sin prefijo git, obtendrá mi voto positivo, creo que esta es la mejor y más informativa respuesta. Motivo: Creo que ".git *" debe reservarse para los archivos prescritos por git, mientras que esto es solo un simple marcador de posición. Mi primera suposición cuando vi eso es que, por ejemplo, un archivo ".gitkeep" se ignoraría automáticamente (sería una buena característica), pero ese no es el caso, ¿verdad?
Johnny
55
Me pregunto por qué a las personas les cuesta tanto entender por qué uno quiere agregar carpetas "vacías" a git. Tienes que empezar por algún lado, ¿verdad? Por lo tanto, generalmente comienza con la estructura de carpetas de sus proyectos y, por desgracia, al comienzo del proyecto todavía no hay nada allí. Una vez que se realiza el repositorio del proyecto, los trabajadores del equipo pueden clonar y comenzar a trabajar en la MISMA estructura.
BitTickler
127

Como se describe en otras respuestas, Git no puede representar directorios vacíos en su área de preparación. (Consulte las preguntas frecuentes de Git ). Sin embargo, si, para sus propósitos, un directorio está lo suficientemente vacío si solo contiene un .gitignorearchivo, entonces puede crear .gitignorearchivos en directorios vacíos solo a través de:

find . -type d -empty -exec touch {}/.gitignore \;
mjs
fuente
21
Es posible que desee ignorar el directorio .git: find . -name .git -prune -o -type d -empty -exec touch {}/.gitignore \;
steffen
3
Una variación más simple para la mayoría de las situaciones esfind * -type d -empty -exec touch {}/.gitignore \;
akhan
2
Dado que OS X crea un archivo .DS_Store en casi todos los directorios, esto no funciona allí. La única solución (¡PELIGROSA!) Que encontré fue eliminar todos los archivos .DS_Store primero a través de find . -name .DS_Store -exec rm {} \;y luego usar la variante preferida de esta respuesta. ¡Asegúrese de ejecutar esto solo en la carpeta correcta!
zerweck
1
¿Alguien sabe una manera de hacer esto en Windows desde la línea de comandos? He visto algunas soluciones aquí en Ruby y Python, pero me gustaría una solución básica si se puede administrar.
Mig82
1
@akhan Agregar algo a .gitignoreno tiene influencia en la -emptybandera del findcomando. Mi comentario es acerca de eliminar los .DS_Storearchivos en un árbol de directorios, por lo -emptyque se puede aplicar la bandera.
zerweck
68

Andy Lester es correcta, pero si el directorio sólo tiene que estar vacío, y no vaciar vacío, puede poner un vacío .gitignorede archivos allí como una solución.

Por otro lado, este es un problema de implementación, no un problema fundamental de diseño de almacenamiento de Git. Como se ha mencionado muchas veces en la lista de correo de Git, la razón por la que esto no se ha implementado es que a nadie le ha importado lo suficiente como para enviar un parche, no es que no se pueda o no se deba hacer.

Aristóteles Pagaltzis
fuente
44
Eso es exactamente lo que dije. Ambos párrafos se abordan en el fragmento de preguntas frecuentes que publiqué.
Andy Lester
1
Creo que el lado es poco interesante y útil de saber: se puede solucionar, simplemente no lo espere pronto cuando haya una solución alternativa tan fácil para la mayoría de los casos.
wnoise
Lo siento, no leí el último párrafo, y si bien leí el primer párrafo, bueno, no estoy seguro de por qué repetí esa información.
Aristóteles Pagaltzis
2
Por supuesto, esta respuesta adicional sirve para señalar el hecho.
Michael Johnson
Llegué mirando un caso en el que la compilación se cayó si el directorio no existe y, de manera predeterminada, está vacío, pero no necesita estar vacío. Crear un .gitignore hace lo correcto.
Joshua
33

La forma de creación de la carpeta de registro de Ruby on Rails :

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

Ahora el directorio de registro se incluirá en el árbol. Es muy útil cuando se implementa, por lo que no tendrá que escribir una rutina para crear directorios de registro.

Los archivos de registro se pueden mantener emitiendo,

echo log/dev.log >> .gitignore

pero probablemente lo sabías.

Thomas E
fuente
23
¿Qué tiene eso que ver con Ruby on Rails?
Preguntas de Quolonel
30

Git no rastrea directorios vacíos. Consulte las preguntas frecuentes de Git para obtener más explicaciones. La solución alternativa sugerida es colocar un .gitignorearchivo en el directorio vacío. No me gusta esa solución, porque el.gitignore está "oculta" por la convención de Unix. Además, no hay explicación de por qué los directorios están vacíos.

Sugiero poner un archivo README en el directorio vacío explicando por qué el directorio está vacío y por qué debe rastrearse en Git. Con el archivo README en su lugar, en lo que respecta a Git, el directorio ya no está vacío.

La verdadera pregunta es ¿por qué necesita el directorio vacío en git? Por lo general, tiene algún tipo de script de compilación que puede crear el directorio vacío antes de compilar / ejecutar. Si no, entonces haz uno. Esa es una solución mucho mejor que poner directorios vacíos en git.

Entonces tiene alguna razón por la que necesita un directorio vacío en git. Ponga esa razón en el archivo README. De esa manera, otros desarrolladores (y el futuro) saben por qué el directorio vacío debe estar allí. También sabrá que puede eliminar el directorio vacío cuando se resuelva el problema que requiere el directorio vacío.


Para enumerar cada directorio vacío, use el siguiente comando:

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

Para crear READMEs de marcador de posición en cada directorio vacío:

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

Para ignorar todo en el directorio excepto el archivo README, ponga las siguientes líneas en su .gitignore:

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

Alternativamente, podría excluir todos los archivos README de ser ignorados:

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

Para enumerar cada LÉAME después de que ya se hayan creado:

find -name README.emptydir
lesmana
fuente
28

ADVERTENCIA: este ajuste no funciona realmente como resulta. Lo siento por los inconvenientes ocasionados.

Publicación original a continuación:

¡Encontré una solución mientras jugaba con Git internos!

  1. Supongamos que está en su repositorio.
  2. Crea tu directorio vacío:

    $ mkdir path/to/empty-folder
    
  3. Agréguelo al índice usando un comando de plomería y el árbol vacío SHA-1 :

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

    Escriba el comando y luego ingrese la segunda línea. Presione Entery luego Ctrl+ Dpara finalizar su entrada. Nota: el formato es el modo [ESPACIO] tipo [ESPACIO] SHA-1hash [TAB] ruta (la pestaña es importante, el formato de respuesta no lo conserva).

  4. ¡Eso es! Su carpeta vacía está en su índice. Todo lo que tienes que hacer es comprometerte.

Esta solución es corta y aparentemente funciona bien (¡ vea EDITAR! ), Pero no es tan fácil de recordar ...

El árbol vacío SHA-1 se puede encontrar creando un nuevo repositorio Git vacío, cden él y emitir git write-tree, que genera el árbol vacío SHA-1.

EDITAR:

He estado usando esta solución desde que la encontré. Parece funcionar exactamente de la misma manera que la creación de un submódulo, excepto que no hay un módulo definido en ninguna parte. Esto conduce a errores al emitir git submodule init|update. El problema es que git update-indexreescribe la 040000 treeparte en160000 commit .

Además, Git no notará ningún archivo colocado debajo de esa ruta, ya que cree que pertenecen a algún otro repositorio. ¡Esto es desagradable ya que se puede pasar por alto fácilmente!

Sin embargo, si aún no usa (y no usará) ningún submódulo Git en su repositorio, y la carpeta "vacía" permanecerá vacía o si desea que Git sepa de su existencia e ignore su contenido, puede ir con Este ajuste. Seguir el camino habitual con submódulos requiere más pasos que este ajuste.

ofavre
fuente
Después de poner la carpeta vacía en el índice y confirmar, ¿es posible git svn dcommithacerlo con el resultado deseado?
Expiación limitada el
2
Es poco probable que este ajuste funcione con cualquier otra herramienta. Como se indica en la advertencia y la edición, desaconsejo usarlo a menos que sea en un caso bastante restringido.
ofavre
1
Y, por supuesto, esta es la razón por la cual jugar con los componentes internos de Git está contraindicado.
Casey
@abhisekp ¿Cómo es eso posible?
PyRulez
1
@PyRulez bueno, en el mundo del software, nada es imposible. : D En realidad, seguí la respuesta.
abhisekp
21

Digamos que necesita un directorio vacío llamado tmp :

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

En otras palabras, debe agregar el archivo .gitignore al índice antes de decirle a Git que lo ignore (y todo lo demás en el directorio vacío).

m104
fuente
12
Dos cosas: puede simplemente "echo '*'> tmp / .gitignore" en lugar de tocar, y "git commit -m" no confirma los cambios realizados después de agregar los archivos al índice.
Christoffer Hammarström
66
Si lo hace echo bla > file, no obtendrá file: File existsporque >sobrescribirá el archivo si ya está allí o creará uno nuevo si no existe.
psyrendust 01 de
3
/bin/shsupuesto cultural! * Si "aquí" está cshy noclobberse establece la variable , de hecho obtendrá file: File exists. Si alguien dice "Entiendo esto", no asumas que es un idiota y responde "No, no lo haces". * c2.com/cgi/wiki?AmericanCulturalAssumption
clacke
1
@clacke Si alguien decide usar un caparazón diferente que todos los demás, debe indicarlo expresamente si tiene problemas. A diferencia de la nacionalidad, todos tienen su libre elección de concha.
SeldomNeedy
2
@SeldomNeedy Quizás estén buscando ayuda porque ni siquiera saben que están usando un shell diferente al de todos los demás.
clacke
20

Tal vez agregar un directorio vacío parece que sería la ruta de menor resistencia porque tiene scripts que esperan que ese directorio exista (tal vez porque es un objetivo para los binarios generados). Otro enfoque sería modificar sus scripts para crear el directorio según sea necesario .

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

En este ejemplo, puede registrar un enlace simbólico (roto) al directorio para poder acceder a él sin el prefijo ".generated" (pero esto es opcional).

ln -sf .generated/bin bin
git add bin

Cuando desee limpiar su árbol de origen, simplemente puede:

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

Si adopta el enfoque sugerido con frecuencia de registrar una carpeta casi vacía, tiene la menor complejidad de eliminar el contenido sin eliminar también el archivo ".gitignore".

Puede ignorar todos sus archivos generados agregando lo siguiente a su raíz .gitignore:

.generated
sin bar
fuente
1
Nota: El enlace simbólico que sugerí está "roto" en un pago limpio porque el .generateddirectorio no existe inicialmente. Ya no se romperá una vez que hagas tu construcción.
nobar
2
Estoy de acuerdo en que en algunos casos es una muy buena idea, pero en otros (como la distribución de un proyecto en el que tienes un esqueleto vacío con carpetas como modelos / y vistas /) querrás que el usuario tenga estos directorios a mano en lugar de que tener que leer manualmente los documentos, y podría ser un poco demasiado esperar que ejecuten algún tipo de script de instalación después de clonar el repositorio. Creo que esta respuesta en combinación con la respuesta README de @ john-mee debería cubrir la mayoría, si no todos los casos.
moopet
14

También he enfrentado el problema con los directorios vacíos. El problema con el uso de archivos de marcador de posición es que necesita crearlos y eliminarlos, si ya no son necesarios (porque más tarde se agregaron subdirectorios o archivos. Con grandes árboles fuente, la administración de estos archivos de marcadores de posición puede ser engorroso y error propenso.

Es por eso que decidí escribir una herramienta de código abierto que pueda administrar la creación / eliminación de dichos archivos de marcador de posición automáticamente. Está escrito para la plataforma .NET y se ejecuta bajo Mono (.NET para Linux) y Windows.

Solo eche un vistazo a: http://code.google.com/p/markemptydirs


fuente
14

Me gustan las respuestas de @ Artur79 y @mjs, así que he estado usando una combinación de ambos y lo convertí en un estándar para nuestros proyectos.

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

Sin embargo, solo unos pocos de nuestros desarrolladores trabajan en Mac o Linux. Mucho trabajo en Windows y no pude encontrar una línea simple equivalente para lograr lo mismo allí. Algunos tuvieron la suerte de tener Cygwin instalado por otras razones, pero recetar Cygwin solo por esto parecía excesivo.

Editar para una mejor solución

Entonces, dado que la mayoría de nuestros desarrolladores ya tienen Ant instalado, lo primero que pensé fue armar un archivo de compilación Ant para lograr esto independientemente de la plataforma. Esto todavía se puede encontrar aquí

Sin embargo , más tarde pensé que sería mejor convertir esto en un pequeño comando de utilidad, así que lo recreé usando Python y lo publiqué aquí en PyPI . Puede instalarlo simplemente ejecutando:

pip3 install gitkeep2

Le permitirá crear y eliminar .gitkeeparchivos de forma recursiva, y también le permitirá agregar mensajes para que sus pares comprendan por qué esos directorios son importantes. Este último bit es un bono. Pensé que sería bueno si los .gitkeeparchivos pudieran auto documentarse.

$ 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.

Espero que le sea útil.

Mig82
fuente
13

No puedes y desafortunadamente nunca podrás. Esta es una decisión tomada por el propio Linus Torvald. Él sabe lo que es bueno para nosotros.

Hay una diatriba por ahí en alguna parte que leí una vez.

Encontré Re: Directorios vacíos ... , pero tal vez hay otro.

Tienes que vivir con las soluciones ... desafortunadamente.

usuario2334883
fuente
1
Sé que publicaste esto como un ejemplo de un mal argumento, pero aprecio el enlace porque en realidad es un argumento bien razonado contra el seguimiento de directorios. ;-)
clacke
1
Esta respuesta parece ser inconsistente, ya que en la siguiente publicación en el hilo de referencia, Linus Torvald dice que espera que necesiten agregar seguimiento de directorio: markmail.org/message/libip4vpvvxhyqbl . De hecho, dice que "agradecería los parches que [agreguen soporte para el seguimiento de directorios vacíos]"
Patrick M
Patrick, él también usa la palabra "idiota" allí. Sospecho que su redacción se dirige a las personas aquí en este hilo, por lo que asumo que él no implementará algo "idiota" en Git por sí mismo.
user2334883
10

Cuando agrega un .gitignorearchivo, si va a poner cualquier cantidad de contenido en él (que desea que Git ignore), es posible que desee agregar una sola línea con solo un asterisco* para asegurarse de no agregar accidentalmente el contenido ignorado .

Michael Johnson
fuente
9

No hay forma de hacer que Git rastree directorios, por lo que la única solución es agregar un archivo de marcador de posición dentro del directorio que desea que Git rastree.

El archivo puede nombrarse y contener lo que desee, pero la mayoría de las personas usa un archivo vacío llamado .gitkeep (aunque algunas personas prefieren el VCS-agnóstico.keep ).

El prefijo . marca como un archivo oculto.

Otra idea sería agregar un READMEarchivo que explique para qué se utilizará el directorio.

Zaz
fuente
8

Como se mencionó, no es posible agregar directorios vacíos, pero aquí hay una línea que agrega archivos .gitignore vacíos a todos los directorios.

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

He pegado esto en un Rakefile para facilitar el acceso.

Peter Hoeg
fuente
66
Prefiero usarfind . -type d -empty -print0 | xargs --null bash -c 'for a; do { echo "*"; echo "!.gitignore"; } >>"$a/.gitignore"; done' --
Tino
8

La solución de Jamie Flournoy funciona muy bien. Aquí hay una versión un poco mejorada para mantener el .htaccess:

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

Con esta solución, puede confirmar una carpeta vacía, por ejemplo /log, /tmpo /cachey la carpeta permanecerá vacía.

romano
fuente
2
Quiere mantener un directorio vacío y no un archivo.
gvsrepins
2
Y he mencionado que también mantendrá el .htaccess. Ejemplo: si un software tiene un directorio para archivos de registro (como oxid eshop) que no debería ser accesible a través de la web, hay un .htaccess en el directorio. Si coloca el .gitignore mencionado anteriormente en la carpeta, el .htaccess no se activará y se podrá acceder a la carpeta a través de la web.
Romano
Si tiene un archivo .htaccess que está bajo control de versiones, entonces ya tiene el directorio que lo contiene bajo control de versiones. Por lo tanto, el problema ya está resuelto: el archivo .gitignore se vuelve irrelevante.
Ponkadoodle
1
@Wallacoloo Relacionado con la pregunta que tienes razón, sin embargo, el archivo es útil, lo usaré para un directorio de carga como ese donde los archivos estarán protegidos por .htaccess. Contrariamente a la explicación de los romanos, el archivo .htaccess se confirmará ya que está excluido por la regla de ignorar. [hilo viejo, lo sé]
David
7

Siempre construyo una función para verificar la estructura de carpetas deseada y la construyo para mí dentro del proyecto. Esto evita este problema ya que las carpetas vacías se mantienen en Git por 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");
}

Esto está en PHP, pero estoy seguro de que la mayoría de los idiomas admiten la misma funcionalidad, y debido a que la aplicación se encarga de la creación de las carpetas, las carpetas siempre estarán ahí.

Fuzz suave
fuente
2
Solo para que todos estemos en la misma página, ya no hago esto. Es una pérdida de tiempo. La .gitkeepconvención es una práctica mucho mejor.
Mild Fuzz
No puedo ver cómo esto puede ser una pérdida de tiempo. Cuando su TEMPLATEPATH es obviamente dinámica, no puede usar la solución .gitkeep. E incluso con una estructura de carpetas no dinámica, debe agregar algunas cosas más en lugar de eliminar la muy buena solución de verificar directorios, por ejemplo, verificar permisos y modificar los archivos. Agregar una forma de marcar directorios dentro de un .gitignore global sería perfecto para mí. Algo así como #keep / path / to / dir
Jochen Schultz
7

Aquí hay un truco, pero es divertido que funcione (Git 2.2.1). Similar a lo que sugirió @Teka, pero más fácil de recordar:

  • Agregar un submódulo a cualquier repositorio ( git submodule add path_to_repo)
  • Esto agregará una carpeta y un archivo .submodules. Cometer un cambio.
  • Eliminar .submodulesarchivo y confirmar el cambio.

Ahora, tiene un directorio que se crea cuando se confirma la confirmación. Sin embargo, una cosa interesante es que si observa el contenido del objeto de árbol de este archivo obtendrá:

fatal: no es un nombre de objeto válido b64338b90b4209263b50244d18278c0999867193

Sin embargo, no recomendaría usarlo ya que puede dejar de funcionar en las futuras versiones de Git. Lo que puede dejar su repositorio dañado.

Stanislav Bashkyrtsev
fuente
Esto realmente funciona, pero creo que confunde a IntelliJ ...: |
rogerdpack
He creado una mejor solución basada en esto que no tiene estos inconvenientes: stackoverflow.com/a/58543445/277882
ntninja
7

Muchos ya han respondido esta pregunta. Solo agrego una versión de PowerShell aquí.

Encuentra todas las carpetas vacías en el directorio

Agregue un archivo .gitkeep vacío allí

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}
Hainan.Z
fuente
Nice.‌‌ ༼ ͡☉ ͜ʖ ͡☉ ༽
FiringSquadWitness
6

Si desea agregar una carpeta que albergue una gran cantidad de datos transitorios en múltiples directorios semánticos, entonces un enfoque es agregar algo como esto a su raíz .gitignore ...

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

A continuación, puede enviar archivos README.md descriptivos (o archivos en blanco, no importa, siempre y cuando pueda seleccionarlos de forma única, como *.mden este caso) en cada directorio para asegurarse de que todos los directorios sigan siendo parte del repositorio pero los archivos (con extensiones) se mantienen ignorados. LIMITACIÓN: .¡no están permitidos en los nombres de directorio!

Puede llenar todos estos directorios con archivos xml / images o lo que sea y agregar más directorios a lo /app/data/largo del tiempo a medida que se desarrollen las necesidades de almacenamiento de su aplicación (con los archivos README.md que sirven para grabar en una descripción de para qué sirve cada directorio de almacenamiento exactamente).

No hay necesidad de alterar .gitignoreo descentralizar aún más creando un .gitignorenuevo directorio para cada nuevo directorio. Probablemente no sea la solución más inteligente, pero es concienzudo y siempre funciona para mí. Agradable y simple! ;)

ingrese la descripción de la imagen aquí

ajmedway
fuente
6

Una manera fácil de hacerlo es agregar un .gitkeeparchivo al directorio que desea (actualmente) mantener vacío.

Consulte esta respuesta de SOF para obtener más información, lo que también explica por qué algunas personas encuentran que la convención competitiva de agregar un archivo .gitignore (como se indica en muchas respuestas aquí) es confusa.

arcseldon
fuente
4

Agregar una opción más a la refriega.

Asumiendo que le gustaría agregar un directorio a giteso, para todos los propósitos relacionados git, debe permanecer vacío y nunca rastrear su contenido, y .gitignorecomo se sugiere varias veces aquí, hará el truco.

El formato, como se mencionó, es:

*
!.gitignore

Ahora, si desea una manera de hacer esto en la línea de comando, de una sola vez, dentro del directorio que desea agregar, puede ejecutar:

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

Yo mismo, tengo un script de shell que utilizo para hacer esto. Asigne un nombre al script como desee y agréguelo en algún lugar de su ruta de inclusión o haga referencia directamente a él:

#!/bin/bash

dir=''

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

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

Con esto, puede ejecutarlo desde el directorio que desea agregar o hacer referencia al directorio como su primer y único parámetro:

$ ignore_dir ./some/directory

Otra opción (en respuesta a un comentario de @GreenAsJade), si desea realizar un seguimiento de una carpeta vacía que MAYO contiene archivos de seguimiento en el futuro, pero estará vacía por el momento, se puede ommit el *del .gitignorearchivo, y comprobar que en. Básicamente, todo lo que dice el archivo es "no me ignores ", pero de lo contrario, el directorio está vacío y seguido.

Su .gitignorearchivo se vería así:

!.gitignore

Eso es todo, verifíquelo y tendrá un directorio vacío, pero rastreado, en el que puede rastrear archivos en algún momento posterior.

La razón por la que sugiero mantener esa línea en el archivo es porque da el .gitignorepropósito. De lo contrario, alguien en el futuro puede pensar en eliminarlo. Puede ayudar si coloca un comentario sobre la línea.

Miguel
fuente
4

A veces tiene que lidiar con bibliotecas o software mal escritos, que necesitan un directorio "real" vacío y existente. Poner un simple .gitignoreo .keeppodría romperlos y causar un error. Lo siguiente podría ayudar en estos casos, pero no hay garantía ...

Primero cree el directorio necesario:

mkdir empty

Luego agrega un enlace simbólico roto a este directorio (pero en cualquier otro caso que no sea el caso de uso descrito anteriormente, utilice un READMEcon una explicación):

ln -s .this.directory empty/.keep

Para ignorar los archivos en este directorio, puede agregarlo en su raíz .gitignore:

echo "/empty" >> .gitignore

Para agregar el archivo ignorado, use un parámetro para forzarlo:

git add -f empty/.keep

Después de la confirmación, tiene un enlace simbólico roto en su índice y git crea el directorio. El enlace roto tiene algunas ventajas, ya que no es un archivo normal y no apunta a ningún archivo regular. Entonces, incluso se ajusta a la parte de la pregunta "(que no contiene archivos)", no por la intención sino por el significado, supongo:

find empty -type f

Este comando muestra un resultado vacío, ya que no hay archivos presentes en este directorio. Por lo tanto, la mayoría de las aplicaciones, que obtienen todos los archivos en un directorio, generalmente no ven este enlace, al menos si lo hacen, un "archivo existe" o un "es legible". Incluso algunos scripts no encontrarán ningún archivo allí:

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

Pero recomiendo utilizar esta solución solo en circunstancias especiales, un buen escrito READMEen un directorio vacío suele ser una mejor solución. (Y no sé si esto funciona con un sistema de archivos de Windows ...)

Trendfischer
fuente
4

Leyendo las respuestas de @ofavre y @ stanislav-bashkyrtsev usando referencias de submódulos GIT rotos para crear los directorios de GIT, me sorprende que nadie haya sugerido aún esta simple enmienda de la idea para hacer que todo esté sano y salvo:

En lugar de piratear un submódulo falso en GIT , simplemente agregue uno real vacío .

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

Un repositorio GIT con exactamente un commit:

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

Sin mensaje, sin archivos comprometidos.

Uso

Para agregar un directorio vacío a su repositorio GIT:

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

Para convertir todos los directorios vacíos existentes en submódulos:

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

Git almacenará el último hash de confirmación al crear la referencia de submódulo, para que no tenga que preocuparse de que yo (o GitLab) lo use para inyectar archivos maliciosos. Desafortunadamente, no he encontrado ninguna forma de forzar qué ID de confirmación se usa durante el pago, por lo que deberá verificar manualmente que la ID de confirmación de referencia esté e84d7b81f0033399e325b8037ed2b801a5c994e0usando git submodule statusdespués de agregar el repositorio.

Todavía no es una solución nativa, pero lo mejor que probablemente puede tener sin que alguien conseguir sus manos muy , muy sucia en el código base GIT.

Apéndice: Recreando este commit

Debería poder volver a crear esta confirmación exacta utilizando (en un directorio vacío):

# 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

Crear confirmaciones GIT reproducibles es sorprendentemente difícil ...

ntninja
fuente
3

No puedes Esta es una decisión de diseño intencional por parte de los mantenedores de Git. Básicamente, el propósito de un sistema de administración de código fuente como Git es administrar el código fuente y los directorios vacíos no son código fuente. Git también se describe a menudo como un rastreador de contenido, y nuevamente, los directorios vacíos no son contenido (todo lo contrario, en realidad), por lo que no se rastrean.

Jörg W Mittag
fuente
6060
Disputo este punto de vista. La estructura es contenido, y todo lo que nombres contribuye al contenido.
ThomasH
20
Un archivo vacío tampoco es código fuente o contenido. Es solo un nombre. Sin embargo, Git hará un seguimiento feliz de los archivos vacíos. No creo que haya sido una decisión de diseño intencional hacer que Git se niegue a rastrear directorios vacíos. Creo que el seguimiento de directorios vacíos es una característica que simplemente no se necesita el 99% del tiempo, por lo que no se molestaron en hacer el trabajo adicional requerido para que funcione correctamente. Git puede hacerlo si alguien quiere la función lo suficiente como para implementarla. Dudo que los mantenedores de Git se opondrían a tal parche si se hiciera correctamente.
Dan Moulding
1
@TobyAllen aquí está el enlace de preguntas frecuentes actualizado . La respuesta principal también es la recomendada por las preguntas frecuentes con instrucciones más precisas.
Daniel Da Cunha
3
Es una característica faltante (y de baja prioridad), no una limitación intencional. De las preguntas frecuentes de Git: actualmente, el diseño del índice Git (área de preparación) solo permite que se enumeren los archivos, y nadie lo suficientemente competente como para realizar el cambio para permitir directorios vacíos se ha preocupado lo suficiente por esta situación para remediarla.
jbo5112
Realmente no estoy de acuerdo. Puedo encontrar varias razones por las que quiero rastrear una carpeta vacía. Por ejemplo, estoy desarrollando un framework PHP MVC muy liviano para mis proyectos. Tengo carpetas específicas para colocar modelos, vistas, etc. Cuando hago un nuevo sitio basado en mi marco, esas carpetas están vacías ya que no hay modelos o vistas por defecto, pero necesito que exista la carpeta, de lo contrario mi marco ganó no funciona!
Gladen
2

Puede guardar este código como create_readme.php y ejecutar el código PHP desde el directorio raíz de su proyecto Git.

> php create_readme.php

Agregará archivos README a todos los directorios que estén vacíos para que esos directorios se agreguen al índice.

<?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
            }
        }
?>

Entonces hazlo

git commit -m "message"
git push
usuario665190
fuente