66

There's already several questions similar to this, but none of the answers work for me.

I want to ignore everything in the folders below my repository except files with *.foo

(If anyone is wondering how this can be justified - I'm actually making a git repository for all my "Logic" projects - music software on the mac - but I only want to store the actual project files *.logic)

I'm going to spell it out, so we're all on the same plate. Here's what I do, starting from scratch:

Setup:

mkdir temp
cd temp
mkdir testdir
cd testdir
touch include.foo
touch dontinclude.bad
cd..
git init
touch .gitignore

Paste this in to .gitignore

# Ignore all
/*

# But not these files...
!.gitignore
!*.foo

git status

And the only untracked file is .gitignore

if I typed 'git add .' - no change, only .gitignore is seen and my 2 files are ignored.

Why doesn't this work and how can you change the procedure above to make it work?

Here's the extremely similar question where I got the .gitignore file from. I'm using git --version 1.7.7 (also tried 1.7.3) - .gitignore to ignore all files, then recursively allows files of a certain type

Community
  • 1
  • 1
PandaWood
  • 8,086
  • 9
  • 49
  • 54
  • Wait, did you `git add .gitignore` and `git commit -m "added gitignore"` ? – Nic Nov 06 '11 at 03:22
  • 1
    fwiw, the granddaddy of duplicate answers on this topic--one that you should look over--would probably be [Make .gitignore ignore everything except a few files](https://stackoverflow.com/questions/987142/make-gitignore-ignore-everything-except-a-few-files) - very regular activity and several good answers. I'm a particular fan of [this answer](https://stackoverflow.com/a/29932318/5440638), which seems clear and thorough. – Kay V Jul 20 '18 at 01:52

1 Answers1

140

Your problem is that the /* pattern at the beginning is matching all files and directories at the top level - including testdir, so everything inside testdir is ignored.

This is what you want:

# Ignore everything
*
# Don't ignore directories, so we can recurse into them
!*/
# Don't ignore .gitignore and *.foo files
!.gitignore
!*.foo

When you do a git add . with this config, you should find you have only .gitignore and *.foo files listed as changes to be committed.

camh
  • 40,988
  • 13
  • 62
  • 70
  • though, as an aside, in my real world version with .logic files, it mysteriously doesn't work. I've recreated the git repo, checked a million times, copied the .gitignore in exactly, change to .logic, find . -name "*.logic" returns heaps of files but this .gitignore ignores all *.logic files... something stupid is surely going on... probably worth a follow up comment when I finally crack it – PandaWood Nov 06 '11 at 05:14
  • @PandaWood: Make sure you don't have `core.excludesfile` set in `~/.gitconfig` pointing to a file that has a pattern that would exclude your `*.logic` files. – camh Nov 06 '11 at 07:07
  • I didn't get this, but I was given a hint when I tried to upload these .logic files to DropBox the other day, it failed. Another hint is, I added !*.txt to .gitignore, as I have a few text files, and they began to appear in the tracked list, no worries. So Logic "files" (eg bla.logic) are actually "packages" - the ones you click on in Mac Finder and choose "Show Package Contents" - hence the *.logic in git is not working... how can I store these "files" in git then, might be my next question ;-) – PandaWood Nov 24 '11 at 12:04
  • @PandaWood: I don't know much about Mac OS X packages except from a quick search that indicated they are actually directories. So you will need a pattern to un-ignore whatever files are in package directories. – camh Nov 24 '11 at 20:41
  • yes, that's right, they are basically directories. The files inside can be all sorts of unknowns, so looks like I'll have to go opposite & work out all the files I can reasonably know not to "include" - which is not so bad, in this case. I can probably get away with excluding .wav .m4a *backup* and a few other things. I wrote this comment to confirm to anyone else doing the same thing with .logic files, that they should probably give up and and do what I'm suggesting with exclusions instead – PandaWood Nov 25 '11 at 00:59
  • @PandaWood: A little bit ugly, but you could use `!*.logic/`, `!*.logic/*`, `!*.logic/*/*` and so on up to a depth you think will capture the deepest directory hierarchy under a `*.logic` directory. – camh Nov 25 '11 at 07:17
  • 9
    I found that "don't ignore subdirectories" line to make excluding recursively work in .gitignore. For example, I wanted not to ignore a directory bar/. To do that, after the lines shown in this answer, I just added ```!bar/*``` and ```!bar/**/*``` and all the files in bar/ and its subdirectories recursively were not ignored. – yuvilio Aug 13 '12 at 00:44
  • 4
    the best gitignore answer I've found on Stackoverflow, due to the 'unignore .gitignore' part – RichVel Apr 08 '13 at 07:10
  • 1
    This solution. Specifically the command that prevents directories from being ignored (`!*/`) only seems to work if you apply it to the root directory. Therefore, if you want to apply it to a subdirectory you must create a new .gitignore file in the subdir. – Erpheus Mar 12 '18 at 11:54