Haga que .gitignore ignore todo excepto algunos archivos

1702

Entiendo que un archivo .gitignore oculta archivos específicos del control de versiones de Git. Tengo un proyecto (LaTeX) que genera muchos archivos adicionales (.auth, .dvi, .pdf, registros, etc.) mientras se ejecuta, pero no quiero que se rastreen.

Soy consciente de que podría (tal vez debería) hacerlo para que todos esos archivos se coloquen en una subcarpeta separada en el proyecto, ya que podría ignorar la carpeta.

Sin embargo, ¿hay alguna manera factible de mantener los archivos de salida en la raíz del árbol del proyecto y usar .gitignore para ignorar todo excepto los archivos que estoy rastreando con Git? Algo como

# Ignore everything
*

# But not these files...
script.pl
template.latex
# etc...
Andrés
fuente
12
Duplicado de stackoverflow.com/q/9162919/321973 (Sé que es más nuevo, pero la respuesta allí es más correcta). En realidad, esta respuesta es probablemente la mejor
Tobias Kienzler

Respuestas:

2444

Un prefijo opcional !que niega el patrón; cualquier archivo coincidente excluido por un patrón anterior se volverá a incluir. Si un patrón negado coincide, esto anulará las fuentes de patrones de precedencia inferior.

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# ...even if they are in subdirectories
!*/

# if the files to be tracked are in subdirectories
!*/a/b/file1.txt
!*/a/b/c/*
Joakim Elofsson
fuente
14
Parece que esto también 'ignora' las subcarpetas, de modo que cualquier archivo llamado 'script.pl' en cualquier otra cosa que no sea el directorio raíz no se encontrará de todos modos. Estoy usando esto ahora (con * .pl) y todos los archivos * .pl se ignoran a pesar de que hay muchos en los subdirectorios debajo del archivo
.gitignore
38
@PandaWood Ese problema se trajo aquí (stackoverflow.com). Es causado por la primera expresión que coincide con todo, incluidos los directorios, que nunca niega. Para solucionarlo, agregue (! * /), Que coincide con cualquier subdirectorio (recursivamente) en el directorio actual. Esto no ayudará a la respuesta principal, que es la inclusión en la lista blanca de archivos específicos (si están en subdirectorios, es probable que desee especificar manualmente la ruta completa o usar archivos .gitignore específicos del directorio).
simont
40
No pude hacer que esto funcione. Estoy ignorando una carpeta (p wp/. Ej. ) Pero no quiero ignorar algunos archivos en esa carpeta (p wp/path/to/some/location/*. Ej .). La única forma en que pude hacerlo funcionar fuegit add -f wp/path/to/some/location/*
trusktr
13
@trusktr Use la !*/excepción de Simont
Tobias Kienzler
77
Dios, esa última regla: !*/marca la diferencia en mis inútiles intentos de arreglar un .gitignorearchivo para que funcione. Muchas gracias.
racl101
629

Si desea ignorar todo el contenido de un directorio, excepto un archivo dentro de él, puede escribir un par de reglas para cada directorio en la ruta del archivo. Por ejemplo .gitignore para ignorar la carpeta pippo excepto de pippo / pluto / paperino.xml

.gitignore

pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml
Giuseppe Galano
fuente
58
Excelente respuesta, pero vale la pena señalar Es para cualquiera que venga a través de esta tarde que fooy foo/*son no lo mismo. Para que esto funcione, debe usarlo foo/*para la carpeta base
thislooksfun
20
@Mayank Pippo es Goofy en italiano, mientras que Paperino es Donald Duck y Plutón es lo mismo que en inglés. Solían ser un triplete muy común de nombres de variables para programar muestras en aquellos días. Fue agradable leerlos de nuevo .. :)
Ghidello
Lo que dice @thislooksfun es importante si desea "excluir una carpeta excepto el archivo x".
Czechnology
8
no funciona para mí: node_modules / *! node_modules / bootstrap
SuperUberDuper
1
@simple_human Eso sería cierto si ignorara todo en la raíz del repositorio, o si tuviera que preocuparse por el archivo .gitignore, dentro de los directorios mencionados.
xZero
245

Desea usar en /*lugar de *o */en la mayoría de los casos

