.gitignore exclure le dossier mais inclut un sous-dossier spécifique

J’ai l’application de dossier / que j’ajoute à .gitignore. A l’intérieur de l’application / du dossier se trouve le dossier application / language / gr. Comment puis-je inclure ce dossier? J’ai essayé ça

application/ !application/language/gr/ 

sans chance …

Si vous excluez application/ , alors tout ce qui se trouve en dessous sera toujours exclu (même si un modèle d’exclusion négative ultérieur («unignore») pourrait correspondre à quelque chose sous application/ ).

Pour faire ce que vous voulez, vous devez «ignorer» chaque répertoire parent de tout ce que vous voulez «ignorer». En général, vous finissez par écrire des règles pour cette situation par paires: ignorez tout dans un répertoire, mais pas un certain sous-répertoire.

 # you can skip this first one if it is not already excluded by prior patterns !application/ application/* !application/language/ application/language/* !application/language/gr/ 

Remarque
Le trailing /* est significatif:

  • Le répertoire dir/ exclut un répertoire nommé dir et (implicitement) tout ce qu’il contient.
    Avec dir/ , Git ne regardera jamais rien dans dir , et par conséquent, il n’appliquera jamais aucun des motifs «un-exclude» à quelque chose sous dir .
  • Le pattern dir/* ne dit rien sur dir lui-même; il exclut tout ce qui est sous dir . Avec dir/* , Git traitera le contenu direct de dir , donnant aux autres modèles une chance de «exclure» un peu du contenu ( !dir/sub/ ).

Commit 59856de de Karsten Blees (kblees) pour Git 1.9 / 2.0 (T1 2014) clarifie ce cas:

gitignore.txt : clarifie la nature récursive des répertoires exclus

Un préfixe facultatif ” ! ” Qui annule le motif; tout fichier correspondant exclu par un modèle précédent sera à nouveau inclus.

Il n’est pas possible de ré-inclure un fichier si un répertoire parent de ce fichier est exclu. ( * )
( * : sauf si certaines conditions sont remplies dans git 2.8+, voir ci-dessous)
Git ne répertorie pas les répertoires exclus pour des raisons de performances, donc tous les modèles sur les fichiers contenus n’ont aucun effet, peu importe où ils sont définis.

Placez une barre oblique inverse (” \ “) devant le premier ” ! ” Pour les modèles commençant par un littéral ” ! “, Par exemple ” \!important!.txt “.

Exemple pour exclure tout sauf un répertoire spécifique foo/bar (notez le /* – sans le slash, le caractère générique exclurait également tout ce qui se trouve dans foo/bar ):

  -------------------------------------------------------------- $ cat .gitignore # exclude everything except directory foo/bar /* !/foo /foo/* !/foo/bar -------------------------------------------------------------- 

Mise à jour de février / mars 2016:

Notez qu’avec git 2.9.x / 2.10 (mi-2016?), Il est possible de ré-inclure un fichier si un répertoire parent de ce fichier est exclu s’il n’y a pas de caractère générique dans le chemin à nouveau inclus .

Nguyễn Thái Ngọc Duy ( pclouds ) tente d’append cette fonctionnalité:

  • commettre 506d8f1 pour git v2.7.0, retourné dans commit 76b620d git v2.8.0-rc0
  • commettre 5e57f9c git v2.8.0-rc0, … retourné (!) dans commit 5cee3493 git 2.8.0.

Donc, avec git 2.9+, cela aurait pu fonctionner, mais a finalement été annulé:

 application/ !application/language/gr/ 

La réponse de @Chris Johnsen est géniale, mais avec les nouvelles versions de Git (1.8.2 ou ultérieur), il existe un double astérisque pour une solution un peu plus rapide:

 # assuming the root folder you want to ignore is 'application' application/**/* # the subfolder(s) you want to track: !application/language/gr/ 

De cette façon, vous n’avez pas à “ignorer” le répertoire parent du sous-dossier que vous souhaitez suivre.


Avec Git 2.17.0 (Vous ne savez pas trop tôt avant cette version. Peut-être retour à la version 1.8.2), le modèle ** combiné avec excludes pour chaque sous-répertoire menant à vos fichiers fonctionne. Par exemple:

 # assuming the root folder you want to ignore is 'application' application/** # Explicitly track certain content nested in the 'application' folder: !application/language/ !application/language/gr/ !application/language/gr/** # Example adding all files & folder in the 'gr' folder !application/language/gr/SomeFile.txt # Example adding specific file in the 'gr' folder 

Il y a un tas de questions similaires à ce sujet, alors je posterai ce que j’ai écrit auparavant:

La seule façon pour moi de travailler sur ma machine était de le faire de cette façon:

 # 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: !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/*/*/*/*/* 

Notez comment vous devez explicitement autoriser le contenu pour chaque niveau que vous souhaitez inclure. Donc, si j’ai des sous-répertoires 5 sous les thèmes, je dois toujours préciser.

Ceci vient du commentaire de @ Yarin ici: https://stackoverflow.com/a/5250314/1696153

