.gitignore files added inside Git submodules
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A Git submodule is a separate Git repository nested inside another repository. That separation is the key to understanding ignore behavior: the parent repository does not control which files a submodule tracks internally. Ignore rules inside a submodule belong to the submodule repository, not to the superproject.
Why the Parent .gitignore Does Not Reach Inside
When a repository contains a submodule, the parent repository tracks the submodule as a special entry that points to a specific commit. It does not track the submodule's individual files directly.
That means a .gitignore file in the parent project affects paths that belong to the parent repository, but not the internal file set of the submodule.
A structure like this helps make the boundary clear:
The parent .gitignore can ignore app/build/ or tmp/ in main-repo, but it cannot decide whether vendor/lib-a/generated.txt is ignored inside lib-a. That decision belongs to the submodule's own Git metadata.
Ignore Files in the Submodule Itself
If you want a file inside the submodule to be ignored by Git, you must add the rule in the submodule repository.
For example, from inside the submodule:
Now Git evaluates build/ according to vendor/lib-a/.gitignore, because vendor/lib-a is its own repository.
If the ignore rule should be shared with everyone using the submodule, commit that .gitignore change in the submodule repository:
Then update the superproject to point at the new submodule commit:
That two-step commit flow is normal for submodules.
Ignore Local-Only Files Without Changing the Submodule Repo
Sometimes you do not want to modify the shared .gitignore in the submodule. Maybe the ignored file is local to your workstation. In that case, use the submodule's local exclude file:
.git/info/exclude behaves like a local ignore file that is not committed. It is useful for editor files, machine-specific build output, or temporary artifacts that only exist in one developer environment.
This is usually better than editing a committed .gitignore if the ignore rule should not be shared with the team.
What the Superproject Actually Sees
From the parent repository's perspective, the submodule is mostly one tracked entry. The superproject notices when the submodule's checked-out commit changes, and it can also show that the submodule has uncommitted changes inside it.
A typical status in the parent repository might look like this:
Output often includes something conceptually like this:
or this:
That does not mean the parent repository is tracking each file inside the submodule. It means Git sees that the submodule repository is not in the clean state expected by the superproject.
Useful Configuration for Dirty Submodules
If local changes inside a submodule create too much noise in the parent repository, Git can be configured to reduce how aggressively it reports them.
For example:
This tells the superproject to ignore uncommitted changes when reporting that submodule's state. It does not change how the submodule itself tracks files. It only changes what the parent repository reports.
That is a visibility setting, not an ignore rule in the normal .gitignore sense.
Common Pitfalls
The most common mistake is adding a pattern to the parent .gitignore and expecting it to ignore files inside the submodule repository. Another is changing the submodule's .gitignore but forgetting to commit that change inside the submodule and then update the recorded submodule commit in the parent repository. Teams also sometimes use .git/info/exclude when the rule should actually be shared, which leaves other developers with the same noisy files. A final issue is confusing submodule.<name>.ignore configuration with real ignore rules, even though it only affects how the superproject reports submodule dirtiness.
Summary
- A submodule is a separate Git repository with its own ignore rules.
- The parent repository's
.gitignoredoes not control files inside the submodule. - Shared ignore rules belong in the submodule's committed
.gitignore. - Local-only ignore rules belong in the submodule's
.git/info/exclude. - The superproject tracks the submodule commit and can report dirty state, but it does not directly manage the submodule's internal tracked files.

