tag - ¿Cómo ignoro los archivos en un directorio en Git?
git push (10)
¿Cuál es la sintaxis correcta para que el archivo .gitignore
ignore los archivos en un directorio?
Podría ser
config/databases.yml
cache/*
log/*
data/sql/*
lib/filter/base/*
lib/form/base/*
lib/model/map/*
lib/model/om/*
o
/config/databases.yml
/cache/*
/log/*
/data/sql/*
/lib/filter/base/*
/lib/form/base/*
/lib/model/map/*
/lib/model/om/*
?
¡Ambos ejemplos en la pregunta son realmente malos ejemplos que pueden llevar a la pérdida de datos!
Mi consejo: nunca agregue /*
a los directorios en archivos .gitignore, ¡a menos que tenga una buena razón!
Una buena razón sería, por ejemplo, lo que escribió Jefromi: "si tiene la intención de ignorar posteriormente algo en el directorio" .
La razón por la que de otro modo no debería hacerse es que agregar /*
a los directorios funciona, por un lado, de la forma en que ignora adecuadamente todos los contenidos del directorio, pero por otro lado tiene un efecto secundario peligroso:
Si ejecuta git stash -u
(para esconder temporalmente los archivos rastreados y no rastreados) o git clean -df
(para eliminar archivos no rastreados pero mantenerlos ignorados) en su repositorio, todos los directorios que se ignoren con un /*
anexado serán borrados irreversiblemente .
Algunos antecedentes
Tuve que aprender esto de la manera más difícil. Alguien en mi equipo estaba agregando /*
a algunos directorios en nuestro .gitignore. Con el tiempo tuve ocasiones en que ciertos directorios desaparecían repentinamente. Directorios con gigabytes de datos locales que necesita nuestra aplicación. Nadie podría explicarlo y siempre tengo ganas de volver a descargar todos los datos. Después de un tiempo, me di cuenta de que podría tener que ver con el git stash
. Un día quise limpiar mi repositorio local (mientras mantenía los archivos ignorados) y estaba usando git clean -df
y, de nuevo, mis datos desaparecieron. Esta vez tuve suficiente e investigé el tema. Finalmente me di cuenta de que la razón es la anexada /*
.
Supongo que puede explicarse de alguna manera por el hecho de que el directory/*
ignora todos los contenidos del directorio pero no el directorio en sí. Por lo tanto, no se considera rastreado ni ignorado cuando las cosas se eliminan. A pesar de que git status
y git status --ignored
dan una imagen ligeramente diferente.
Como reproducirse
Aquí es cómo reproducir el comportamiento. Actualmente estoy usando Git 2.8.4.
Se localdata/
un directorio llamado localdata/
con un archivo ficticio ( important.dat
) en un repositorio local de git y los contenidos se ignorarán al poner /localdata/*
en el archivo .gitignore
. Cuando uno de los dos comandos git mencionados se ejecute ahora, el directorio se perderá (inesperadamente).
mkdir test
cd test
git init
echo "/localdata/*" >.gitignore
git add .gitignore
git commit -m "Add .gitignore."
mkdir localdata
echo "Important data" >localdata/important.dat
touch untracked-file
Si haces un git status --ignored
aquí, obtendrás:
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
untracked-file
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
localdata/
Ahora bien
git stash -u
git stash pop
o
git clean -df
En ambos casos, el directorio supuestamente ignorado localdata
se habrá ido!
No estoy seguro de si esto se puede considerar un error, pero supongo que es al menos una característica que nadie necesita.
Informaré eso a la lista de desarrollo de git y veré qué piensan al respecto.
El primero. Esas rutas de archivos son relativas desde donde se encuentra su archivo .gitignore.
Las rutas que contienen barras inclinadas se consideran relativas al directorio que contiene el archivo .gitignore, generalmente el nivel superior de su repositorio, aunque también puede ubicarlas en subdirectorios.
Entonces, dado que en todos los ejemplos que das, las rutas contienen barras diagonales, las dos versiones son idénticas. La única vez que necesita poner una barra diagonal inicial es cuando ya no hay ninguna en la ruta. Por ejemplo, para ignorar foo solo en el nivel superior del repositorio, use /foo
. Simplemente escribir foo
ignoraría cualquier cosa llamada foo en cualquier parte del repositorio.
Sus comodines también son redundantes. Si desea ignorar un directorio completo, simplemente asígnele un nombre:
lib/model/om
La única razón para usar comodines de la forma que tiene es si tiene la intención de ignorar posteriormente algo en el directorio:
lib/model/om/* # ignore everything in the directory
!lib/model/om/foo # except foo
Podría ser:
config/databases.yml
cache
log
data/sql
lib/filter/base
lib/form/base
lib/model/map
lib/model/om
o posiblemente incluso:
config/databases.yml
cache
log
data/sql
lib/*/base
lib/model/map
lib/model/om
en caso de que el filter
y la form
sean los únicos directorios en lib que tengan un subdirectorio base
que deba ignorarse (véalo como un ejemplo de lo que puede hacer con los asterics).
Sería el primero. Ir por extensiones también en lugar de la estructura de carpetas.
Es decir, mi ejemplo C # desarrollo ignorar archivo:
#OS junk files
[Tt]humbs.db
*.DS_Store
#Visual Studio files
*.[Oo]bj
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.lib
*.sbr
*.sdf
ipch/
obj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad
#Tooling
_ReSharper*/
*.resharper
[Tt]est[Rr]esult*
#Project files
[Bb]uild/
#Subversion files
.svn
# Office Temp Files
~$*
Actualizar
Pensé que iba a proporcionar una actualización de los comentarios a continuación. Aunque no responde directamente a la pregunta del OP, vea lo siguiente para obtener más ejemplos de la sintaxis de .gitignore
.
Wiki de la comunidad (en constante actualización):
.gitignore para proyectos y soluciones de Visual Studio
Puede encontrar más ejemplos con el uso específico del idioma aquí (gracias al comentario de Chris McKnight):
Si desea colocar un archivo .gitignore en el nivel superior y hacerlo funcionar para cualquier carpeta debajo, use /**/
.
Por ejemplo, para ignorar todos los archivos *.map
en una carpeta /src/main/
y el uso de subcarpetas:
/src/main/**/*.map
Un archivo .gitignore de muestra puede verse como uno de los siguientes para un proyecto de Android Studio
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
# Local configuration file (sdk path, etc)
local.properties
#Eclipse
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
YourProjetcName/.gradle/
YourProjetcName/app/build/
*/YourProjetcName/.gradle/
*/YourProjetcName/app/build/
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
# Proguard folder generated by Eclipse
proguard/
# Intellij project files
*.iml
*.ipr
*.iws
.idea/
/build
build/
*/build/
*/*/build/
*/*/*/build/
*.bin
*.lock
YourProjetcName/app/build/
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
.gradle/
app/build/
*app/build/
# Local configuration file (sdk path, etc)
local.properties
/YourProjetcName/build/intermediates/lint-cache/api-versions-6-23.1.bin
appcompat_v7_23_1_1.xml
projectFilesBackup
build.gradle
YourProjetcName.iml
YourProjetcName.iml
gradlew
gradlew.bat
local.properties
settings.gradle
.gradle
.idea
android
build
gradle
Una barra diagonal inicial indica que la entrada de ignorar solo será válida con respecto al directorio en el que reside el archivo .gitignore. Especificar *.o
ignoraría todos los archivos .o en este directorio y todos los subdirectorios, mientras que /*.o
simplemente los ignoraría en ese directorio, mientras que otra vez, /foo/*.o
solo los ignoraría en /foo/*.o .
.gitignore
servicio basado en GUI y CLI que te permite generar plantillas .gitignore
muy fácilmente en https://www.gitignore.io .
Puede escribir las plantillas que desee en el campo de búsqueda o instalar el alias de línea de comandos y ejecutar
$ gi swift,osx
FORMATO DE PATRON
Una línea en blanco no coincide con ningún archivo, por lo que puede servir como un separador para facilitar la lectura.
Una línea que comienza con
#
sirve como comentario.Un prefijo opcional
!
lo que niega el patrón; Cualquier archivo coincidente excluido por un patrón anterior se incluirá nuevamente. Si un patrón negado coincide, esto anulará las fuentes de patrones de precedencia inferior.Si el patrón termina con una barra diagonal, se elimina con el propósito de la siguiente descripción, pero solo encontraría una coincidencia con un directorio. En otras palabras,
foo/
coincidirá con un directoriofoo
y rutas debajo de él, pero no coincidirá con un archivo regular o un enlace simbólicofoo
(esto es consistente con la forma en que pathspec funciona en general en git).Si el patrón no contiene una barra oblicua, git lo trata como un patrón global de shell y comprueba si hay una coincidencia con la ruta de acceso relativa a la ubicación del archivo
.gitignore
(en relación con el nivel superior del árbol de trabajo, si no es de un.gitignore
expediente).De lo contrario, git trata el patrón como un globo de shell adecuado para el consumo de
fnmatch(3)
con el indicadorFNM_PATHNAME
: los comodines en el patrón no coincidirán con a/
en la ruta de acceso. Por ejemplo,Documentation/*.html
coincide conDocumentation/git.html
pero noDocumentation/ppc/ppc.html
otools/perf/Documentation/perf.html
.Una barra diagonal principal coincide con el comienzo de la ruta de acceso. Por ejemplo,
/*.c
coincide concat-file.c
pero no conmozilla-sha1/sha1.c
Puedes encontrar más aquí
git help gitignore
o
man gitignore