Make .gitignore ignore everything except a few files
Asked Answered
D

31

2619

I understand that a .gitignore file cloaks specified files from Git's version control.

How do I tell .gitignore to ignore everything except the files I'm tracking with Git? Something like:

# Ignore everything:
*

# Do not ignore these files:
script.pl
template.latex
Droshky answered 12/6, 2009 at 15:4 Comment(1)
Duplicate of https://mcmap.net/q/11682/-whitelisting-and-subdirectories-in-git/321973 (I know that's newer, but the answer there is more correct). Actually this answer is probably the bestEconomizer
Z
3516

An optional prefix ! which negates the pattern; any matching file excluded by a previous pattern will become included again. If a negated pattern matches, this will override lower precedence patterns sources.

# 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/*
Zincograph answered 12/6, 2009 at 15:7 Comment(20)
It looks like this also 'ignores' subfolders, such that any files named 'script.pl' in anything other than the root dir won't be found anyway. I'm using this now (with *.pl) and all *.pl files are being ignored even though there are many in the subdirectories below the .gitignore fileCricoid
@Cricoid That issue was brought up here (stackoverflow.com). It's caused by the first expression matching everything including directories, which you never negate. To fix, add (!*/), which matches any subdirectories (recursively) in current directory. This won't help the parent answer, which is whitelisting specific files (if they're in subdirectories, you'd probably want to manually specify the full path, or use directory-specific .gitignore files).Ing
@huyz not really, when .gitignore is inside the repo changes to it will not be ignored (as with all files). .gitignore ignoring itself before added, one can work around by doing 'git add -f .gitignore' (as mentioned when trying).Zincograph
I couldn't get this to work. I am ignoring a folder (e.g. wp/) but I want to NOT ignore some files deep in that folder (e.g. wp/path/to/some/location/*). The only way I could get it to work was by doing git add -f wp/path/to/some/location/*Brotherly
@Ing Thanks for your comment, it helped me solve my similar question, rendering it a dupe of the one you linked toEconomizer
@JoakimElofsson Simont is right, if the non-ignored files are allowed to rest in a nested directory, you need to add the !*/ exceptionEconomizer
@Brotherly Use simont's !*/ exceptionEconomizer
What if you wanted to ignore all but one directory? couldn't make that to work..Seethe
Geez that last rule: !*/ makes all the difference in my futile attempts to wrangle a .gitignore file to work. Thank you very much.Pernickety
See my answer, instead of doing * and !*/ use just /* it's equivalent, and makes more sense in my mind.Greatniece
@Brotherly I had the same problem and I used @giuseppe-galano (which you can find here below) and that solved my problem. Simply use write it inthis order wp/* !wp/path/to/some/location/. In my case wp/* !wp/wp-content/Infantile
If you're struggling to track a nested file by using this !*/a/b/file1.txt, you should try this !a/b/file1.txt. The first one matches only paths such as 1/a/b/file1.txt, but not paths such as a/b/file1.txt.Lamb
This answer is incomplete. See https://mcmap.net/q/11501/-using-gitignore-to-ignore-everything-but-specific-directories for a better solutionColquitt
Note that git status will be very slow with !*/ when there's a large folder structure in the repo (because git have to scan every folder, only ignore the files inside)Homeopathic
So everthing in .gitignore is ignored (*) except the subfolders (!*/).Rumen
IMPORTANT: * refers to files, while ** refers to subdirectories. Also, Git interprets from top to bottom, so later statements take precedence (they can override earlier statements).Drawplate
Important note: I thought this pattern wasn't working, but it turned out I had a global git ignore ~/.gitignore_global that was causing me grief.Auteur
I first add this line /docroot/sites/*/files, it works, then at the bottom I add !/docroot/sites/default/*/*.json. It doesn't work at all on my side. Even if I remove the leading slash.Pass
I couldn't make it work: .obsidian/plugins/*\n!.obsidian/plugins/*/data.json I want it to ignore all files in plugins those which name is data.json.Amin
I needed to use these - * (ignore everything), !**/subdirectory_to_be_added/* (files in directory are tracked), */subdirectory_to_be_added/subsubdirectory_to_be_ignored/* (files in directory are ignored)Superaltar
C
1086

If you want to ignore the whole content of a directory except one file inside it, you could write a pair of rules for each directory in the file path. E.g. .gitignore to ignore the pippo folder except from pippo/pluto/paperino.xml

pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml

Note that the /* is required for the folders. The following will not work:

folder
!folder/some-file.txt

but only this will:

folder/*
!folder/some-file.txt

Note that if you simply had written above:

pippo/*
!pippo/pluto/paperino.xml

It wouldn't work because the intermediary pluto folder would not exist to Git, so paperino.xml could not find a place in which to exist.

Casar answered 1/5, 2013 at 12:31 Comment(13)
Excellent answer, but It's worth noting for anyone coming across this later that foo and foo/* are not the same. For this to work, you need to use foo/* for the base folderScallion
@Mayank Pippo is Goofy in italian while Paperino is Donald Duck and Pluto is the same as in english. They used to be a very common triplet of variable names for programming samples back in the days. It was nice to read them again.. :)Camber
What @Scallion says is important if you want to "exclude a folder except file x".Palocz
doesn't work for me: node_modules/* !node_modules/bootstrapHypocoristic
you must include !.gitignore or else this wont work. .gitignore file will also untracked by gitPadraig
@simple_human That would be true if he was ignoring everything in repository root, or if he had .gitignore file to care about, inside mentioned directories.Basidium
@Basidium yes. in my case i want to ignore all except a file in a subdirectory. so i put the .gitignore file in that sub directory. so i have to track .gitignore file too.Padraig
Interestingly, it works for me without excluding the subdirectory (!pippo/pluto), but listing the subdirectory contents (pippo/pluto/*) is necessary.Unreel
"write a pair of rules for each directory in the file path" this works for me. To ignore a/ except for a/b/c, do this: a/* !a/b a/b/* !a/b/cTouristy
GENIUS, none of the answers worked or tricks anywhere on the internet, only this worked. Thanks so much.Anatollo
Note that 'git status' will show Untracked files: pippo/pluto/, but only pippo/pluto/paperino.xml will be addedSelfpronouncing
Thanks! When excluding a directory that you then want to include a file from the "/*" at the end makes all the difference. Usually I exclude folders by name onlyJanejanean
/* for folders is a useful note!Fimbria
G
385

You want to use /* instead of * or */ in most cases

