Gitignore File For Your Python Project: How Does It Look Like?

A gitignore file contains information about files and directories that Git should ignore. In this tutorial, you will learn how to use gitignore files in your Python project!

What is Gitignore and Why Do You Need It?

A file in a Git repository can be either tracked or untracked. Tracked files are files Git knows about, everything else is untracked. Git will not start tracking untracked files unless you request to do so.

A gitignore file plays a crucial role in explicitly specifying the files Git should ignore and helps avoid pushing by mistake files that shouldn’t be tracked in a repository.

Examples of files that shouldn’t be tracked in a Git repository are files that contain sensitive data (e.g. passwords), log files, or files generated by a build system.

A gitignore file consists of generalized patterns that can match a wide variety of files. The name of this file is actually .gitignore. It starts with a dot (.).

As a general rule, add a .gitignore file to your repository when you create it and before starting to make any changes to your project.

Let’s learn how to edit .gitignore files manually and write gitignore patterns.

Create gitignore files with Glob Patterns

Glob patterns are extensively used in gitignore files to denote a wide range of possible patterns to ignore. If you have ever worked with regular expressions, you are already familiar with some of them.

We will test these patterns while going through them…

Create a directory called git_ignore on your machine, access the directory, and then use the git init command to add this directory under Git control.

$ mkdir git_ignore
$ cd git_ignore 
$ git init
Initialized empty Git repository in /opt/git_ignore/.git/

Let’s examine some of the most common globbing expressions:

One of the most commonly used gitignore patterns is the asterisk (*). An asterisk stands for zero or more characters (except slashes).

*.log

This expression matches any files with .log extensions (log files). Create a .gitignore file and add the expression above to it.

Note: every time you change the .gitignore file remember to commit it to your repository (use the git add and git commit commands).

Now, create two .log files inside the repo directory:

$ touch access.log
$ mkdir var
$ touch var/access.log

Then confirm that the git status command doesn’t show them considering that they are ignored based on the *.log pattern in the .gitignore file.

$ git status
On branch master
nothing to commit, working tree clean

Create a file that doesn’t match the .log extension and confirm that is not ignored by Git:

$ touch access.out 
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	access.out

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

Another common wildcard you can use as part of patterns is the question mark that represents one character:

data?.csv

This pattern matches files called data1.csv or data2.csv but not data12.csv considering that the question mark represents a single character.

And here is a third common pattern…

Numerical and alphabetical ranges specified using square brackets can be used as well in gitignore files.

For example, the following pattern matches data0.txt, data1.txt, …, data9.txt:

data[0-9].txt

Similarly, the pattern below matches data_a.txt and data_b.txt.

data_[a-b].txt

How Do You Ignore all PYC Files in a Git Repository?

A common requirement when working on a Python project is to make sure that any .pyc files generated by the Python interpreter on your local machine don’t get committed to your Git repo.

Achieving this using the .gitignore file is relatively easy…

You can use the following expression similar to the one we have seen in the previous section:

*.pyc

Also, another example of a pattern you will need in your Python gitignore file is the following that ignores the __pycache__ directory:

__pycache__/

This is a start but it’s not a full list of what you might need for your Python project.

Here is an example of Python gitignore file you can look at for more ideas.

How to Disable Recursive Behaviour in gitignore Patterns

In the previous section, you have seen that the *.log pattern has matched a file in the current directory and a file in the var subdirectory.

By default, glob patterns are applied recursively to the entire directory structure. Add a forward slash ( / ) at the beginning of a gitignore pattern to disable the recursive behavior.

Update the existing pattern to the following:

/*.log

And execute the git status command:

$ git status    
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	access.out
	var/

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

After this change, Git tracks the content of the var directory because we are not ignoring the file var/access.log anymore.

Can You Apply a gitignore Pattern to All Subdirectories?

Let’s say you want to ignore the pattern test_pattern123 in all subdirectories of your repo you can use the following pattern:

**/test_pattern123

Two asterisks followed by a slash before a pattern match that pattern for a file or directory in all subdirectories.

This can be useful if you want to ignore a specific pattern based on more complex conditions.

For example, let’s say you want to ignore .pyc files anywhere in your Git repo only if they are inside a directory called test_pattern123. You can use the following expression:

**/test_pattern123/*.pyc

And don’t worry if some of these patterns may seem a bit complex!

Most of the time the patterns you need in your .gitignore files are fairly simple.

How to Ignore All the Files in a Directory With a gitignore File

The gitignore pattern to ignore all the files in a directory is the directory name followed by a trailing /**. This pattern is relative to the location of the .gitignore file.

For example, if the directory name is ignore_dir and this directory is inside a directory called test the pattern will be the following:

test/ignore_dir/**

To become more familiar with these patterns make sure to test them on your machine.

How to Negate a gitignore Pattern

A frequently used globbing pattern is the negating pattern denoted with an exclamation mark: !. A leading exclamation mark does not ignore the specified pattern.

For instance, the following two lines ignore data.txt but don’t ignore data.csv.

data.*
!data.csv

Can You Use Blank Lines in a .gitignore File?

Blank lines in a gitignore file match no patterns and they are generally used to make the gitignore file more readable.

Also to add a comment to a .gitignore file you can start a line with the hash character (#). You would use a comment to explain the reason for patterns added to the gitignore file over time.

How to Escape a Character in a .gitignore File

To escape a character in a gitignore file and interpret the character literally you can use the backslash. For instance, the hash is used for comments but you can interpret it as a character inside a pattern by escaping it with a backslash.

Here is an example…

Create a file called #testfile and run the git status command:

$ touch #testfile
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	#testfile

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

As you can see this new file is marked as untracked.

Now add the following pattern to your .gitignore file (commit the file as usual after the change):

\#test*

Rerun the git status command and you will see that Git doesn’t detect the file #testfile anymore:

$ git status
On branch master
nothing to commit, working tree clean

Without the backslash, the line #test* would be interpreted as a comment in the .gitignore file.

An Exception to the Rule: How to Commit Ignored Files?

The intention of this section is just to give you a full understanding of what you can do with your Git repository. This doesn’t mean that you should bypass .gitignore patterns.

In most cases, there is a reason why those patterns have been added to the .gitignore file for your repo (unless a pattern is unintentionally incorrect).

Let’s assume you have the following pattern in a gitignore file and you want to commit the file sample.html to your repository.

*.html

Here is what happens if you try to stage it:

$ git add sample.html
The following paths are ignored by one of your .gitignore files:
sample.html
Use -f if you really want to add them.

Git tells you that this file is ignored so it prevents you from making a mistake.

In the git add output you can also see that you can pass the -f flag if you want to stage this file.

Let’s try it (again…not recommended!)

$ git add -f sample.html
$ git commit -m "sample.html added despite gitignore pattern"

A better option would be to use the negate pattern we have seen in one of the previous sections:

*.html
!sample.html

Conclusion

Git .gitignore files are widely used and they are important for Git to know which files it should ignore so you can keep your repositories clean and safe.

In this tutorial, you have learned the fundamentals of gitignore files and patterns, and you are now ready to use gitignore files in your Python projects.

Bonus read: In this article, we have briefly talked about .pyc files. Learn more about .pyc files in Python.

Leave a Comment