1

I have the following directory structure:

./
├── proj-1
│   ├── README.md
│   ├── src/
│   └── test/
└── proj-2
    ├── README.md
    ├── src/
    └── test/

How can I ignore everything except for the src/ directories using just one .gitignore file in the root directory?

I've tried:

*
!.gitignore
!/*/src/
!/*/src/*

But that doesn't seem to pick up the directories I want after running git status.

Any tips?

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
Adam Jarvis
  • 183
  • 1
  • 13
  • Possible duplicate of https://stackoverflow.com/questions/3001888/how-do-gitignore-exclusion-rules-actually-work – negacao Nov 04 '17 at 17:44
  • That is somewhat unrelated @negacao, as it assumes you have a fixed number of directories within the root directory. I want a general rule of: ignore all except a directory that has a `/src` directory in the next level, then, include all files in that chain – Adam Jarvis Nov 04 '17 at 17:55

1 Answers1

1

You have to recursively un-ignore all parent directories of the src directory tree, then ignore their content:

# Ignore everything
*

# Unignore .gitignore
!.gitignore

# Unignore all directories
!*/

# Ignore contents of all directories
*/*

# Unignore all src subdirectories
!*/src/

# Unignore directory tree under src subdirectories
!*/src/**

So, for a tree that looks like

.
├── proj-1
│   ├── README.md
│   ├── src
│   │   ├── srcfile1
│   │   ├── srcfile2
│   │   ├── srcfile3
│   │   └── subsrc
│   │       ├── subsrcfile1
│   │       ├── subsrcfile2
│   │       └── subsrcfile3
│   └── test
│       ├── testfile1
│       ├── testfile2
│       └── testfile3
├── proj-2
│   ├── README.md
│   ├── src
│   │   ├── srcfile1
│   │   ├── srcfile2
│   │   └── srcfile3
│   └── test
│       ├── testfile1
│       ├── testfile2
│       └── testfile3
└── proj-3
    └── file

you get this status

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    .gitignore
    proj-1/
    proj-2/

nothing added to commit but untracked files present (use "git add" to track)

and after adding everything, you get

$ git add * .gitignore 

$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   .gitignore
        new file:   proj-1/src/srcfile1
        new file:   proj-1/src/srcfile2
        new file:   proj-1/src/srcfile3
        new file:   proj-1/src/subsrc/subsrcfile1
        new file:   proj-1/src/subsrc/subsrcfile2
        new file:   proj-1/src/subsrc/subsrcfile3
        new file:   proj-2/src/srcfile1
        new file:   proj-2/src/srcfile2
        new file:   proj-2/src/srcfile3

.gitignore has to be added explicitly because the shell doesn't expand * to include hidden files.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116