Ces sujets étaient utiles:

  • Comment fonctionnent les motifs négatifs dans .gitignore?
  • Comment fonctionnent les règles d’exclusion de gitignore?

J’ai aussi essayé

 * */* **/** 

et **/wp-content/themes/**

ou /wp-content/themes/**/*

Rien de tout cela n’a fonctionné pour moi non plus. Beaucoup de piste et d’erreur!

Donc, puisque de nombreux programmeurs utilisent le noeud. le cas d’utilisation qui répond à cette question est d’exclure node_modules sauf un module module-a par exemple:

 !node_modules/ node_modules/* !node_modules/module-a/ 

J’ai trouvé que cela fonctionne réellement .

 **/node_modules/* !**/node_modules/keep-dir 

Juste un autre exemple de marche dans la structure des répertoires pour obtenir exactement ce que vous voulez. Remarque: je n’ai pas exclu Library/ mais Library/**/*

 # .gitignore file Library/**/* !Library/Application Support/ !Library/Application Support/Sublime Text 3/ !Library/Application Support/Sublime Text 3/Packages/ !Library/Application Support/Sublime Text 3/Packages/User/ !Library/Application Support/Sublime Text 3/Packages/User/*macro !Library/Application Support/Sublime Text 3/Packages/User/*snippet !Library/Application Support/Sublime Text 3/Packages/User/*settings !Library/Application Support/Sublime Text 3/Packages/User/*keymap !Library/Application Support/Sublime Text 3/Packages/User/*theme !Library/Application Support/Sublime Text 3/Packages/User/**/ !Library/Application Support/Sublime Text 3/Packages/User/**/*macro !Library/Application Support/Sublime Text 3/Packages/User/**/*snippet !Library/Application Support/Sublime Text 3/Packages/User/**/*settings !Library/Application Support/Sublime Text 3/Packages/User/**/*keymap !Library/Application Support/Sublime Text 3/Packages/User/**/*theme 

> git add Library

> git status

 On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD ..." to unstage) new file: Library/Application Support/Sublime Text 3/Packages/User/Default (OSX).sublime-keymap new file: Library/Application Support/Sublime Text 3/Packages/User/ElixirSublime.sublime-settings new file: Library/Application Support/Sublime Text 3/Packages/User/Package Control.sublime-settings new file: Library/Application Support/Sublime Text 3/Packages/User/Preferences.sublime-settings new file: Library/Application Support/Sublime Text 3/Packages/User/RESTer.sublime-settings new file: Library/Application Support/Sublime Text 3/Packages/User/SublimeLinter/Monokai (SL).tmTheme new file: Library/Application Support/Sublime Text 3/Packages/User/TextPastryHistory.sublime-settings new file: Library/Application Support/Sublime Text 3/Packages/User/ZenTabs.sublime-settings new file: Library/Application Support/Sublime Text 3/Packages/User/adrian-comment.sublime-macro new file: Library/Application Support/Sublime Text 3/Packages/User/json-pretty-generate.sublime-snippet new file: Library/Application Support/Sublime Text 3/Packages/User/raise-exception.sublime-snippet new file: Library/Application Support/Sublime Text 3/Packages/User/trailing_spaces.sublime-settings 

Surtout pour les anciennes versions de Git, la plupart des suggestions ne fonctionnent pas très bien. Si tel est le cas, je mettrais un fichier .gitignore distinct dans le répertoire où je souhaite que le contenu soit inclus, indépendamment des autres parameters, et j’y atsortingbuerais les ressources nécessaires.

Par exemple: /.gitignore

 # ignore all .dll files *.dll 

/dependency_files/.gitignore

 # include everything !* 

Donc, tout dans / dependency_files (même les fichiers .dll) est inclus.

J’ai trouvé un cas similaire ici, où par défaut, .gitignore ignore tout en utilisant un astérisque, puis remplace le répertoire public.

 * !public !.gitignore 

Cela ne suffit pas si vous rencontrez le scénario OP.

Si vous souhaitez valider un sous-dossier spécifique du public , par exemple dans votre répertoire public/products , vous voulez inclure des fichiers d’un sous-dossier, par exemple, public/products/a/b.jpg vous les ajoutez spécifiquement comme ceci !/public/products !public/products/* , etc.

La solution consiste à vous assurer que vous ajoutez une entrée pour chaque niveau de chemin comme celui-ci pour les remplacer tous.

 * !.gitignore !public/ !public/*/ !public/products/ !public/products/* !public/products/*/ !public/products/*/ !public/products/*/* 

Dans WordPress, cela m’a aidé:

 wp-admin/ wp-includes/ /wp-content/* !wp-content/plugins/ /wp-content/plugins/* !/wp-content/plugins/plugin-name/ !/wp-content/plugins/plugin-name/*.* !/wp-content/plugins/plugin-name/** 

Je voulais suivre les fichiers de production jquery js et cela a fonctionné:

 node_modules/* !node_modules/jquery node_modules/jquery/* !node_modules/jquery/dist/*