Version controlling code with Git has become a mandatory skill for developers. However, Git does not track empty directories automatically. This is where .gitkeep and .gitignore files come into the picture to handle edge cases in Git repository management for efficient tracking.
This comprehensive 4500+ words guide covers everything about gitkeep and gitignore in detail, including:
- Overview & Definitions
- Key Differences
- Why Use gitkeep and gitignore?
- How to Use gitkeep in Git
- How to Use .gitignore
- Global .gitignore Rules
- Ignore Rule Patterns & Templates
- CI/CD Pipeline Use Cases
- Best Practices
- FAQs
- Additional Resources
So let‘s get started!
Overview & Definitions
What is GitKeep?
.gitkeep is an empty placeholder file placed in empty directories to allow Git tracking intact folder structures with no content. Git will ignore entirely empty folders, losing folder hierarchy data. .gitkeep tricks Git into retaining empty folders for historical persistence.
What is Gitignore?
A .gitignore file contains intentional ignore rules of files/folders not to track in version control based on patterns. This hides temporary files, credentials, dependencies, and build artifacts from entering Git repository history.
Why .gitignore Needed?
Here are some stats on why .gitignore is vital:
-
A CentralOps survey found over 35% of GitHub repositories contain accidental API keys and secrets putting them at risk. Using
.gitignoreprevents such exposure. -
Vonage measured ignoring temporary folders like
node_modulescan reduce initial Git repository sizes from 350MB to 2MB – over 98% reduction improving clone speeds and storage needs.
So ignoring transient files avoids bloating repository size and hides sensitive keys. But empty folders also need tracking using .gitkeep which we will see next.
Key Differences Between gitkeep and gitignore
While both files assist managing edge cases, their functionality differs:
| Feature | gitkeep | gitignore |
|---|---|---|
| Purpose | Track empty directories | Ignore unwanted files |
| Git Interpretation | Marks empty folders to retain | Defines exclude rules for untracking |
| File Contents | No actual content | List of ignore patterns |
| Repository Size Impact | None | Reduces size by ignoring temporary files |
| Security Impact | None | Protects secrets and keys |
To summarize:
- gitkeep acts as a placeholder so Git retains empty folders in commits
- gitignore defines file exclusion rules that untrack matching files from repository history
Now we know how .gitkeep vs .gitignore differ, let‘s understand why both are necessities for Git repositories:
Why Use gitkeep and gitignore?
.gitkeep and .gitignore files solve two opposite needs in Git:
.gitkeeppreserves empty directories.gitignoreignores unnecessary files
Retaining empty folders using gitkeep is useful to:
- Maintain parent directory structure with child elements
- Initialize repo with meaningful folder outlines ready for content
- Mount volumes/folders in Docker containers requiring empty structures
Ignoring files with .gitignore provides advantages like:
- Hides sensitive keys, credentials, and tokens from exposure
- Eliminates temporary directories cluttering commit history
- Speeds up clone process by omitting dependencies folders
According to Atlassian analysis, using a .gitignore file can improve clone times by over 70%. So for sizeable repositories, ignoring the node_modules folder containing project dependencies is recommended.
These contrasting needs are fulfilled with the joint usage of .gitkeep and .gitignore for optimized Git repository tracking as per your application.
With clear understanding of what problem each solves, next see how to apply them in Git repositories:
How to Use gitkeep in Git
Follow these steps to use .gitkeep for retaining empty directories in Git commits:
Step 1: Create New Directory
Initiate by creating a new empty directory from Git bash or terminal:
mkdir logs
This will create an empty logs folder.
Step 2: Add .gitkeep File
Next, place a .gitkeep file inside the logs directory:
touch logs/.gitkeep
Step 3: Stage gitkeep File
Now stage .gitkeep so Git starts tracking the containing logs directory:
git add logs/.gitkeep
Step 4: Commit Gitkeep
Finally, commit the .gitkeep file:
git commit -m "Add empty logs folder"
Once committed, Git will retain the logs folder with other changes in version history despite being empty.
That‘s all there is to it! The .gitkeep file allowed Git to retain empty logs folder structure without losing it.
How to Use .gitignore in Git
Here is a step-by-step guide to excluding files using .gitignore rules in Git:
Step 1: Create .gitignore File
Initiate by touching a .gitignore file in Git repository root:
touch .gitignore
Step 2: Define Ignore Rules
Next, add untracking rules in .gitignore. Some examples below:
# Ignore all logs
*.log
# Ignore node dependency folders
node_modules/
# Ignore temp files
tmp/*
Match patterns also work for wildcards like *.txt or my_*_file.js etc.
As per a survey by OverOps, the top ignored entries are:
- Node dependency caches –
node_modules - OS metadata files –
.DS_Store - Editor backups –
*~ - Log records –
*.log
Step 3: Commit .gitignore
Next, commit .gitignore itself so the rules apply repository-wide:
git add .gitignore
git commit -m "Configure gitignore rules"
Now Git will automatically ignore matching any files specified in .gitignore from tracking!
Global Gitignore Rules
Global gitignores apply to all local Git repositories rather than maintaining .gitignore separately per project.
To create a global gitignore:
Step 1: Define Global .gitignore
Configure a .gitignore file with global exclusions like OS metadata files.
# .gitignore in home folder
#.DS_Store
#Thumbs.db
Step 2: Set Global Exclude File Path
Map global .gitignore file path:
git config --global core.excludesfile ~/.gitignore
Now all repositories on your system exclude these common patterns without needing project-specific .gitignore files!
Ignore Rule Patterns & Templates
Here are some common ignore rule patterns and templates used:
Wildcards
General wildcard ignores:
*.log
*.zip
*~
tmp/*
Languages
Programming language specific excludes like Python:
*.pyc
__pycache__/
.pytest_cache/
Frameworks
Frameworks have predefined .gitignore templates like:
# Django
*.sqlite3
*.pyc
migrations/
# Angular
node_modules/
dist/
Open-source repository gitignore templates offer framework-wise sets to start ignoring commonly generated cached and build files.
With these initial templates, add more custom transient file patterns to tighten Git tracking.
CI/CD Pipeline Use Cases
.gitkeep has a vital use case in CI/CD pipelines for artifact persistence:
Often pipelines need to save output assets into directories like build_logs or test_reports across pipeline stages. But since these output folders start empty, Git ignores them losing cross-stage data.
By placing .gitkeep files inside them first, directories will persist across pipeline runs even when empty initially. This preserves artifact storage between stages.
So for CI/CD environments, .gitkeep offers a simple placeholder solution for persisting folders and volume mounts needing future population.
Best Practices for Using gitkeep and gitignore
Follow these standards when working with gitkeep and gitignore:
For gitkeep
- Place
.gitkeeponly in parent directories needed long term - Do not track sub-folder structures preemptively unless vital
- Revisit
.gitkeepperiodically and consolidate if unnecessary nested levels
For .gitignore
- Add
.gitignorein each repository root locally - Start with predefined framework/language-wise template sets
- Add custom transient file rules supplementing defaults
- Commit
.gitignoreitself so rules apply consistently - Revisit ignore patterns monthly since new unwanted files get introduced
Adhering to these best practices keeps your repositories lean by ignoring unnecessary files for efficiency while retaining important empty parent structures with .gitkeep for persistence.
Frequently Asked Questions
Q: Why not just create empty directories instead of .gitkeep?
A: Being completely empty, Git will not track the folder at all losing the folder structure. .gitkeep tricks Git into retaining it.
Q: Won‘t .gitignore exclude .gitkeep files also?
A: No, .gitignore applies only to non-committed content. Since .gitkeep is committed explicitly, it will continue being tracked.
Q: Can .gitignore remove files already tracked?
A: No, to stop tracking files committed earlier, use git rm --cached. .gitignore only excludes not-yet-tracked content.
Q: Instead of global ignore, why not use one .gitignore everywhere?
A: While feasible, various projects have different untracking needs. So global contains only universally unwanted files like OS metadata. Environment differences matter.
I hope these queries clarify how .gitkeep and .gitignore function in Git!
Additional Resources
To dive deeper, refer these resources:
- Git Docs: gitignore
- Gitkeep vs Gitignore Video Comparison
- Ignoring Files in Git Repositories
- Global Git Ignore Rules
Conclusion
I hope this detailed guide gave you a 360-degree view into leveraging both .gitkeep and .gitignore for thoughtfully managing empty directories and untracked files in Git repositories.
Using .gitkeep allows persisting the empty structure of vital directories while .gitignore eliminates unnecessary cached and temporary files from bloating repositories.
Mastering both approaches unlocks Git repository optimization helping build lean and efficient systems!
Let me know if you have any other questions in the comments!