El uso *es válido, pero funciona de forma recursiva. No buscará en los directorios a partir de ese momento. La gente recomienda usar los !*/directorios de la lista blanca nuevamente, pero en realidad es mejor incluir en la lista negra la carpeta de nivel más alto con/*

# Blacklist files/folders in same directory as the .gitignore file
/*

# Whitelist some files
!.gitignore
!README.md

# Ignore all files named .DS_Store or ending with .log
**/.DS_Store
**.log

# Whitelist folder/a/b1/ and folder/a/b2/
# trailing "/" is optional for folders, may match file though.
# "/" is NOT optional when followed by a *
!folder/
folder/*
!folder/a/
folder/a/*
!folder/a/b1/
!folder/a/b2/
!folder/a/file.txt

# Adding to the above, this also works...
!/folder/a/deeply
/folder/a/deeply/*
!/folder/a/deeply/nested
/folder/a/deeply/nested/*
!/folder/a/deeply/nested/subfolder

El código anterior podría ignorar todos los archivos a excepción de .gitignore, README.md, folder/a/file.txt, folder/a/b1/y folder/a/b2/, y todo lo contenido en estas dos últimas carpetas. (Y .DS_Storey*.log archivos serían ignorados en esas carpetas.)

Obviamente podría hacer, por ejemplo, !/foldero !/.gitignoretambién.

Más información: http://git-scm.com/docs/gitignore

Ryan Taylor
fuente
3
Muy inteligente, gracias. En mi opinión, esta es la mejor manera de hacerlo para los sitios de WordPress con el número mínimo de reglas de inclusión. Además, los nuevos complementos, temas o actualizaciones de WP no se eliminan o agregan sin su permiso expreso. Cuando uso GitHub Desktop, encuentro que los .DS_Storearchivos no se ignoran, pero a través de la línea de comandos esto no es un problema. Para evitar esto, tuve que mover **/.DS_Storetodas las demás reglas a continuación.
Jibran
77
Mi resaltador interno de sintaxis está teniendo una reacción extraña al título de tu publicación.
itsadok
3
Gracias! también puede incluir en la lista blanca un archivo en una carpeta ..! /some/folder/file.txt
PodTech.io
Impresionante, el uso de / * en lugar de * solucionó todos mis problemas cuando las respuestas anteriores no lo hicieron. Mi única pregunta ahora es ¿cuál es la diferencia entre! / Folder y! / Folder / *? Si uso la carpeta! / Sin el *, aún recoge los cambios en todos los archivos de la carpeta por lo que puedo decir.
dallin
1
@dallin no hay diferencia. Una lista blanca de una carpeta y la otra lista blanca los hijos de esa carpeta, que hace lo mismo. El único problema es que los padres de una carpeta o de los archivos deben incluirse en la lista blanca antes de que pueda incluirse en la lista blanca, por lo que no puede hacerlo /*entonces !/nested/folder/*(o el equivalente !/nested/folder) sin hacerlo !/nested/o !/nestedprimero. (y probablemente /nested/*en el medio). Un truco para recordar es que si estás en la lista blanca de una subcarpeta profundamente anidada, debes ennegrecer a los niños de cada subcarpeta y esas listas negras terminarán con la "estrella diagonal" ...
Ryan Taylor,
75

Un poco más específico:

Ejemplo: Ignora todo webroot/cache, pero sigue webroot/cache/.htaccess.

Observe la barra inclinada (/) después de la cachecarpeta:

FALLAS

webroot/cache*
!webroot/cache/.htaccess

TRABAJOS

webroot/cache/*
!webroot/cache/.htaccess
Nik
fuente
Si está utilizando VS Code, tenga cuidado de no leer mal el color del archivo después de aplicarlo a una carpeta con .gitkeep porque el nombre de la carpeta se volverá verde pero el archivo .gitkeep se volverá gris al igual que todos los demás archivos ignorados; .gitkeep parecerá ignorado, pero debería ver que hay una 'U' en el lado derecho, lo que indica que se ha detectado
OzzyTheGiant
55
# ignore these
*
# except foo
!foo
Suvesh Pratapa
fuente
28

Para ignorar algunos archivos en un directorio, debe hacer esto en el orden correcto :

Por ejemplo, ignore todo en la carpeta "aplicación" excepto index.php y la carpeta "config" preste atención al pedido .

Debes negar lo que quieres primero.

FALLAS

application/*

!application/config/*

!application/index.php

TRABAJOS

!application/config/*

!application/index.php

application/*

slatunje
fuente
38
Incorrecto. Niegas después de "ignorar todo".
Carlos
2
No se deje engañar git statuspara verificar si sus cambios .gitignorefuncionan como se esperaba
Philippe Rathé
10
Si git statusno le va a decir qué está mirando y qué se ignora, ¿cómo puede saber si esto está funcionando?
kris
1
@kris Limpia el caché de git primero. Haga un "git rm --cached *" primero, luego puede hacer un "git add --all" y luego un "estado de git" le mostrará todos los nuevos cambios de gitignore.
Mark McCorkle
20

Puede usar git config status.showUntrackedFiles noy todos los archivos no rastreados estarán ocultos para usted. Ver man git-configpara más detalles.

Robert Munteanu
fuente
¡Esto es genial si solo desea confirmar algunos archivos de muchos!
Josh M.
16

Para excluir la carpeta de .gitignore, se puede hacer lo siguiente.

!app/

app/*
!app/bower_components/

app/bower_components/*
!app/bower_components/highcharts/

Esto ignorará todos los archivos / subcarpetas dentro, bower_componentsexcepto /highcharts.

Guy Baskin
fuente
14

Hay un montón de preguntas similares sobre esto, así que publicaré lo que escribí antes:

La única forma en que conseguí que esto funcionara en mi máquina fue hacerlo de esta manera:

# Ignore all directories, and all sub-directories, and it's contents:
*/*

