README
¶
Hitch
A Git workflow manager for multi-environment development teams
Hitch simplifies managing feature branches across multiple deployment environments (dev, qa, production) by treating environment branches as hitched branches - ephemeral, reconstructible branches that are "hitched" to a specific feature list rather than having permanent independent histories.
Installation
Homebrew (macOS/Linux)
brew tap DoomedRamen/hitch
brew install hitch
curl (macOS/Linux)
curl -fsSL https://raw.githubusercontent.com/DoomedRamen/hitch/main/install.sh | bash
Go Install
go install github.com/DoomedRamen/hitch/cmd/hitch@latest
Manual Download
Download pre-built binaries from GitHub Releases:
# macOS ARM64 (M1/M2/M3)
curl -fsSL https://github.com/DoomedRamen/hitch/releases/latest/download/hitch_<version>_darwin_arm64.tar.gz | tar -xz
sudo mv hitch /usr/local/bin/
# macOS AMD64 (Intel)
curl -fsSL https://github.com/DoomedRamen/hitch/releases/latest/download/hitch_<version>_darwin_amd64.tar.gz | tar -xz
sudo mv hitch /usr/local/bin/
# Linux AMD64
curl -fsSL https://github.com/DoomedRamen/hitch/releases/latest/download/hitch_<version>_linux_amd64.tar.gz | tar -xz
sudo mv hitch /usr/local/bin/
# Linux ARM64
curl -fsSL https://github.com/DoomedRamen/hitch/releases/latest/download/hitch_<version>_linux_arm64.tar.gz | tar -xz
sudo mv hitch /usr/local/bin/
# Windows AMD64
# Download from releases page and add to PATH
Build from Source
git clone https://github.com/DoomedRamen/hitch.git
cd hitch
go build -o hitch ./cmd/hitch
sudo mv hitch /usr/local/bin/
For development (includes git hooks, testing tools):
git clone https://github.com/DoomedRamen/hitch.git
cd hitch
just setup # Installs lefthook, golangci-lint, and git hooks
Manual golangci-lint installation (if not using just setup):
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Overview
The Problem
Traditional multi-environment Git workflows lead to:
- Divergent histories between
dev,qa, andmainbranches - Merge conflicts when trying to sync environments
- Stale feature branches that fall out of sync with main
- Manual cherry-picking to untangle mixed changes
- Periodic branch deletion to reset environments and restore sanity
Example of the Mess:
Developer M: feature/xyz → dev → qa → main
Developer S: feature/abc → dev
Developer R: feature/lmp (branched from old main, now out of sync!)
After a few iterations, dev and qa have different histories than main, feature branches are stale, and the team resorts to deleting and recreating environment branches.
The Hitch Solution
Hitch treats dev and qa as hitched branches - branches that are "hitched" to a specific feature list:
qa = main + feature/xyz + feature/lmp + bug/473
dev = main + feature/xus + feature/lmp + bug/473
Key principles:
mainis the source of truth - all feature branches originate from main- Hitched branches are rebuilt -
devandqaare reconstructed on-demand from their feature lists - Metadata tracks state - a special
hitch-metadatabranch stores which features are in each environment - Automatic locking - prevents concurrent modifications during rebuilds
- Lifecycle management - identifies and cleans up stale branches
Features
- 🔄 Environment promotion: Move features between dev → qa → main
- 🔒 Automatic locking: Prevents race conditions during rebuilds
- 🧹 Stale branch cleanup: Identifies branches safe to delete
- 📊 Status overview: See which features are in each environment
- 🎯 Merge conflict detection: Alerts when features conflict
- 🪝 Git hook integration: Optional
hitch hookcommands for your existing hooks
Quick Start
# Initialize Hitch in your repository
cd your-repo
hitch init
# Create a feature branch
git checkout -b feature/new-login
# ... make changes ...
git push origin feature/new-login
# Promote to dev environment
hitch promote feature/new-login to dev
# Check status
hitch status
# Promote to qa
hitch promote feature/new-login to qa
# Release to main
hitch release feature/new-login
# Clean up stale branches
hitch cleanup --dry-run
hitch cleanup
Core Commands
hitch init- Initialize Hitch in a repositoryhitch status- Show current environment statehitch promote <branch> to <env>- Add a feature to an environmenthitch demote <branch> from <env>- Remove a feature from an environmenthitch release <branch>- Merge a feature to mainhitch rebuild <env>- Reconstruct an environment from scratchhitch cleanup- Delete stale brancheshitch lock <env>/hitch unlock <env>- Manual lock managementhitch hook pre-push- Git hook integration (optional)
How It Works
Hitch maintains a special hitch-metadata orphan branch containing:
{
"environments": {
"dev": {
"base": "main",
"features": ["feature/xus", "feature/lmp", "bug/473"],
"locked": false
},
"qa": {
"base": "main",
"features": ["feature/xyz", "feature/lmp", "bug/473"],
"locked": false
}
},
"branches": {
"feature/xyz": {
"created_at": "2025-10-01T09:00:00Z",
"promoted_to": ["dev", "qa"],
"merged_to_main_at": null
}
},
"config": {
"retention_days_after_merge": 7,
"stale_days_no_activity": 30
}
}
When you run hitch promote feature/xyz to qa, Hitch:
- Locks the
qaenvironment - Checks out a fresh
mainbranch - Merges all features in order:
main+feature/xyz+feature/lmp+bug/473 - Force-pushes the rebuilt
qabranch - Updates metadata
- Unlocks the environment
Documentation
- COMMANDS.md - Complete command reference
- HOOKS.md - Git hook integration guide
- ARCHITECTURE.md - Technical architecture details
- WORKFLOWS.md - Common workflow patterns
- TERMINOLOGY.md - Glossary of Hitch terminology
- SAFETY.md - Safety mechanisms and best practices
- TESTING.md - Testing guide for contributors
- CONTRIBUTING.md - Contribution guidelines
- CHANGELOG.md - Version history
- RELEASING.md - Release process for maintainers
Why "Hitch"?
A hitch is a type of knot used to temporarily attach a rope to an object. Like the tool, it's about temporary connections (features to environments) that are easy to tie and untie, rather than permanent tangles.
Contributing
Contributions welcome! Please read CONTRIBUTING.md first.
License
MIT License - see LICENSE
Author
Martin Page (@DoomedRamen) - m@rtin.page