Using * is valid, but it works recursively. It won't look into directories from then on out. People recommend using !*/ to includelist directories again, but it's actually better to blocklist the highest level folder with /*

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

# Includelist some files
!.gitignore
!README.md

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

# Includelist 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

The above code would ignore all files except for .gitignore, README.md, folder/a/file.txt, folder/a/b1/ and folder/a/b2/ and everything contained in those last two folders. (And .DS_Store and *.log files would be ignored in those folders.)

Obviously I could do e.g. !/folder or !/.gitignore too.

More info: http://git-scm.com/docs/gitignore

Greatniece answered 29/4, 2015 at 0:31 Comment(11)
Very clever, thanks. IMO, this is the best way to go about it for WordPress sites with the minimum number of inclusion rules. Also, any new plugins, themes or WP updates aren't removed or added without your express permission. When using GitHub Desktop I find .DS_Store files are not ignored, but via command line this is not an issue. To get around this I had to move the **/.DS_Store below all other rules.Retardation
My inner syntax highlighter is having a strange reaction to the title of your post.Divaricate
Gracias! you can also whitelist a file in a folder.. !/some/folder/file.txtNoblesse
Awesome, using /* instead of * fixed all my problems when the answers above didn't. My only question now is what's the difference between !/folder and !/folder/*? If I use !/folder without the *, it still picks up changes to all files in the folder as far as I can tell.Fratricide
@Fratricide there is no difference. One whitelists a folder and the other whitelists the children of that folder, which does the same thing. The only problem is a folder or files's parent has to be whitelisted before it can be whitelisted, so you can't do /* then !/nested/folder/* (or the equivalent !/nested/folder) without doing !/nested/ or !/nested first! (and probably /nested/* in between). A trick to remember is if you're whitelisting a deeply nested subfolder you need to black the children in each subfolder all the way up, and those blacklists will end with the "slash star"...Greatniece
others' answers work as well, but yours is the best! thanksSinnard
@RyanTaylor I've been looking for a solution to keeping my modules for a platform we work on in git nicely while in dev environments and this works SO perfectly I can't believe it. THANK YOU SO MUCH!Photogenic
Why there's backslash with **/.DS_Store but not with **.log?Esthonia
@Esthonia one is for files named .DS_Store (the filename starts with a dot) and the other is for files ending in .log like debug.log and server.log etc – the double dots represent that it's recursive and may be in any sub-folder (in our case any file ending in .log in all folders). It's equivalent to **/*.log.Greatniece
@Fratricide I actually could only get it to recognise files in my new dir (not part of index yet) with [directory]/ not [directory]/*, but maybe I wrote it wrongNucleonics
I was looking for a solution to allow ANYthing inside of ONLY ONE folder and ifgore anything else. I am not sure why but this worked for me: * !*/ !/allowed/folder/*Marilumarilyn
P
104

A little more specific:

Example: Ignore everything in webroot/cache - but keep webroot/cache/.htaccess.

Notice the slash (/) after the cache folder:

FAILS

webroot/cache*
!webroot/cache/.htaccess

WORKS

webroot/cache/*
!webroot/cache/.htaccess
Pr answered 13/8, 2013 at 13:23 Comment(1)
If you're using VS Code, careful not to misread the file coloring after applying this to a folder with .gitkeep because the folder name will turn green but the .gitkeep file will turn gray just like all the other ignored files; .gitkeep will look like its ignored but you should see that there is a 'U' on the right side, indicating that it's been detectedDenominative
R
95

Let's toolify!

As @Joakim said, to ignore a file, you can use something like below.

# Ignore everything
*

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

but if the file is in nested directories, it's a little difficult to write those rules.

For example, if we want to skip all files but not a.txt, located in aDir/anotherDir/someOtherDir/aDir/bDir/cDir. Then, our .gitignore will be something like this

# 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

This is quite hard to write by hand.

To solve this hurdle, I've created a web app named git-do-not-ignore which will generate the rules for you.

Tool

Demo

Sample Input

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

Sample Output

!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
Rickierickman answered 25/2, 2019 at 15:58 Comment(3)
Great tool, it has a problem when is a folder. When is a folder, you need to delete the penultimate line. BTW if you add it as a vscode extension you will get lots of downloads, cheersPga
Great tool. Saved my day!!Ranchod
This is the correct solution IMO. It's even open source ! github.com/theapache64/git-do-not-ignore/tree/masterCheke
L
90
# ignore these
*
# except foo
!foo
Leontina answered 12/6, 2009 at 15:6 Comment(0)
M
44

Had the similar issue as OP but none of top 10 upvoted answer actually worked.
I finally found out the following

Wrong syntax :

*
!bin/script.sh

Correct syntax :

*
!bin
!bin/script.sh

Explanation from gitignore man page :

An optional prefix "!" which negates the pattern; any matching file excluded by a previous pattern will become included again. It is not possible to re-include a file if a parent directory of that file is excluded. Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined.

Which means that "Wrong syntax" above is wrong because bin/script.sh cannot be reincluded as bin/ is ignored. That's all.

Extended example :

$ tree .

.
├── .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 --ignored

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)
Michaeu answered 2/5, 2020 at 7:54 Comment(3)
Thanks man this should be the accepted answer ! Way prettier and easier to read than the other postsSerle
Only answer that worked; the !*/ pattern that people are raving about seemed to re-include all those folders that I was trying to exclude. But I doubt this solution is ideal with lots of files / subfolders that should be exluded.Ewer
This should be the excepted answer.Fandango
P
36