#Now ignore all files in the current directory 
#(This fails to ignore files without a ".", for example 
#'file.txt' works, but 
#'file' doesn't):
*.*

#Only Include these specific directories and subdirectories and files if you wish:
!wordpress/somefile.jpg
!wordpress/
!wordpress/*/
!wordpress/*/wp-content/
!wordpress/*/wp-content/themes/
!wordpress/*/wp-content/themes/*
!wordpress/*/wp-content/themes/*/*
!wordpress/*/wp-content/themes/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*/*

Observe cómo debe permitir explícitamente el contenido para cada nivel que desee incluir. Entonces, si tengo subdirectorios 5 profundos debajo de los temas, todavía necesito explicarlo.

Esto es del comentario de @ Yarin aquí: https://stackoverflow.com/a/5250314/1696153

Estos fueron temas útiles:

También intenté

*
*/*
**/**

y **/wp-content/themes/**

o /wp-content/themes/**/*

Nada de eso funcionó para mí tampoco. Un montón de rastro y error!

Katie
fuente
2
Este es el único método que funciona para incluir exclusivamente ciertas extensiones de archivo. Aún mejor, es un excelente arte ASCII: gist.github.com/Wolfgange3311999/91c671f5e4d3c56cf5a1
Matthew D. Scholefield
10

Tuve un problema con la subcarpeta.

No funciona:

