Comment ignorer les fichiers d'un répertoire dans Git?

544

Quelle est la syntaxe appropriée pour que le .gitignorefichier ignore les fichiers d'un répertoire?

Serait-ce

config/databases.yml
cache/*
log/*
data/sql/*
lib/filter/base/*
lib/form/base/*
lib/model/map/*
lib/model/om/*

ou

/config/databases.yml
/cache/*
/log/*
/data/sql/*
/lib/filter/base/*
/lib/form/base/*
/lib/model/map/*
/lib/model/om/*

?

Chris McKnight
la source
5
fait la .gitignoredifférence entre les fichiers et les répertoires qu'il ignore? par exemple, datavs data/signifie-t-il des choses différentes?
Charlie Parker
6
@CharlieParker yes-ish: dataignorera les fichiers et répertoires qui correspondent, data/ignorera uniquement les répertoires qui correspondent.
jox
Rappelez-vous toujours si vous avez mis en scène ou validé le fichier que vous essayez d'ignorer, alors il n'y a aucun moyen de l'ignorer :( Juste mes 2 cents après avoir pensé que j'avais un mauvais schéma et perdu un quart d'heure.
Adam
@Adam correct, vous devrez mettre à jour .gitignore puis décompresser / git rm --cachez le fichier.
Chris McKnight

Réponses:

374

FORMAT DE MODÈLE

  • Une ligne vierge ne correspond à aucun fichier, elle peut donc servir de séparateur pour la lisibilité.

  • Une ligne commençant par #sert de commentaire.

  • Un préfixe facultatif !qui annule le modèle; tout fichier correspondant exclu par un modèle précédent sera à nouveau inclus. Si un modèle annulé correspond, cela remplacera les sources de modèles de priorité inférieure.

  • Si le modèle se termine par une barre oblique, il est supprimé aux fins de la description suivante, mais il ne trouve une correspondance qu'avec un répertoire. En d'autres termes, foo/correspondra à un répertoire fooet aux chemins en dessous, mais ne correspondra pas à un fichier normal ou à un lien symbolique foo(cela est cohérent avec la façon dont pathspec fonctionne en général dans git).

  • Si le modèle ne contient pas de barre oblique /, git le traite comme un modèle de glob de shell et vérifie une correspondance avec le chemin d'accès par rapport à l'emplacement du .gitignorefichier (par rapport au niveau supérieur de l'arborescence de travail s'il ne provient pas d'un .gitignorefichier).

  • Sinon, git traite le modèle comme un glob de shell adapté à la consommation fnmatch(3)avec le FNM_PATHNAMEdrapeau: les caractères génériques dans le modèle ne correspondront pas à a /dans le chemin d'accès. Par exemple, Documentation/*.htmlcorrespond Documentation/git.htmlmais pas Documentation/ppc/ppc.htmlou tools/perf/Documentation/perf.html.

  • Une barre oblique correspond au début du chemin d'accès. Par exemple, /*.ccorrespond cat-file.cmais pas mozilla-sha1/sha1.c.

Vous pouvez en trouver plus ici

git help gitignore
ou
man gitignore

Op De Cirkel
la source
2
Comment puis-je mettre un fichier .gitignore au niveau supérieur et le faire fonctionner pour n'importe quel dossier en dessous? Merci.
Royi
104
-1 TL; DR et répond à peine à la question. Il s'agit de répertoires, pas de fichiers, donc la section en gras n'est appropriée qu'avec de la gymnastique mentale. @Jefromi était plus direct.
Bob Stein
J'ai lu l'homme, et la réponse de @ Jefromi est meilleure - tant que vous lisez également l'avertissement de @ jox - et @ Luke Hutton pourrait être plus utile pour ignorer, par exemple, les fichiers de projet IDE.
WillC
1
Il s'agit en fait d'un copier-coller de la documentation git
mcont
1
Pas sûr (essentiellement) de copier-coller une manpage ou un document officiel est le meilleur format pour SO ...
jdk1.0
183

Ce serait le premier. Utilisez également les extensions au lieu de la structure des dossiers.

Par exemple, mon exemple de développement C # ignore le fichier:

#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
~$*

Mise à jour

Je pensais fournir une mise à jour à partir des commentaires ci-dessous. Bien qu'il ne réponde pas directement à la question de l'OP, consultez ce qui suit pour plus d'exemples de .gitignoresyntaxe.

Wiki de la communauté (constamment mis à jour):

.gitignore pour les projets et solutions Visual Studio

Vous trouverez plus d'exemples d'utilisation d'une langue spécifique ici (grâce au commentaire de Chris McKnight):

https://github.com/github/gitignore

Luke Hutton
la source
5
@Stallman, c'est ça range. Cela correspond donc *.Objaussi bien *.obj.
norbert
131

Les chemins qui contiennent des barres obliques sont considérés comme relatifs au répertoire contenant le fichier .gitignore - généralement le niveau supérieur de votre référentiel, mais vous pouvez également les placer dans des sous-répertoires.

Donc, puisque dans tous les exemples que vous donnez, les chemins contiennent des barres obliques, les deux versions sont identiques. Le seul moment où vous devez mettre une barre oblique est quand il n'y en a pas déjà sur le chemin. Par exemple, pour ignorer foo uniquement au niveau supérieur du référentiel, utilisez /foo. Une simple écriture fooignorerait tout ce qui s'appelle foo n'importe où dans le référentiel.

Vos caractères génériques sont également redondants. Si vous voulez ignorer un répertoire entier, nommez-le simplement:

lib/model/om

La seule raison d'utiliser des caractères génériques comme vous l'avez fait si vous avez l'intention de dés-ignorer ultérieurement quelque chose dans le répertoire:

lib/model/om/*      # ignore everything in the directory
!lib/model/om/foo   # except foo
Cascabel
la source
5
Meilleure explication que réponse acceptée pour cette question
eerrzz
78

Une barre oblique principale indique que l'entrée ignorer doit uniquement être valide par rapport au répertoire dans lequel réside le fichier .gitignore. La spécification *.oignorerait tous les fichiers .o dans ce répertoire et tous les sous-répertoires, tout en les /*.oignorant simplement dans ce répertoire, tandis que là encore, /foo/*.oils ne les ignoreraient que dans /foo/*.o.

jørgensen
la source
34

Si vous souhaitez placer un fichier .gitignore au niveau supérieur et le faire fonctionner pour n'importe quel dossier en dessous, utilisez-le /**/.