To ignore some files in a directory, you have to do this in the correct order:

For example, ignore everything in folder "application" except index.php and folder "config" pay attention to the order.

You must negate want you want first.

FAILS

application/*

!application/config/*

!application/index.php

WORKS

!application/config/*

!application/index.php

application/*

Pedicab answered 9/8, 2012 at 8:39 Comment(5)
Wrong. You negate after the "ignore everything".Avoid
Don't get fooled by git status to check if your changes to .gitignore work as expectedFootpoundsecond
If git status is not going to tell you what it is looking at and what is ignored, then how can you know if this is working?Ammonal
@Ammonal Clear the git cache first. Do a "git rm --cached *" first then you can do a "git add --all" then a "git status" will show you all the new gitignore changes.Fornix
you can also use **Delmardelmer
T
25

You can use git config status.showUntrackedFiles no and all untracked files will be hidden from you. See man git-config for details.

Taratarabar answered 12/6, 2009 at 15:20 Comment(1)
This is great if you only want to commit a few files out of many!Boysenberry
H
24

This is how I keep the structure of folders while ignoring everything else. You have to have a README.md file in each directory (or .gitkeep).

/data/*
!/data/README.md

!/data/input/
/data/input/*
!/data/input/README.md

!/data/output/
/data/output/*
!/data/output/README.md
Heeled answered 29/1, 2021 at 23:17 Comment(3)
This one was what I was looking for. But is this really the easiest way to allow one file in an otherwise ignored nested directory? Mine is several levels deep...Fillbert
I think you just have to create an exception for that file and parent directories have to follow.Heeled
Unfortunately, I think this is the easiest way, and yes, parent directory has to follow if that makes things easier.Heeled
C
19

To exclude folder from .gitignore, the following can be done.

!app/

app/*
!app/bower_components/

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

This will ignore all files/subfolders inside bower_components except for /highcharts.

Carpetbagger answered 10/11, 2016 at 14:21 Comment(0)
V
16

There are a bunch of similar questions about this, so I'll post what I wrote before:

The only way I got this to work on my machine was to do it this way:

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

Notice how you have to explicitly allow content for each level you want to include. So if I have subdirectories 5 deep under themes, I still need to spell that out.

This is from @Yarin's comment here: https://mcmap.net/q/11501/-using-gitignore-to-ignore-everything-but-specific-directories

These were useful topics:

I also tried

*
*/*
**/**

and **/wp-content/themes/**

or /wp-content/themes/**/*

