Git ignore everything in a folder except some files

Git allows you to ignore files from version control using a file named .gitignore. There can be various cases where you would like to ignore almost everything in a folder, except a few files.

This could be the case when you would like to exclude everything in the current folder, but commit the .gitignore file, otherwise the next time you clone the repo, Git won’t know what you have excluded.

Solution

We need to use the * (star) operator to ignore everything, and then the ! (exclamation mark) operator to remove the exclusion from those files that you would like to keep.

This short quote from the documentation of gitignore describes the use of the ! operator.

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.

So, in our case we’ll have to use something like the following

# Ignore everything
*

# But not these files
!.gitignore
!important.txt

How to commit an empty directory to Git

There is no way to commit an empty directory to a Git repository, you have to put a file in the directory to be able to commit it to your repo. Here is an explanation from the Git FAQ:

Currently the design of the Git index (staging area) only permits files to be listed, and nobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it.
Directories are added automatically when adding files inside them. That is, directories never have to be added to the repository, and are not tracked on their own.

Possible paths

So now we know that we have to put a file in the directory. But what file should it be?

If we are forced to put in a file we should make the best of it. Use a file that has at least some use, or could have a use in the future.

Use a README file

Some say, that the best idea is to use a README file, and inside it, describe why did you leave this directory empty. This could be a good idea, but sometimes the reason for the directory being there is obvious (e.g. Controllers), you just don’t have any files in it, because you did not get to that point in the development.

Use a .gitignore file

Git uses the .gitignore file to determine which files to exclude from tracking in the repository. Putting in an empty one leaves the possibility of adding exclusion rules later.

Use a .gitkeep file

In some people’s opinion the filename should be descriptive about the purpose of it. They use a file named .gitkeep, that just means “Keep this folder in revision control, although it’s empty”.

 

 

Running git init with or without the bare option

As you probably know, the git init command is used to create a new Git repository. It initializes a new repository by creating an initial file and folder structure that is required for a Git repository to work and track changes in your project.

When running the git init command you can use the --bare option.

Without the bare option

git init

If you are not using the bare option, then these files will be placed in a .git named directory in the root of your project directory. In this case, your project directory will contain the current working files of your project alongside with the .git that contains all of the version tracking information. Most commonly this is the way you want to set up your repository because it allows you to work on your project and then commit your changes in your local repository.

With the bare option

git init --bare

If you use the bare option you will have all the files that would live in the .git folder directly placed under the root of your project directory. So in this case there will be no working files, only the repository files that contain all the version history of your project. This means that you cannot directly commit to this repository, you can only push changes to this repo or pull changes from it. This is the purpose of a bare repository: to have a centralized server (even though git is a decentralized version control system), where you can share your changes with your teammates or with the world.

Summary

When you want to work on your project, make changes to it, you need to have all the working files at your disposal…because you want to work with them. So in this case you have to use a non-bare repository.

When you want to create a central repository where people working on the same project can share their changes with each other then you need to create a bare repository.