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:
.
├── .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:
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:
# .gitignore file
public/*.txt
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:
# .gitignore file
public/*.txt
!public/file-c.txt
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:
.
├── .git(git repo configs)
├── .gitignore
├── file-a.txt
└── public
├── .gitkeep
├── file-b.txt
├── file-c.txt
└── file-d.txt
# .gitignore file
# ignore everything inside but keep .gitkeep, thus keeping the empty folder
/public/*
!/public/.gitkeep