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
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/*
Answered 2023-09-20 20:28:31
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/*
- anyone !*/
exception - anyone !*/
makes all the difference in my futile attempts to wrangle a .gitignore
file to work. Thank you very much. - anyone 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.
Answered 2023-09-20 20:28:31
foo
and foo/*
are not the same. For this to work, you need to use foo/*
for the base folder - anyone !.gitignore
or else this wont work. .gitignore
file will also untracked by git - anyone 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
Answered 2023-09-20 20:28:31
.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. - anyone /*
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"... - anyone 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
Answered 2023-09-20 20:28:31
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.
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
Answered 2023-09-20 20:28:31
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)
Answered 2023-09-20 20:28:31
!*/
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. - anyone 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/*
Answered 2023-09-20 20:28:31
git status
to check if your changes to .gitignore
work as expected - anyone 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? - anyone You can use git config status.showUntrackedFiles no
and all untracked files will be hidden from you. See man git-config
for details.
Answered 2023-09-20 20:28:31
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
Answered 2023-09-20 20:28:31
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
.
Answered 2023-09-20 20:28:31
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://stackoverflow.com/a/5250314/1696153
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!
Answered 2023-09-20 20:28:31
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
Answered 2023-09-20 20:28:31
I had a problem with subfolder.
Does not work:
/custom/*
!/custom/config/foo.yml.dist
Works:
/custom/config/*
!/custom/config/foo.yml.dist
Answered 2023-09-20 20:28:31
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
Answered 2023-09-20 20:28:31
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.
Answered 2023-09-20 20:28:31
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
Answered 2023-09-20 20:28:31
That's what have worked for me, I wanted to commit only one Cordova plugin to the repo:
...
plugins/*
!plugins/cordova-plugin-app-customization
Answered 2023-09-20 20:28:31
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.
Answered 2023-09-20 20:28:31
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.
Answered 2023-09-20 20:28:31
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.
Answered 2023-09-20 20:28:31
!directory/*
did not work like many previous examples. It had to be !directory
without the slash or * at the end. - anyone I got this working
# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib
Answered 2023-09-20 20:28:31
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
Answered 2023-09-20 20:28:31
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 ;)
Answered 2023-09-20 20:28:31
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/**/*
Answered 2023-09-20 20:28:31
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
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/*"
-!
prefix, and 2nd with /*
postfix.sed '$d'
- remove last linesed -z 's/..$//'
- remove last 2 characters /*
from last lineThen 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!
Answered 2023-09-20 20:28:31
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/
- anyone # Ignore everything
*
# But not these files...
!script.pl
!template.latex
And probably include:
!.gitignore
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 withinfoo/bar
):$ cat .gitignore # exclude everything except directory foo/bar /* !/foo /foo/* !/foo/bar
Answered 2023-09-20 20:28:31
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;
example_PostProcessingManager
example_PostProcessingManager/src/
folder contentsexample_PostProcessingManager/bin/data/
folder contentsBriefly, 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
Answered 2023-09-20 20:28:31
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!
Answered 2023-09-20 20:28:31
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 '*'.
Answered 2023-09-20 20:28:31