None of that worked for me, either. Lots of trail and error!

Vanadium answered 29/4, 2015 at 23:40 Comment(2)
This is the only method that works to exclusively-include certain file extensions. Even better, it makes great ASCII art: gist.github.com/Wolfgange3311999/91c671f5e4d3c56cf5a1Huggermugger
The above gist link is not working, but for extensions, this works - https://mcmap.net/q/11763/-make-gitignore-ignore-everything-except-a-few-filesTinner
M
14

This is how I did it:

# 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

Use gig status -u to view individual files in untracked directories recursively - with git status you'd only see folders, which could fool you into thinking that everything inside them was tracked

Manille answered 12/6, 2019 at 22:39 Comment(1)
Thank you very much for the tip regarding the -u parameter.. I was already using git status and could not get my head around the ignore rules as I got wrong untracked folders and files list..Steeplechase
A
12

I had a problem with subfolder.

Does not work:

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

Works:

/custom/config/*
!/custom/config/foo.yml.dist
Authenticate answered 6/6, 2018 at 6:43 Comment(0)
C
12

Not sure if this has been pointed out already but I was having trouble ignoring a subfolder inside an ignored folder using the ! in front of the folder i want gitignore to ignore.

However I figured out that the folder that was being ignored had no * in its path. My .gitignore looked like this:

/folder/
!/folder/subfolder

The subfolder was still being ignored, but adding a * after folder made it work like so

/folder/*
!/folder/subfolder
Castaway answered 23/8, 2022 at 9:4 Comment(0)
P
11

I tried all answers as given here above, but none worked for me. After reading the gitignore documentation (here) i found out that if you exclude a folder first that the filenames in the subfolder are not being indexed. So if you use the exclamation mark afterwards to include a file, it is not found in the index and thus not being included in your git client.

That was the way to finding the solution. I started with adding exceptions for all subfolders in my folder tree to get it working, which is a hell of a job. Afterwards i was able to compact the detailed configuration to the configuration below, which is a bit contrary to the documentation..

Working .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/

As result i see in my git client that only the two files inside the Pro/3rdparty/domain/modulename/ folder are being staged for the next commit, and that was exactly what i was looking for.

And if you need to whitelist several subfolders of the same folder then group the exclamation mark lines below the exclude statement like this:

# 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/

Else it wont work as expected.

Publus answered 12/9, 2018 at 12:55 Comment(1)
Finally an answer that worked. I wonder when I will understand how .gitignore actually worksRoup
M
11

a lot of complex answers here... here's something pretty simple that I don't see above and works well in many scenarios:

# ignore all files that have an extension
**/*.*

# except for these extensions
!**/*.extension1
!**/*.extension2

this doesn't ignore any extensionless files, but if you have a bunch that all have the same or similar name, you can add exclusions for those

**/EXTENSIONLESSFILETOIGNORE
Mineralogy answered 5/11, 2021 at 11:58 Comment(2)
This is exactly what I was looking for and it worked great. I wanted to include files with only one extension and ignore everything else in any sub path inside a specific directory.Tinner
ilyyy this is what i'm going to try for my copilotignoreEndoscope
S
9

That's what have worked for me, I wanted to commit only one Cordova plugin to the repo:

