Automatically discover and update all git repositories in a directory tree
Project description
๐ด Gitty Up!
Never forget to pull again
Automatically discover and update all your Git repositories with one command
Features โข Installation โข Quick Start โข Documentation โข FAQ
๐ฏ The Problem
You're about to start coding. You open your project, dive into the code, make changes... then realize you forgot to git pull. Now you're dealing with merge conflicts, rebasing headaches, and lost time. Sound familiar?
When you're juggling multiple projects, working across different machines, or collaborating with a team, keeping every repository up-to-date becomes a mental burden. One forgotten git pull can derail your entire workflow.
โจ The Solution
Gitty Up is your automated Git guardian. Point it at your projects directory, and it intelligently scans every repository, pulling the latest changes while keeping your work safe. It documents everything it does, so you always know exactly what changed. No more forgotten pulls. No more merge conflict surprises. No more wondering what happened. Just smooth, up-to-date repositories ready for actionโwith complete accountability.
Think of it as your morning coffee routine for your codebaseโone command, and everything's fresh, safe, and fully documented.
๐ Features
๐ก๏ธ Safety FirstSmart checks prevent data loss. Skips repos with uncommitted changes, detached HEADs, or missing upstreams. Your local work is always protected. ๐ Complete TransparencyYour Git guardian keeps detailed records. Every operation is automatically logged with commit details, file changes, and timing data. Use ๐จ Visual ClarityBeautiful, color-coded output with intuitive symbols. Green for success, red for errorsโknow exactly what's happening at a glance. ๐ Intelligent DiscoveryRecursively finds every Git repository in your directory tree, no matter how deeply nested. |
โก Lightning FastConcurrent batch processing updates multiple repositories simultaneously. Configurable batch sizes optimize performance for your workflow. Auto-excludes common junk directories. ๐ฏ Flexible ControlDry-run mode, depth limits, custom exclusions, verbosity levelsโyou're in complete control of every operation. โ Battle-Tested91.93% test coverage with 216 comprehensive tests. Production-ready and reliable with every release. |
๐ฆ Installation
Prerequisites
- Python 3.13+ installed on your system
- Git available in your PATH
- uv package manager (recommended) or pip
Method 1: Install from PyPI (Recommended) โญ
Install directly from PyPI as a global CLI toolโno virtual environment needed!
# Install as a global tool with uv
uv tool install gittyup
# That's it! Use from anywhere without activating venv
gittyup --version
Benefits: โ No venv activation โข โ Available system-wide โข โ Isolated environment โข โ Easy updates
Method 2: Install from Source
For development or contributing to the project:
# Clone and navigate to the project
git clone https://github.com/mikeckennedy/gittyup
cd gittyup
# Install in editable mode with uv
uv tool install --editable .
โก Quick Start
Basic Commands
# Update all repos in current directory
gittyup
# Update repos in a specific location
gittyup ~/dev/projects
# Preview what would happen (dry run)
gittyup --dry-run
# Get detailed output
gittyup --verbose
Common Workflows
The Monday Morning Refresh ๐
gittyup ~/projects
Start your week with every project up-to-date.
The Quick Check ๐
gittyup --dry-run --verbose
See what's outdated without touching anything.
The Deep Dive ๐
gittyup ~/dev --max-depth 3 --exclude archive --verbose
Scan thoroughly but skip archived projects.
The Safe Update with Work in Progress ๐ง
gittyup --ignore-all-changes
Update repos even when you have uncommitted changes, but only if no merge conflict would occur.
The Accountability Check ๐
gittyup --explain
Review your guardian's detailed report: see exactly what commits were pulled, which files changed, and why any repos were skipped. Perfect for Monday morning catch-up or debugging unexpected changes.
The Performance Mode โก
gittyup ~/projects --batch-size 5
Update multiple repositories concurrently for maximum speed. Adjust batch size based on your system resources and network connection. Careful you don't over do it and get rate limited at GitHub.
The Safe and Sequential ๐ฏ
gittyup --sync --verbose
Process repositories one at a time for careful monitoring or when debugging issues. Perfect for troubleshooting or conservative workflows.
๐ Documentation
Command Reference
gittyup [DIRECTORY] [OPTIONS]
| Argument/Option | Description | Default |
|---|---|---|
DIRECTORY |
Path to scan for repositories | Current directory |
-n, --dry-run |
Preview changes without updating | Disabled |
-b, --batch-size N |
Number of repos to update concurrently | 3 |
-s, --sync |
Force sequential updates (batch size = 1) | Concurrent |
-d, --max-depth N |
Maximum directory depth to scan | Unlimited |
-e, --exclude PATTERN |
Skip directories matching pattern | None |
-v, --verbose |
Show all repos, including up-to-date | Normal |
-q, --quiet |
Only show errors | Normal |
--ignore-untracked |
Allow updates even when untracked files present | Disabled |
--ignore-all-changes |
Allow updates with uncommitted changes (if safe) | Disabled |
--explain |
Show detailed history of last run | Disabled |
--version |
Display version information | - |
--help |
Show help message | - |
Output Guide
Gitty Up uses clear visual indicators to communicate status:
| โ Green | Repository is up-to-date or successfully updated |
| โ Cyan | Repository pulled new commits |
| โ Yellow | Repository skipped (safety check failed) |
| โ Red | Error occurred during update |
| โ White | Processing repository |
Example Output
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Gitty Up โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Scanning directory: /Users/dev/projects
โ Found 9 git repositories
Updating: project-alpha, project-beta, project-gamma
โ project-alpha - Already up-to-date
โ project-beta - Pulled 3 commits
โ project-gamma - Uncommitted changes
Updating: project-delta, project-epsilon, project-zeta
โ project-delta - Already up-to-date
โ project-epsilon - Network timeout
โ project-zeta - Pulled 1 commit
Updating: project-omega, project-sigma, project-theta
โ project-omega - Already up-to-date
โ project-sigma - Already up-to-date
โ project-theta - Already up-to-date
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Total repositories found: 9
โ Up to date: 5
โ Updated: 2
โ Skipped: 1
โ Errors: 1
Completed in 4.23 seconds
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Note: The example shows default batch processing (3 repos at a time). Use --sync for sequential updates with individual progress indicators.
Using --explain to Review History
Your Git guardian keeps detailed records of every operation. Need to know what changed? Just ask:
$ cd ~/projects
$ gittyup --explain
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Gitty Up - Operation History
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Operation Details
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐
Run Date: 2025-10-15 14:23:45
๐ Directory: /Users/dev/projects
โฑ๏ธ Duration: 2.34 seconds
๐ง Gittyup Version: 1.0.0
๐ Git Version: 2.39.0
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Total repositories: 5
โ
Updated: 1
๐ค Already up-to-date: 3
โญ๏ธ Skipped: 1
โ Errors: 0
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Repository Details
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
project-alpha
Path: /Users/dev/projects/project-alpha
Duration: 487ms
Branch: main
Changes pulled successfully
Commits: 3
Files changed: 5
Insertions: +127
Deletions: -43
๐ Commits:
a7f2c3d - Add new feature for user authentication
John Doe โข 2025-10-15T10:23:00
b8e1d4f - Fix bug in login validation
Jane Smith โข 2025-10-15T09:15:00
c9f2e5g - Update dependencies to latest versions
John Doe โข 2025-10-14T16:45:00
๐ Files:
~ src/auth.py
(+45/-12)
+ src/validators.py
(+32/-0)
~ tests/test_auth.py
(+28/-8)
๐ค project-beta
Path: /Users/dev/projects/project-beta
Duration: 123ms
Branch: develop
Already up-to-date
โญ๏ธ project-gamma
Path: /Users/dev/projects/project-gamma
Duration: 89ms
Branch: main
Skipped
Reason: Repository has uncommitted changes
Details: Pull would conflict with local modifications
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
What --explain shows:
- Complete operation metadata: When it ran, how long it took, tool versions
- Summary statistics: Overall results across all repositories
- Detailed repository information:
- Every commit that was pulled (who wrote it, when, what changed)
- Exactly which files changed with insertion/deletion counts
- Why any repos were skipped with specific reasons
- Full error details for debugging failed operations
- Branch information and precise timing data
Perfect for:
- Debugging issues or understanding unexpected changes
- Auditing what happened during automated runs
- Reviewing what you missed while away from your desk
- Team accountability and change tracking
Where logs are stored: Your guardian keeps records in OS-specific cache directories:
- macOS:
~/Library/Caches/gittyup/logs - Linux:
~/.cache/gittyup/logs - Windows:
C:\Users\<user>\AppData\Local\gittyup\logs
Each directory you scan gets its own log, automatically updated with each run. Storage is minimal (10-50 KB per log).
๐ก๏ธ Safety Features
Gitty Up protects your work with intelligent safety checks. It will skip updating a repository if it detects:
| Condition | Why it's Skipped | What to Do |
|---|---|---|
| ๐ Uncommitted changes | Prevents losing your work | Commit, stash, or discard changes first |
| ๐ No remote configured | Nothing to pull from | Add a remote: git remote add origin <url> |
| ๐ Detached HEAD state | Not on a branch | Checkout a branch: git checkout main |
| ๐ฏ No upstream branch | Branch not tracking remote | Set upstream: git push -u origin <branch> |
| ๐ Network errors | Can't reach remote | Check connection and remote URL |
| ๐ Authentication failed | Credentials missing | Configure Git credentials |
Your local work is always safe. Gitty Up never forces changes or overwrites uncommitted work.
๐ง Smart Filtering
Gitty Up automatically skips common directories that aren't your code:
Development Environments:
node_modules, venv, .venv, env, .env, vendor
Build Artifacts:
dist, build, target, .eggs, eggs
Caches:
__pycache__, .pytest_cache, .mypy_cache, .ruff_cache, htmlcov
Tools:
.tox, .nox, .idea, .vscode
Version Control:
.git, .svn, .hg
Want to exclude more? Use --exclude:
gittyup --exclude temp --exclude backup --exclude old-stuff
๐งน Always-Ignored Files
GittyUp knows the difference between real changes and desktop clutter. These common system and cache files are automatically ignored when checking for uncommitted changes:
.DS_Store- macOS metadata that clutters every directoryThumbs.db- Windows thumbnail caches you never asked for__pycache__- Python bytecode that regenerates anyway
Why this matters: Repositories with only these files are treated as clean and can be updated automatically. No more "uncommitted changes" blocks just because your OS left metadata files lying around.
๐ Learn more: See Always-Ignored Files Documentation for detailed examples and implementation details.
โ FAQ
Will Gitty Up overwrite my local changes?
Absolutely not. By default, Gitty Up includes comprehensive safety checks and will skip any repository with uncommitted changes. Your local work is always protected.
If you want more control, use:
--ignore-untracked: Allows updates when only untracked files are present (with safety checks)--ignore-all-changes: Allows updates even with modified files, but only if no merge conflict would occur
What's the difference between --ignore-untracked and --ignore-all-changes?
-
--ignore-untracked: Only works when you have untracked files (new files not in git). It checks if those files would conflict with incoming changes and only proceeds if safe. -
--ignore-all-changes: Works with any uncommitted changes (modified, staged, or untracked files). It performs a more comprehensive safety checkโfetches from origin and verifies that none of your uncommitted files would conflict with incoming changes. Only proceeds if the pull can be done safely.
When to use which:
- Use
--ignore-untrackedif you often have temporary/working files that aren't tracked - Use
--ignore-all-changesif you need to pull updates even when you have work in progress, but want assurance you won't get merge conflicts
Both flags are mutually exclusiveโuse the one that fits your workflow.
What happens if I have a merge conflict?
Gitty Up will detect the conflict, report it as an error, and move on to the next repository. You'll need to resolve conflicts manuallyโGitty Up never forces merges.
Can I use this with private repositories?
Yes! As long as your Git credentials are properly configured (SSH keys or credential helper), Gitty Up will work seamlessly with private repos.
How do I exclude specific directories?
Use the --exclude option (multiple times if needed):
gittyup --exclude archive --exclude temp --exclude old-projects
Does it work with Git submodules?
Gitty Up treats the parent repository as a single unit and doesn't traverse into submodules. This prevents confusion and duplicate updates.
Can I run this on a schedule?
Absolutely! Set up a cron job (Unix) or Task Scheduler (Windows):
# Example: Daily at 9 AM
0 9 * * * cd ~/projects && ~/.local/bin/gittyup --quiet
What if one repository fails?
Gitty Up continues processing all other repositories. Failures are clearly reported at the end, and you can address them individually.
Does it support SVN or Mercurial?
No, Gitty Up is specifically designed for Git repositories. It's Git all the way down. ๐ด
What information does --explain show?
Think of --explain as your guardian's detailed report card. It shows:
- Every commit that was pulled: Who wrote it, when they committed it, and the commit message
- Exactly which files changed: File paths with insertion/deletion counts
- Why any repos were skipped: Specific reasons like uncommitted changes or detached HEAD
- Full error details: Complete diagnostics for debugging any issues
- Operation metadata: When it ran, how long it took, versions used
Perfect when you need to understand what happened, debug an issue, or provide accountability for automated runs. No need to re-run the operationโyour guardian remembers everything.
Where are logs stored and how much space do they use?
Your guardian stores logs in OS-specific cache directories using efficient key-value storage:
- macOS:
~/Library/Caches/gittyup/logs - Linux:
~/.cache/gittyup/logs - Windows:
C:\Users\<user>\AppData\Local\gittyup\logs
Storage impact is minimal: each log is typically 10-50 KB. Even with 100 directories logged, total storage is only 1-5 MB. Each directory gets one log that's updated with each run, so space doesn't grow unbounded.
Do dry runs create logs?
No, dry runs (--dry-run) do not save logs. Your guardian only records actual operations that modify repositories. This keeps your history clean and focused on real changes, not "what if" scenarios.
How does concurrent batch processing work?
By default, Gitty Up updates repositories in batches of 3 simultaneously using async I/O operations. This dramatically improves performance when updating many repositories:
# Default: 3 repos at a time
gittyup ~/projects
# High performance: 5 repos at a time
gittyup ~/projects --batch-size 5
# Sequential (old behavior): 1 repo at a time
gittyup ~/projects --sync
Benefits:
- Faster updates: Network I/O happens concurrently while waiting for git operations
- Controlled resources: Batch size prevents overwhelming your system
- Clear output: Results are displayed in order after each batch completes
When to adjust batch size:
- Increase (
--batch-size 5-10): Fast internet, powerful system, many repos - Decrease (
--batch-size 1or--sync): Debugging issues, slow connection, conservative approach
The concurrent processing is safe and respects all the same safety checks as sequential mode.
๐จ Troubleshooting
Git Not Found
Error: Git is not installed or not found in PATH
Fix: Install Git and ensure it's in your system PATH:
# macOS
brew install git
# Linux (Debian/Ubuntu)
sudo apt-get install git
# Verify
git --version
Authentication Issues
Error: Authentication failed
Fix: Configure your Git credentials:
# SSH keys (recommended)
ssh-keygen -t ed25519 -C "your@email.com"
# Then add to GitHub/GitLab/etc.
# Or use credential helper
git config --global credential.helper store
Permission Denied
Error: Permission denied
Fix: Ensure you have read access to the directories being scanned. Check file permissions or run with appropriate privileges.
Network Timeouts
Error: Network error
Fix:
- Check your internet connection
- Verify remote URLs:
git remote -v - Check firewall settings
- Consider using
--max-depthto reduce scope
Log History Not Found
โ ๏ธ No history found for: /path/to/directory
Fix:
- Run
gittyupin this directory first (your guardian needs something to record!) - Remember: logs are only created for actual operations (non-dry-run)
- Verify you're in the same directory where you previously ran gittyup
- Check that the cache directory has write permissions
Cache Permission Errors
Error: Failed to save operation log
Fix:
- Ensure write access to cache directory:
- macOS:
~/Library/Caches/gittyup/logs - Linux:
~/.cache/gittyup/logs - Windows:
C:\Users\<user>\AppData\Local\gittyup\logs
- macOS:
- Check directory permissions:
ls -la ~/.cache/gittyup(Unix/macOS) - Create directory manually if needed:
mkdir -p ~/.cache/gittyup/logs
๐ง Development & Contributing
Interested in contributing to Gitty Up or running it locally for development?
๐ See the Development Guide for:
- Development setup instructions
- Testing and code quality guidelines
- Contributing guidelines and PR process
- Project architecture and design decisions
- Release process and versioning
We welcome contributions of all kindsโbug reports, feature requests, documentation improvements, and code contributions!
๐ Project Stats
| Metric | Value |
|---|---|
| Test Coverage | 91.93% |
| Total Tests | 216 passing |
| Code Quality | Zero linting issues |
| Python Version | 3.13+ |
| Dependencies | Minimal (click, colorama, platformdirs, diskcache) |
| Lines of Code | ~2,100 |
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
Built with โค๏ธ for developers who juggle too many projects and forget to git pull.
Powered by:
- Click - Command-line interface magic
- Colorama - Cross-platform colored output
- platformdirs - OS-specific directory paths
- diskcache - Fast persistent caching
- Ruff - Lightning-fast Python linting
๐ Version
Current Release: 1.0.0
See change-log.md for complete version history and release notes.
Made with ๐ด by developers, for developers
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gittyup-1.2.0.tar.gz.
File metadata
- Download URL: gittyup-1.2.0.tar.gz
- Upload date:
- Size: 100.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d669e733fdbb9694e3a410ffe878d2a69eab19c4fcb2c4a066c112e61bc10176
|
|
| MD5 |
4573c77281b7e1980230ddabfeadd3d1
|
|
| BLAKE2b-256 |
addf609b29a56d6e98c22c157d5a315b89a5013ad309549b8fa2028b8be21f79
|
File details
Details for the file gittyup-1.2.0-py3-none-any.whl.
File metadata
- Download URL: gittyup-1.2.0-py3-none-any.whl
- Upload date:
- Size: 32.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52449d4264cfae50483de10e48fba7057f2869edc224317b114350e076b121a4
|
|
| MD5 |
a28de9eded6a78197efb4ed3021ae934
|
|
| BLAKE2b-256 |
c3ff436936f4770d1400b2490fe8f4137452a0e46c41a77a64aa76a70b35ae09
|