We can use the literal ! to make gitignore include an ignored file or folder by negating a pattern.

Assuming we have a new initialized repo with the following structure:

1
2
3
4
5
6
7
8
.
├── .git(git repo configs)
├── .gitignore
├── file-a.txt
└── public
    ├── file-b.txt
    ├── file-c.txt
    └── file-d.txt

If we were to do a dry-run for adding the files we’d get:

1
2
3
4
5
6
7
8
git add . --dry-run 

# output
add '.gitignore'
add 'file-a.txt'
add 'public/file-b.txt'
add 'public/file-c.txt'
add 'public/file-d.txt'

Now let’s use the wildcard to ignore all the text files inside the public folder:

1
2
3
# .gitignore file

public/*.txt
1
2
3
4
5
git add . --dry-run 

# output
add '.gitignore'
add 'file-a.txt'

Now we can use the ! literal to actually include one of the ignored files:

1
2
3
4
# .gitignore file

public/*.txt
!public/file-c.txt
1
2
3
4
5
6
git add . --dry-run 

# output
add '.gitignore'
add 'file-a.txt'
add 'public/file-c.txt'

If we wanted to instead, add an empty folder, but ignore its contents, we can create an empty .gitkeep file(standard for including empty folders in git) and set it up like so:

1
2
3
4
5
6
7
8
9
.
├── .git(git repo configs)
├── .gitignore
├── file-a.txt
└── public
    ├── .gitkeep
    ├── file-b.txt
    ├── file-c.txt
    └── file-d.txt
1
2
3
4
5
# .gitignore file

# ignore everything inside but keep .gitkeep, thus keeping the empty folder
/public/*
!/public/.gitkeep