Shared utilities for git workflow automation scripts.
This package provides common git operations that can work either on the current working directory or on a specified repository path. Originally extracted from wolf/dotfiles git utilities.
- Repository resolution: Find and validate git repositories from relative or absolute paths
- Branch discovery: Intelligently find local and remote branches with wildcard support
- Submodule management: Automatically initialize and update submodules recursively
- Direnv integration: Create .envrc symlinks and run
direnv allowif available - User templates: Automatically apply user-specific files to new worktrees and clones
- Path utilities: Handle tilde expansion and absolute path conversion
- Git operations: Run git commands with flexible options and error handling
# Install from GitHub
pip install git+https://github.com/wolf/git-workflow-utils.git
# Install from local directory (for development)
pip install -e /path/to/git-workflow-utilsFor use with uv scripts, add to your inline metadata:
# /// script
# dependencies = [
# "git-workflow-utils @ git+https://github.com/wolf/git-workflow-utils.git",
# ]
# ///from git_workflow_utils import (
run_git,
current_branch,
find_branches,
initialize_repo,
resolve_repo,
apply_user_template,
)
# Get current branch
branch = current_branch()
print(f"On branch: {branch}")
# Find branches matching a pattern
branches = find_branches("feature-*")
print(f"Feature branches: {branches}")
# Initialize a repository (submodules + direnv + user templates)
initialize_repo("/path/to/repo")
# Apply user templates to an existing repository
apply_user_template("/path/to/repo")
# Run git commands
result = run_git("status", "--short", capture=True)
print(result.stdout)The user template system allows you to automatically populate new worktrees and clones with user-specific files that are typically gitignored (like .envrc.local, .ipython/, .helix/, etc.).
- Create a template directory with your user-specific files:
mkdir -p ~/.config/git/user-template
echo 'export MY_API_KEY=secret123' > ~/.config/git/user-template/.envrc.local- Configure the template mode (required):
# Use symlinks (changes propagate across all worktrees)
git config --global worktree.userTemplate.mode link
# Or use copies (each worktree gets independent copies)
git config --global worktree.userTemplate.mode copy- Templates are applied automatically when you use
initialize_repo():
from git_workflow_utils import initialize_repo
# This will now apply user templates
initialize_repo("/path/to/new-worktree")Templates are loaded from the first location that exists:
- Explicit path (function parameter):
apply_user_template(repo, template_path=Path("~/my-template")) - Git config:
git config worktree.userTemplate.path ~/.config/git/templates/python - Default location:
~/.config/git/user-template/
You must configure the mode if a template directory exists:
# Link mode: creates symlinks to template files
# Pro: Changes to template propagate to all repos
# Con: Can't customize per-repo
git config --global worktree.userTemplate.mode link
# Copy mode: copies template files
# Pro: Each repo can customize independently
# Con: Changes to template don't propagate
git config --global worktree.userTemplate.mode copyYou can override the mode for specific files:
# Use link mode globally, but copy .ipython/ directory
git config --global worktree.userTemplate.mode link
git config --global --add worktree.userTemplate.copy .ipython
# Use copy mode globally, but link .envrc.local
git config --global worktree.userTemplate.mode copy
git config --global --add worktree.userTemplate.link .envrc.local# Template directory structure
~/.config/git/user-template/
└── .ipython/
└── profile_default/
└── startup/
└── 00-imports.py # Auto-import commonly used modules# .envrc.local for secrets and personal config
~/.config/git/user-template/.envrc.localContent:
# Personal API keys and tokens (gitignored)
export ANTHROPIC_API_KEY=sk-xxxxx
export GITHUB_TOKEN=ghp_xxxxx# Helix editor project-specific settings
~/.config/git/user-template/.helix/
└── languages.tomlFor different project types (Python, Rust, etc.):
# Create project-specific templates
~/.config/git/templates/
├── python/
│ ├── .envrc.local
│ └── .ipython/
└── rust/
└── .envrc.local
# Use per-project config
cd ~/my-python-project
git config worktree.userTemplate.path ~/.config/git/templates/python
git config worktree.userTemplate.mode link# 1. Create template directory
mkdir -p ~/.config/git/user-template/.ipython/profile_default/startup
# 2. Add personal environment variables
cat > ~/.config/git/user-template/.envrc.local <<'EOF'
export ANTHROPIC_API_KEY=sk-xxxxx
export DATABASE_PASSWORD=hunter2
EOF
# 3. Add IPython auto-imports
cat > ~/.config/git/user-template/.ipython/profile_default/startup/00-imports.py <<'EOF'
# Auto-imported when IPython starts in project directory
from pathlib import Path
import sys
EOF
# 4. Configure template mode
git config --global worktree.userTemplate.mode link
# 5. Now all new clones/worktrees will get these files automatically!resolve_path(path)- Resolve a path to an absolute Path objectis_absolute_repo_path(repo)- Check if path is an absolute path to a git repositoryresolve_repo(repo)- Resolve and validate a git repository path
run_git(*args, repo=None, check=True, capture=False)- Run a git commandgit_config(key, repo=None, default=None)- Get a git config valuegit_config_list(key, repo=None)- Get all values for a multi-value git config keycurrent_branch(repo=None)- Get the currently checked out branch namehas_uncommitted_changes(repo=None)- Check for uncommitted changesfetch_all(repo=None, quiet=False)- Fetch all remotes, prune deleted refs, update tagsfind_branches(pattern, repo=None, remote_name="origin")- Find branches matching a patternsubmodule_update(repo=None)- Update submodules recursivelyinitialize_repo(repo=None)- Initialize a repository (submodules + direnv + user templates)
symlink_envrc_if_needed(repo=None, template=".envrc.sample")- Create .envrc symlink from template fileapply_user_template(repo=None, template_path=None)- Apply user template directory to repository
is_direnv_available()- Check if direnv is installeddirenv_allow(envrc)- Allow direnv to load a .envrc file
# Clone the repository
git clone github:wolf/git-workflow-utils.git
cd git-workflow-utils
# Activate direnv (sets up uv environment and IPython)
direnv allow
# Or manually install dependencies
uv sync --all-extrasThe project has comprehensive test coverage (96%):
# Run tests
uv run pytest
# Run tests with coverage
uv run pytest --cov=src/git_workflow_utils --cov-report=term-missing
# Run specific test file
uv run pytest tests/test_git.py -vTest suite:
- 85 tests total
- Unit tests for all modules
- Integration tests with real git repositories
- 96% code coverage (100% on new templates module)
git-workflow-utils/
├── src/git_workflow_utils/
│ ├── __init__.py # Public API exports
│ ├── paths.py # Path and repository resolution
│ ├── git.py # Core git operations
│ ├── templates.py # User template system
│ ├── direnv.py # Direnv integration
│ └── py.typed # Type hint marker
├── tests/
│ ├── conftest.py # Shared test fixtures
│ ├── test_paths.py # Path module tests
│ ├── test_git.py # Git module tests
│ ├── test_templates.py # Template module tests
│ └── test_direnv.py # Direnv module tests
├── .ipython/ # Local IPython configuration
├── .envrc # Direnv configuration (uv + IPython)
├── pyproject.toml # Package configuration
└── README.md # This file
- Python 3.13+
- Git 2.0+
- direnv (optional, for .envrc support)
Part of Wolf's personal utilities. Use at your own discretion.
This is a personal utilities repository, but suggestions and improvements are welcome via issues or pull requests.