...
plugins/*
!plugins/cordova-plugin-app-customization
Selfreproach answered 30/4, 2016 at 18:58 Comment(0)
G
8

I have Jquery and Angular from bower. Bower installed them in

/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

The minimized jquery is inside the dist directory and angular is inside angular directory. I only needed minimized files to be commited to github. Some tampering with .gitignore and this is what I managed to conjure...

/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

Hope someone could find this useful.

Gaikwar answered 27/1, 2015 at 20:57 Comment(0)
E
8

The simplest way that I go about this is to force add a file. It will be accounted for in git even if it is buried or nested inside a git-ignored subdirectory tree.

For example:

x64 folder is excluded in .gitignore:

x64/

But you want to include the file myFile.py located in x64/Release/ directory. Then you have to:

git add -f x64/Release/myFile.py

You can do this for multiple files of files that match a pattern e.g.

git add -f x64/Release/myFile*.py

and so on.

Effluent answered 16/11, 2020 at 0:56 Comment(0)
D
7

Simple solution if you need to ignore everything except few files and few root folders:

/*
!.gitignore
!showMe.txt
!my_visible_dir

The magic is in /* (as described above) it ignores everything in the (root) folder BUT NOT recursively.

Dog answered 31/5, 2018 at 11:24 Comment(2)
Up-voted: to get the directory added, !directory/* did not work like many previous examples. It had to be !directory without the slash or * at the end.Silkworm
@FrankForte do you see the last line of my example, how is this contradicting with what you said ?Dog
T
5

I got this working

# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib
Thibaut answered 10/9, 2018 at 6:39 Comment(0)
H
4

Nothing worked for me so far because I was trying to add one jar from lib.

This did not worked:

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

This worked:

build/*
!build/libs
Hbeam answered 15/5, 2018 at 16:17 Comment(0)
C
4

I also had some issues with the negation of single files. I was able to commit them, but my IDE (IntelliJ) always complained about ignored files, which are tracked.

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

Displayed the two files, which I've excluded this way:

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

In the end, this worked for me:

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

The key was the negation of the folder typo3conf/ first.

Also, it seems that the order of the statements doesn't matter. Instead, you need to explicitly negate all subfolders, before you can negate single files in it.

The folder !public/typo3conf/ and the folder contents public/typo3conf/* are two different things for .gitignore.

Great thread! This issue bothered me for a while ;)

Chaucerian answered 12/7, 2018 at 15:51 Comment(0)
D
3

I seem to have found something that worked for me which no one else mentioned.

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

Basically, it seems to negate a sub-directory from being ignored, you have to have two entries, one for the sub-directory itself !subdir/ and then another one which expands to all files and folders under it !subdir/**/*

Desta answered 8/6, 2019 at 9:30 Comment(0)
O
3

It's a disaster that after 16 years (2005) of using git, there is no simple and obvious way to exclude one file when located deep in a directory hierarchy, that should otherwise be ignored. Instead we need to resort to crazy things like repeatedly digging down the structure and excluding and including directories in the correct order. Something which is darn right impossible to remember those 4 times a year you need to do it.

The only smart, but very weird alternative, is to use the git add --force. Something which is bound to fail at some point, when you're not working on the gitted repo alone.

So I wrote a small bash function to fix this for you, for easy copy paste. Let me first explain the one liner:

f=0; y='';for x in $(echo "uploads/rubbish/stuff/KEEP_ME/a.py" | tr '\/' '\n'); do y="$y/$x"; if [ $(($f)) -eq 0 ]; then y="$x"; f=1; fi; echo -e '!'"$y/\n$y/*"; done | sed '$d' |sed -z 's/..$//'; echo;

