Git Chain
Overview
git chain manages chains of dependent Git branches where each branch builds upon the previous one (stacked branches). Instead of manually rebasing each branch in sequence, git-chain tracks relationships and updates all branches with a single command.
I---J---K feature-2
/
E---F---G feature-1
/
A---B---C---D master
When master is updated, git-chain rebases feature-1 onto master, then feature-2 onto feature-1 automatically.
When to Use This Skill
Use git-chain when:
- Stacked PRs: Working with multiple dependent pull requests that build on each other
- Feature chains: Developing a large feature split into incremental branches
- Review feedback: Updating base branches requires propagating changes to dependent branches
- Clean history: Maintaining linear commit history across dependent branches
- Avoiding tedious rebasing: Don't want to manually rebase 3+ branches in sequence
Prerequisites
CRITICAL: Before proceeding, verify that git-chain is installed:
git chain --version
If git-chain is not installed:
- DO NOT attempt to install it automatically
- STOP and inform the user that git-chain is required
- RECOMMEND manual installation:
# From source (requires Rust)
git clone git@github.com:dashed/git-chain.git
cd git-chain
make install
# Or with Cargo
cargo install --path .
If git-chain is not available, exit gracefully and do not proceed with the workflow below.
Key Concepts
- Chain: A named sequence of branches with dependency order
- Root Branch: Foundation branch (typically
mainormaster) - NOT part of the chain - Branch Order: The sequence in which branches depend on each other
Important: A branch can belong to at most one chain.
Basic Workflow
Step 1: Set Up a Chain
Create a chain with your stacked branches:
git chain setup my-feature master feature-1 feature-2 feature-3
This creates chain "my-feature" with master as root and branches in order: feature-1 -> feature-2 -> feature-3.
Step 2: View the Chain
git chain # Show current chain (if on a chain branch)
git chain list # List all chains in the repository
Step 3: Update the Chain
When the root branch or any branch in the chain has new commits:
Option A: Rebase (rewrites history, clean linear commits)
git chain rebase
Option B: Merge (preserves history, creates merge commits)
git chain merge
Common Patterns
Pattern 1: Stacked PR Workflow
Scenario: Working on a feature split into 3 PRs: auth, profiles, settings
# Create branches
git checkout -b auth main
# ... make auth changes, commit ...
git checkout -b profiles auth
# ... make profile changes, commit ...
git checkout -b settings profiles
# ... make settings changes, commit ...
# Set up the chain
git chain setup user-feature main auth profiles settings
# After main receives new commits, update all branches
git chain rebase
git chain push --force # Update all PRs
Pattern 2: Review Feedback on Base Branch
Scenario: Reviewer requested changes on auth branch (first PR)
git checkout auth
# ... make changes, commit ...
# Update dependent branches automatically
git chain rebase
Pattern 3: Adding a New Branch to Existing Chain
Scenario: Need to add notifications branch between profiles and settings
git checkout -b notifications profiles
# ... make changes, commit ...
# Add to chain with specific position
git chain init user-feature main --after=profiles
Core Commands Reference
| Command | Description |
|---------|-------------|
| git chain setup <name> <root> <b1> <b2>... | Create chain with branches |
| git chain init <name> <root> | Add current branch to chain |
| git chain | Display current chain |
| git chain list | List all chains |
| git chain rebase | Rebase all branches (rewrites history) |
| git chain merge | Merge all branches (preserves history) |
| git chain push | Push all branches to remotes |
| git chain push --force | Force push all branches |
| git chain first/last/next/prev | Navigate between chain branches |
| git chain backup | Create backup branches |
| git chain prune | Remove branches merged to root |
| git chain remove | Remove current branch from chain |
| git chain remove --chain | Delete entire chain |
Rebase vs Merge
Use Rebase When:
- Branches are private/not shared
- You prefer clean, linear history
- PRs haven't been reviewed yet
Use Merge When:
- Branches have open PRs with review comments
- You need to preserve commit history
- Collaborating with others on the same branches
Advanced Usage
For comprehensive coverage of all flags and advanced patterns, see:
- references/rebase-options.md - All rebase flags and conflict handling
- references/merge-options.md - All merge flags and strategies
- references/chain-management.md - Moving, reorganizing, and removing chains
Key flags:
--step, -s: Process one branch at a time (rebase)--ignore-root, -i: Skip updating first branch from root--verbose, -v: Detailed output (merge)--chain=<name>: Operate on specific chain--no-ff: Force merge commits even for fast-forwards--squashed-merge=<mode>: Handle squash-merged branches (reset/skip/merge)
Recovery
If something goes wrong during rebase:
# Abort in-progress rebase
git rebase --abort
# Restore from backup (if created with git chain backup)
git checkout branch-name
git reset --hard branch-name-backup
# Or use reflog
git reflog
git reset --hard branch-name@{1}
Handling Conflicts
When conflicts occur during git chain rebase:
- Git-chain pauses at the conflicted commit
- Resolve conflicts manually in the marked files
git add <resolved-files>git rebase --continuegit chain rebase(continues with remaining branches)
Troubleshooting
"Branch not part of any chain"
- Run
git chain listto see available chains - Use
git chain initto add the current branch to a chain
"Cannot find fork-point"
- Reflog may have been cleaned up
- Use
--no-fork-pointflag to fall back to merge-base
Rebase conflicts on every update
- Consider using
git chain mergeinstead to preserve history - Or use
--stepflag to handle each branch individually
Squash-merged branch causing issues
- git-chain detects squash merges; use
--squashed-merge=skipto skip them - Or use
--squashed-merge=reset(default) to reset branch to parent