Par exemple, pour ignorer tous les *.mapfichiers d'un /src/main/dossier et des sous-dossiers, utilisez:

/src/main/**/*.map
petrsyn
la source
J'avais besoin de faire ça. Je ne sais pas pourquoi vous avez besoin de deux ** . Un me suffisait.
Novocaine
8
** correspond également aux fichiers dans les sous
petrsyn
Merci pour l'info @petrsyn
Novocaine
30

Les deux exemples de la question sont en fait de très mauvais exemples qui peuvent entraîner une perte de données!

Mon conseil: ne jamais ajouter /*aux répertoires dans des fichiers .gitignore, sauf si vous avez une bonne raison!

Une bonne raison serait par exemple ce que Jefromi a écrit: "si vous avez l'intention de dés-ignorer ultérieurement quelque chose dans le répertoire" .

La raison pour laquelle cela ne devrait pas être fait autrement est que l'ajout /*aux répertoires fonctionne d'une part de la manière qu'il ignore correctement tout le contenu du répertoire, mais d'autre part, il a un effet secondaire dangereux:

Si vous exécutez git stash -u(pour cacher temporairement les fichiers suivis et non suivis) ou git clean -df(pour supprimer les fichiers non suivis mais gardez les fichiers ignorés) dans votre référentiel, tous les répertoires qui sont ignorés avec un ajout /*seront irréversiblement supprimés !

Quelques antécédents

J'ai dû l'apprendre à la dure. Quelqu'un dans mon équipe ajoutait /*à certains répertoires de notre .gitignore. Au fil du temps, j'ai eu des occasions où certains répertoires disparaissaient soudainement. Répertoires contenant des gigaoctets de données locales nécessaires à notre application. Personne ne pouvait l'expliquer et je déteste toujours télécharger à nouveau toutes les données. Après un certain temps, j'ai eu une idée que cela pourrait avoir à voir avec git stash. Un jour, je voulais nettoyer mon dépôt local (tout en gardant les fichiers ignorés) et j'utilisais git clean -dfet encore mes données avaient disparu. Cette fois, j'en ai eu assez et j'ai enquêté sur le problème. J'ai finalement pensé que la raison en était l'annexe /*.

Je suppose que cela peut s'expliquer d'une manière ou d'une autre par le fait qu'il directory/*ignore tout le contenu du répertoire mais pas le répertoire lui-même. Ainsi, il n'est ni considéré comme suivi ni ignoré lorsque les choses sont supprimées. Même si git statuset git status --ignoreddonnez une image légèrement différente à ce sujet.

Comment se reproduire

Voici comment reproduire le comportement. J'utilise actuellement Git 2.8.4.

Un répertoire appelé localdata/avec un fichier factice ( important.dat) sera créé dans un dépôt git local et le contenu sera ignoré en le mettant /localdata/*dans le .gitignorefichier. Lorsque l'une des deux commandes git mentionnées est exécutée maintenant, le répertoire sera (de manière inattendue) perdu.

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 vous faites un git status --ignoredici, vous obtiendrez:

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/

Maintenant non plus

git stash -u
git stash pop

ou

git clean -df

Dans les deux cas, le répertoire prétendument ignoré localdatadisparaîtra!

Je ne sais pas si cela peut être considéré comme un bug, mais je suppose que c'est au moins une fonctionnalité dont personne n'a besoin.

Je vais signaler cela à la liste de développement git et voir ce qu'ils en pensent.

jox
la source
15

Ce serait:

config/databases.yml
cache
log
data/sql
lib/filter/base
lib/form/base
lib/model/map
lib/model/om

ou peut-être même:

config/databases.yml
cache
log
data/sql
lib/*/base
lib/model/map
lib/model/om

au cas où filteret ce formsont les seuls répertoires de la lib qui ont un basesous-répertoire qui doit être ignoré (voyez-le comme un exemple de ce que vous pouvez faire avec les astérisques).

aefxx
la source
14

Le premier. Ces chemins d'accès aux fichiers sont relatifs par rapport à l'emplacement de votre fichier .gitignore.

Unixmonkey
la source
2
Cela n'est vrai que pour les modèles contenant une barre oblique. Un nom de répertoire unique comme "mydir" ignorera également les répertoires (et fichiers) qui se trouvent dans les sous-dossiers à n'importe quelle profondeur. Seul le fait de placer une barre oblique devant le rendra relatif par rapport à l'emplacement de votre fichier .gitignore.
jox
4

Je maintiens un service basé sur l'interface graphique et CLI qui vous permet de générer .gitignoretrès facilement des modèles sur https://www.gitignore.io .

Vous pouvez soit saisir les modèles souhaités dans le champ de recherche, soit installer l'alias de ligne de commande et exécuter

$ gi swift,osx

Joe
la source
0

Un exemple de fichier .gitignore peut ressembler à celui ci-dessous pour un projet 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
Shirish Herwade
la source