/custom/*
!/custom/config/foo.yml.dist

Trabajos:

/custom/config/*
!/custom/config/foo.yml.dist
Fabian Picone
fuente
9

Intenté todas las respuestas como se dan aquí arriba, pero ninguna funcionó para mí. Después de leer la documentación de gitignore ( aquí ) descubrí que si excluye una carpeta primero, los nombres de archivo en la subcarpeta no se indexan. Entonces, si usa el signo de exclamación después para incluir un archivo, no se encuentra en el índice y, por lo tanto, no se incluye en su cliente git.

Esa fue la forma de encontrar la solución. Comencé agregando excepciones para todas las subcarpetas en mi árbol de carpetas para que funcionara, lo cual es un gran trabajo. Luego pude compactar la configuración detallada a la siguiente configuración, lo cual es un poco contrario a la documentación.

Trabajo .gitignore:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' subfolder
/Pro/3rdparty/*
!Pro/3rdparty/domain/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

Como resultado, veo en mi cliente git que solo los dos archivos dentro de la carpeta Pro / 3rdparty / domain / modulename / se están organizando para la próxima confirmación, y eso fue exactamente lo que estaba buscando.

Y si necesita incluir en la lista blanca varias subcarpetas de la misma carpeta, agrupe las líneas de exclamación debajo de la declaración de exclusión de esta manera:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' & 'hosting' subfolders
/Pro/3rdparty/*
!Pro/3rdparty/domain/
!Pro/3rdparty/hosting/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

# Ignore the 'hosting' folder, except for the 'modulename' subfolder
Pro/3rdparty/hosting/*
!Pro/3rdparty/hosting/modulename/

De lo contrario, no funcionará como se esperaba.

Tim B.
fuente
Finalmente una respuesta que funcionó. Me pregunto cuándo entenderé cómo funciona realmente .gitignore
David
8

Eso es lo que funcionó para mí, quería comprometer solo un complemento de Cordova para el repositorio:

...
plugins/*
!plugins/cordova-plugin-app-customization
Dmitry Sokurenko
fuente
8

Sé que llego tarde a la fiesta, pero aquí está mi respuesta.

Como dijo @Joakim, para ignorar un archivo, puede usar algo como a continuación.

# Ignore everything
*

# But not these files...
!.gitignore
!someFile.txt

pero si el archivo está en directorios anidados, es un poco difícil escribir manualmente las reglas.

Por ejemplo, si queremos omitir todos los archivos en un gitproyecto, pero no en a.txtcuál se encuentra aDir/anotherDir/someOtherDir/aDir/bDir/cDir. Entonces, nuestro .gitignoreserá algo como esto

# Skip all files
*

# But not `aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt`
!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Lo anterior dado .gitignore archivo omitirá todos los directorios y archivos excepto!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Como habrás notado, es difícil definir esas reglas.

Para resolver este obstáculo, he creado una aplicación de consola simple llamada git-do-not-ignore que generará las reglas para usted. He alojado el proyecto en github con instrucciones detalladas.

Ejemplo de uso

java -jar git-do-not-ignore.jar "aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt"

Salida

!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

También hay una versión web simple disponible aquí

Gracias.

theapache64
fuente
7

Tengo a Jquery y Angular de Bower. Bower los instaló en

/public_html/bower_components/jquery/dist/bunch-of-jquery-files
/public_html/bower_components/jquery/src/bunch-of-jquery-source-files
/public_html/bower_components/angular/angular-files

El jquery minimizado está dentro del distdirectorio y angular está dentro del angulardirectorio. Solo necesitaba que los archivos minimizados se comprometieran con github. Un poco de manipulación de .gitignore y esto es lo que logré conjurar ...

/public_html/bower_components/jquery/*
!public_html/bower_components/jquery/dist
/public_html/bower_components/jquery/dist/*
!public_html/bower_components/jquery/dist/jquery.min.js
/public_html/bower_components/angular/*
!public_html/bower_components/angular/angular.min.js

Espero que alguien pueda encontrar esto útil.

Mario Legenda
fuente
7

Así es como lo hice:

# Ignore everything
*

# Whitelist anything that's a directory
!*/

# Whitelist some files
!.gitignore

# Whitelist this folder and everything inside of it
!wordpress/wp-content/themes/my-theme/**

# Ignore this folder inside that folder
wordpress/wp-content/themes/my-theme/node_modules

# Ignore this file recursively
**/.DS_Store

Úselo gig status -upara ver archivos individuales en directorios no rastreados de forma recursiva, con git statussolo ver carpetas, lo que podría engañarlo para que piense que todo dentro de ellos fue rastreado

zok
fuente
5

Solución simple si necesita ignorar todo excepto algunos archivos y pocas carpetas raíz :

