Working with Git Shallow Clones: From Clone to Commit and Push
Posted on August 21, 2025
Hey there!
So, you've found yourself needing to work on a git project, but you don't want to download the entire history? Or maybe you're working with a massive repository and just need to make a quick fix? That's where shallow clones come in handy!
In this post, I'll walk you through the complete workflow of working with a shallow clone - from the initial clone to making changes and pushing them back to the repository.
What is a Shallow Clone?
A shallow clone is a git clone that only downloads the most recent commit (or a limited number of commits) instead of the entire repository history. This is incredibly useful when:
- You're working with large repositories with extensive history
- You only need to make a quick fix or small change
- You want to save bandwidth and disk space
- You're working in CI/CD environments where you don't need full history
The Workflow: Step by Step
1. Creating a Shallow Clone
The magic happens with the --depth 1
flag:
git clone --depth 1 https://github.com/username/repository.git
cd repository
This creates a clone with only the latest commit. You can also specify a different depth if you need a few more commits:
git clone --depth 5 https://github.com/username/repository.git
2. Understanding What You Have
After cloning, you'll notice some differences from a full clone:
# Check the git log - you'll see limited history
git log --oneline
# Check if you have a shallow repository
git rev-parse --is-shallow-repository
# Output: true
3. Making Your Changes
Now you can work on the files just like any other git repository:
# Edit your files
vim src/main.js
# Check what you've changed
git status
# See the differences
git diff
4. The Challenge: Pushing from a Shallow Clone
Here's where things get interesting. By default, you can't push from a shallow clone because git doesn't have the full history to create a proper commit chain. But there are several ways to handle this:
Option A: Convert to Full Clone (Recommended for Small Repos)
If the repository isn't too large, you can fetch the full history:
# Fetch the complete history
git fetch --unshallow
# Now you have a full clone and can push normally
git add .
git commit -m "Fix the bug in main.js"
git push origin main
Option A.1: When Disk Space is Limited
For massive repositories like Linux kernel, Chromium, or large monorepos, git fetch --unshallow
might fail due to disk space constraints. Here are your alternatives:
Strategy 1: Push to a New Branch (Recommended)
# Create a new branch from your shallow clone
git checkout -b fix/your-bug-fix
# Make your changes
git add .
git commit -m "Fix the critical bug"
# Push the new branch
git push origin fix/your-bug-fix
Then create a pull request from the web interface. This is the safest approach for open source contributions.
Strategy 2: Use GitHub's Web Editor For simple changes, use GitHub's built-in file editor:
- Navigate to the file on GitHub
- Click the pencil icon to edit
- Make your changes
- Commit directly through the web interface
Strategy 3: Patch-based Workflow
# Create a patch file from your changes
git format-patch HEAD~1
# This creates a .patch file you can share
# Others can apply it with: git apply your-changes.patch
Strategy 4: Selective Fetch If you need some history but not all:
# Fetch only recent history (last 100 commits)
git fetch --depth 100 origin main
# Or fetch specific date range
git fetch --shallow-since="2024-01-01" origin main
Option B: Push with Force (Use with Caution)
For quick fixes where you're sure about your changes:
git add .
git commit -m "Quick fix for the issue"
git push --force-with-lease origin main
⚠️ Warning: Only use force push when you're certain no one else has pushed changes since your clone.
Option C: Create a New Branch
A safer approach is to create a new branch:
# Create and switch to a new branch
git checkout -b fix/quick-bug-fix
# Make your changes
git add .
git commit -m "Fix the bug in main.js"
# Push the new branch
git push origin fix/quick-bug-fix
Then create a pull request from the web interface.
Real-World Example
Let me walk you through a real scenario I encountered recently:
# 1. Clone a large repository with shallow depth
git clone --depth 1 https://github.com/some-org/massive-project.git
cd massive-project
# 2. Check what we have
git log --oneline
# Output: abc1234 (HEAD -> main) Latest commit message
# 3. Make a quick fix
echo "// Fixed the bug" >> src/config.js
# 4. Stage and commit
git add src/config.js
git commit -m "Fix configuration issue"
# 5. Push (using force since it's a shallow clone)
git push --force-with-lease origin main
Best Practices
When to Use Shallow Clones
✅ Good use cases:
- Quick bug fixes
- Documentation updates
- CI/CD pipelines
- Large repositories where you only need recent changes
- Temporary work that doesn't require full history
❌ Avoid when:
- You need to understand the project's evolution
- You're doing major refactoring
- You need to bisect bugs
- You're contributing to open source projects (usually)
Disk Space Considerations
Before cloning large repositories:
# Check available disk space
df -h
# Estimate repository size (if possible)
# Most large repos show size on GitHub/GitLab
Repository size guidelines:
- < 100MB: Safe to use
git fetch --unshallow
- 100MB - 1GB: Consider selective fetch or branch-based workflow
- > 1GB: Use shallow clone + branch workflow or web-based editing
- > 10GB: Web-based workflow or patch-based contribution recommended
Safety Tips
Always check the remote status first:
bashgit fetch origin git status
Use
--force-with-lease
instead of--force
:bash# Safer than --force git push --force-with-lease origin main
Consider creating feature branches:
bashgit checkout -b feature/your-change # Make changes git push origin feature/your-change
Communicate with your team: Let others know when you're working with shallow clones to avoid conflicts.
Troubleshooting Common Issues
Issue: "Shallow update not allowed"
# Error: Shallow update not allowed
git push origin main
Solution: Use one of the methods above (fetch --unshallow, force push, or new branch).
Issue: "Rejected non-fast-forward"
# Error: ! [rejected] main -> main (non-fast-forward)
Solution: Someone else has pushed changes. Fetch the latest and rebase:
git fetch origin
git rebase origin/main
git push origin main
Issue: "Cannot lock ref"
# Error: cannot lock ref 'refs/remotes/origin/main'
Solution: Clean up the repository:
git remote prune origin
git gc --prune=now
Issue: "No space left on device" during fetch --unshallow
# Error: fatal: write error: No space left on device
git fetch --unshallow
Solutions:
Check available disk space:
bashdf -h du -sh .git
Use alternative strategies:
- Push to a new branch instead:
git push origin your-branch
- Use GitHub's web editor for simple changes
- Create a patch file:
git format-patch HEAD~1
- Push to a new branch instead:
Clean up git objects:
bashgit gc --prune=now git remote prune origin
Use selective fetch:
bash# Instead of full history, get recent commits only git fetch --depth 100 origin main
Advanced Techniques
Handling Massive Repositories
When working with extremely large repositories (like Linux kernel, Chromium, or large monorepos), disk space becomes a critical constraint. Here are specialized strategies:
Repository Size Examples
- Linux kernel: ~1.5GB+ (full history)
- Chromium: ~30GB+ (full history)
- Large monorepos: Can exceed 50GB+
Strategy: Minimal Working Clone
# Clone with minimal depth and single branch
git clone --depth 1 --single-branch --branch main https://github.com/massive/project.git
# Check disk usage
du -sh .git
# Output: ~50MB instead of ~30GB
Strategy: Web-based Workflow
For simple changes, avoid local cloning entirely:
- Fork the repository on GitHub
- Use GitHub's web editor for file changes
- Create pull request directly from the web interface
- Review and merge through GitHub's interface
Strategy: Patch-based Contribution
# Create a minimal clone
git clone --depth 1 https://github.com/massive/project.git
cd project
# Make your changes
vim src/your-file.cpp
git add src/your-file.cpp
git commit -m "Fix critical bug in module"
# Create a patch file
git format-patch HEAD~1
# Creates: 0001-Fix-critical-bug-in-module.patch
# Share the patch file (email, issue, etc.)
# Others can apply: git apply 0001-Fix-critical-bug-in-module.patch
Strategy: Selective History Fetch
If you need some context but not everything:
# Fetch only recent commits
git fetch --depth 50 origin main
# Fetch commits from specific date
git fetch --shallow-since="2024-01-01" origin main
# Fetch specific branch with limited depth
git fetch --depth 10 origin feature-branch
Partial Shallow Clones
You can also create shallow clones of specific branches:
# Clone only the main branch with depth 1
git clone --depth 1 --branch main https://github.com/username/repo.git
# Clone multiple branches with different depths
git clone --depth 1 https://github.com/username/repo.git
cd repo
git fetch --depth 5 origin develop
Converting Shallow to Full
If you later decide you need the full history:
# Fetch all history
git fetch --unshallow
# Or fetch specific branches
git fetch --unshallow origin main
git fetch --unshallow origin develop
The Takeaway
Shallow clones are a powerful tool in your git arsenal, especially when working with large repositories or making quick fixes. The key is understanding the limitations and choosing the right approach for pushing your changes.
Remember:
- Shallow clones save time and space but limit your git operations
- Always consider the team when using force pushes
- Feature branches are often safer than direct pushes to main
- Know when to convert to a full clone if you need more git functionality
The workflow I've outlined here has saved me countless hours when working with large repositories, especially in CI/CD environments where I only need to make small changes.
Happy coding!
P.S. If you're interested in more advanced git workflows, check out my other posts about automating package publishing with GitHub Actions and working with different git strategies.