A few days ago, I was working on a side project and wanted to hide a few files from Git. In the process,
.gitignore caught my eye, and I started digging deeper into it.
.gitignore ignores files or directories but doesn’t hide them, but how? Let’s investigate!
.gitignore file is used to specify files or directories that should be ignored
by Git when tracking changes in our project.
The purpose of
.gitignore is to prevent files from being accidentally committed to repositories that are not intended to.
When we create a project, generally we won’t see a
.gitignore file; we have
to manually create it. As a rule of thumb, it has to be located in the root
directory of our Git repository.
Patterns Are Everywhere
If we want to just ignore a file or a directory, we can just open the
file and add the name of the file (For example: test.txt) or directory(For
example: /logs) and save it. But what if we want to specify a bunch of files or
.gitignore has some common patterns such as filename patterns, directory
patterns, negation patterns etc., which help us to ignore bunch of files
For instance, in filename patterns, if we specify
*.log, it’s going to ignore all
files. In case of directory patterns, if we specify
/build/, it’s going to
We can also use negation patterns, like if we use
!secret.md, it’s going to
exclude a specific file from being ignored.
Patterns Have Rules
For those of us who are familiar with regex and glob patterns in shell, these rules are pretty easy to comprehend.
* - matches zero or more characters. ? - matches a single character. # - comments. / - directory seperator.
.gitignore file doesn’t hide files or folders; rather, it instructs Git to
ignore and exclude specific files or directories from being tracked and included
in the version control system. And this is an important aspect. When files are
.gitignore, Git will simply disregard them when performing various
git add and
When we initialize a Git repository or add existing files to it, Git starts
tracking changes in those files. The
.gitignore file contains patterns and rules that specify which files or directories should be ignored by Git.
When Git encounters a file or directory listed in the
.gitignore file, it checks whether it matches any of the patterns in the file. If there is a match, Git treats that file or directory as “untracked” and does not include it in Git’s operations.
When we run Git commands like
git add, or
git commit, Git examines the
.gitignore file to determine which files should be excluded from these operations.
Files that match the patterns in the
.gitignore file are not displayed in
git status, and they are not included when we use
git add to stage changes.
Finally, when we use
git commit, ignored files are not included in the commit, ensuring they are not added to the version history.
Uff, that was a lot. Let’s move on!
Where Do The Files Live
When a file is ignored by a
.gitignore rule, it continues to exist in our project’s directory structure on our local file system, but Git does not actively track or manage it.
Meaning, the file is still physically present in the same location as before, but Git treats it as if it doesn’t exist within the context of version control.
Time to get our hands dirty and see how
First, let’s create a dummy repository called
test on Github and clone it to our
Next we’ll create some files namely, file1, file2, file3, file4 and file5.
Let’s add some content to
file1 and include that in
Now as we can see, we can’t see the
file1 when we use
git status as it’s
After we commit and push the changes, let’s check what has happened to our missing file. In order to do that, we can simply type
git log --stat to see what has happened to our previous commit.
So we can see a change has been made to our
To investigate further, let’s use
git log -p, where
Look what we got here. Let’s break down line by line.
diff --Git a/.gitignore b/.gitignore - This line indicates that Git is showing a difference(diff) between two versions of the same file named
b/.gitignore represent the “old” and “new” versions of the file, respectively.
new file mode 100644 - This line specifies the file mode for the new
.gitignore file. In this case, it’s set to 100644, which is the standard file mode for regular files in Git.
index 0000000..e212970 - This line shows the Git object IDs (SHA-1 hashes) for the old and new versions of the file. In this case, the old version is represented as all zeros (0000000), indicating that it’s a new file, and the new version has the SHA-1 hash e212970.
/dev/null +++ b/.gitignore - This line is interesting and it indicates that the old version of the file (before the commit) is considered non-existent (/dev/null), and the new version of the file is named
+++ b/.gitignore part).
@@ -0,0 +1 @@ - This line is part of the unified diff format and provides context for the changes. It specifies the line numbers that are being compared between the old and new versions of the file. In this case, it says that there are no lines in the old version (-0,0) and one line in the new version (+1).
Finally, we caught our
+file1 - This line represents the actual change made in the commit. It indicates that the new
.gitignore file contains one line, which is
file1. This means that the commit added a rule to the
.gitignore file to ignore a file named
And an important thing to note here is, it’s not going to hide our files. If our repository is public and if someone clones the repository, they can still get information about our commit messages, branch names, file paths and so on.
Then how can we hide our files or make it inaccessible to others? You should wait for my next blog post!
Follow me on other social media