# output:
!uploads/
uploads/*
!uploads/rubbish/
uploads/rubbish/*
!uploads/rubbish/stuff/
uploads/rubbish/stuff/*
!uploads/rubbish/stuff/KEEP_ME/
uploads/rubbish/stuff/KEEP_ME/*
!uploads/rubbish/stuff/KEEP_ME/a.py

Description

  • There is an if statement to adjust for the 1st item not getting a /.
  • tr '\/' '\n' - translate the / to \n in standard POSIX paths (to get a list)
  • y="$y/$x" - add the next sub-dirctory (in list) after the previous directory.
  • echo -e '!'"$y/\n$y/*" -
    print the 2 lines of sub-directory item, 1st with ! prefix, and 2nd with /* postfix.
  • sed '$d' - remove last line
  • sed -z 's/..$//' - remove last 2 characters /* from last line

Then we create the function:

function gitkeep () { f=0; y='';for x in $(echo "$1" | tr '\/' '\n'); do y="$y/$x"; if [[ f -eq 0 ]]; then y="$x"; f=1; fi; echo -e '!'"$y/\n$y/*"; done | sed '$d' |sed -z 's/..$//'; echo; }

# gitkeep "uploads/rubbish/stuff/KEEP_ME/a"

!uploads/
uploads/*
!uploads/rubbish/
uploads/rubbish/*
!uploads/rubbish/stuff/
uploads/rubbish/stuff/*
!uploads/rubbish/stuff/KEEP_ME/
uploads/rubbish/stuff/KEEP_ME/*
!uploads/rubbish/stuff/KEEP_ME/a

Here I simplified the arithmetic if statement to if [[ f -eq 0 ]];.

Enjoy!

Outspeak answered 5/2, 2022 at 16:41 Comment(1)
This is quite promising and thanks for sharing. I have to point out that the answer here allows specification of multiple folders: e.g. KEEP_ME1/ and KEEP_ME2/ without repetition of the lines that may be common to these subfolders since they share the same parent folder. I suspect, that in the approach you have provided, one would have to separately list each folder KEEP_ME1/ and KEEP_ME2/Olag
M
1

Gist

# Ignore everything
*

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

And probably include:

!.gitignore

Reference

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

An optional prefix "!" which negates the pattern; any matching file excluded by a previous pattern will become included again. It is not possible to re-include a file if a parent directory of that file is excluded. Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined. Put a backslash ("\") in front of the first "!" for patterns that begin with a literal "!", for example, "\!important!.txt".

...

Example to exclude everything except a specific directory foo/bar (note the /* - without the slash, the wildcard would also exclude everything within foo/bar):

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar
Meshwork answered 13/1, 2020 at 21:42 Comment(0)
L
0

The aforementioned snippets work well but they are a little bit confusing. I found the right way with fail and try. Here is how I manage it to work;

  1. I have a folder called example_PostProcessingManager
  2. I want to exclude everything except the example_PostProcessingManager/src/ folder contents
  3. Also except the example_PostProcessingManager/bin/data/ folder contents

Briefly, I want to keep the contents of data and src folders and exclude anything else inside the example_PostProcessingManager folder

To do that I edit the .gitignore as follows;

# Exclude everything inside the root folder as follows
example_PostProcessingManager/*

# Include only src folder
!example_PostProcessingManager/src

# Include also bin folder because the data folder is inside this folder. 
!example_PostProcessingManager/bin

# Exclude everything inside the bin folder. I know we excluded everything above already.
# It doesn't make sense but this is the way...
example_PostProcessingManager/bin/*

# Now include everything inside the data folder.
!example_PostProcessingManager/bin/data

P.S. the main idea is you need to start from root folder and access the destination folder step by step. If you do it as follows, it will only include the src folder and ignores everything inside the data folder.

FAILED CASE

example_PostProcessingManager/*
!example_PostProcessingManager/src
!example_PostProcessingManager/bin/data
Leblanc answered 8/4, 2023 at 10:39 Comment(0)
G
0

Use a separate .gitignore further in the directory structure.

root
|- subdirA
   |- subdirA1
      |- file1.txt
      |- file2.txt
      |- README.md
      |- .gitignore

Use a .gitignore at the root, but then in root/subdirA/subdirA1, this would be the contents of the .gitignore

*
!README.md

Hope that helps!

Gyrus answered 22/4, 2023 at 5:53 Comment(0)
A
0

The contents of the file should be similar to the following

*
!app.py
!local.conf
!requirements.txt
!Dockerfile
!selenium_test/
selenium_test/*
!selenium_test/seleniumTest.py
!selenium_test/seleniumTest2.py
!selenium_test/seleniumTest3.py

Here with the '*' we are ignoring everything.

But with '!' we are saying to include something. Here app.py, local.conf, requirements.txt and Dockerfile are included.

Now including selenium_test folder with '!', because we need few files from this folder.

But in the next line we are excluding all the contents of the folder with selenium_test/*, because we do not need all the files from that folder but need only some of them.

Next we are specifying to include seleniumTest.py, seleniumTest2.py and seleniumTest3.py files which exist within the selenium_test folder.

Note: if we had not added the 6th and 7th line, then 8th, 9th and 10th line would not have worked, since the files specified in those lines would not have gotten the folder 'selenium_test' to reside, because we already have excluded it in the 1st line with the '*'.

Antoinetteanton answered 18/5, 2023 at 4:56 Comment(0)
C
0

Adding a .gitignore file inside the subfolder makes it easier to manage the ignored files.

Changeless answered 6/3 at 10:9 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewInherit

© 2022 - 2024 — McMap. All rights reserved.