/*
!.gitignore
!showMe.txt
!my_visible_dir

La magia está en /*(como se describió anteriormente) ignora todo en la carpeta (raíz) PERO NO de forma recursiva.

d.raev
fuente
4

También tuve algunos problemas con la negación de archivos individuales. Pude cometerlos, pero mi IDE (IntelliJ) siempre se quejó de los archivos ignorados, que se rastrean.

git ls-files -i --exclude-from .gitignore

Se muestran los dos archivos, que he excluido de esta manera:

public/
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

Al final, esto funcionó para mí:

public/*
!public/typo3conf/
public/typo3conf/*
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

La clave fue la negación de la carpeta typo3conf/ primero.

Además, parece que el orden de las declaraciones no importa . En su lugar, debe negar explícitamente todas las subcarpetas, antes de poder negar archivos individuales en él.

La carpeta !public/typo3conf/y el contenido de la carpeta public/typo3conf/*son dos cosas diferentes para .gitignore.

Gran hilo! Este problema me molestó por un tiempo;)

Armin
fuente
3

Nada funcionó para mí hasta ahora porque estaba tratando de agregar un jar de lib.

Esto no funcionó:

build/*
!build/libs/*
!build/libs/
!build/libs/myjarfile.jar 

Esto funcionó:

build/*
!build/libs
Bansal Manish
fuente
3

Tengo esto funcionando

# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib
raftaar1191
fuente
2

Tuve el mismo problema que OP, pero ninguna de las 10 mejores respuestas en realidad funcionó .
Finalmente descubrí lo siguiente

Sintaxis incorrecta

*
!bin/script.sh

Sintaxis correcta:

*
!bin
!bin/script.sh

Explicación de la página de manual de gitignore :

Un prefijo opcional "!" que niega el patrón; cualquier archivo coincidente excluido por un patrón anterior se volverá a incluir. No es posible volver a incluir un archivo si se excluye un directorio principal de ese archivo . Git no enumera los directorios excluidos por razones de rendimiento, por lo que cualquier patrón en los archivos contenidos no tiene ningún efecto, sin importar dónde estén definidos.

Ejemplo extendido:

$ árbol.

.
├── .gitignore
└── bin
    ├── ignore.txt
    └── sub
        └── folder
            └── path
                ├── other.sh
                └── script.sh

$ cat .gitignore

*
!.gitignore
!bin
!bin/sub
!bin/sub/folder
!bin/sub/folder/path
!bin/sub/folder/path/script.sh

$ git status --untracked-files --no ignorado

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        bin/sub/folder/path/script.sh

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)
        bin/ignore.txt
        bin/sub/folder/path/other.sh

nothing added to commit but untracked files present (use "git add" to track)
frntn
fuente
1

Esencia

# Ignore everything
*

# But not these files...
!script.pl
!template.latex

Y probablemente incluya:

!.gitignore

Referencia

Desde https://git-scm.com/docs/gitignore :

Un prefijo opcional " !" que niega el patrón; cualquier archivo coincidente excluido por un patrón anterior se volverá a incluir. No es posible volver a incluir un archivo si se excluye un directorio principal de ese archivo. Git no enumera los directorios excluidos por razones de rendimiento, por lo que cualquier patrón en los archivos contenidos no tiene ningún efecto, sin importar dónde estén definidos. Coloque una barra diagonal inversa (" \") delante de la primera " !" para los patrones que comienzan con un literal " !", por ejemplo, " \!important!.txt".

...

Ejemplo para excluir todo excepto un directorio específico foo/bar(tenga en cuenta que /*, sin la barra inclinada, el comodín también excluiría todo lo que contenga foo/bar):

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar
Will Cain
fuente
0

Parece que encontré algo que funcionó para mí y que nadie más mencionó.

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# And if you want to include a sub-directory and all sub-directory and files under it, but not all sub-directories
!subdir/
!subdir/**/*

Básicamente, parece negar que se ignore un subdirectorio, debe tener dos entradas, una para el subdirectorio en sí !subdir/y luego otra que se expande a todos los archivos y carpetas debajo de él!subdir/**/*

Didier A.
fuente