MCPcopy Index your code
hub / github.com/dashed/git-chain

github.com/dashed/git-chain @v0.0.13

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.0.13 ↗ · + Follow
181 symbols 1,407 edges 25 files 3 documented · 2%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

git-chain

A powerful tool for managing and rebasing chains of dependent Git branches (stacked branches).

What Problem Does Git Chain Solve?

When working on complex features, developers often create a series of branches where each branch builds upon the previous one. For example:

                            I---J---K  feature-2
                           /
                  E---F---G  feature-1
                 /
    A---B---C---D  master

When new changes are added to the master branch, updating all branches in the chain becomes tedious and error-prone:

  1. You need to rebase feature-1 onto the updated master
  2. Then rebase feature-2 onto the updated feature-1
  3. Repeat for any additional branches in the chain

Git Chain automates this entire process. It keeps track of relationships between branches and handles the rebasing for you.

Key Concepts

  • Chain: A sequence of branches that build upon each other, with a designated root branch.
  • Root Branch: The foundation branch (typically main or master) that the chain ultimately merges into.
  • Branch Order: The sequence in which branches depend on each other in the chain.

Note: - A branch can belong to at most one chain. - The root branch is not part of the chain, but serves as its foundation.

How Git Chain Works

Git Chain stores branch relationships in your repository's Git config, tracking: - Which chain a branch belongs to - The order of branches within a chain - Each branch's root branch

Git Chain offers two strategies for updating branches: 1. Rebase: Rewrites branch history by replaying commits on top of the updated parent branch 2. Merge: Preserves branch history by creating merge commits that incorporate changes from the parent branch

When operating on chains, Git Chain: 1. Determines the correct fork-point for each branch using git merge-base --fork-point 2. Updates each branch in sequence, preserving the dependency order 3. Handles edge cases like squash merges and chain reorganization

Rebase Strategy: How git-chain Updates Your Branches

Basic Concept

When you run git chain rebase, git-chain intelligently updates each branch in your chain to incorporate changes from its parent branch. Think of it like moving your work to sit on top of the latest version of your parent branch. This rewrites commit history, giving a cleaner, linear history but generating new commit hashes.

How It Works

  1. Order Matters: Branches are updated in the order they appear in the chain, starting from the one closest to the root branch. This ensures each branch builds upon an already-updated parent.

  2. Finding the Right Starting Point: For each branch, git-chain determines where your branch originally split from its parent. This point (called a "fork-point") is crucial for keeping only your changes when rebasing.

What is a fork-point? A fork-point is the specific commit where you originally created your branch from its parent. It's more intelligent than just finding a common ancestor - Git uses its reflog (a history of where branch tips have been) to determine the exact point where your branch's history forked from the parent branch. This is especially useful when the parent branch has been rebased or reorganized since you created your branch. When rebasing, Git needs to know this point to correctly identify which commits belong to your branch (and should be moved) versus which commits were already in the parent branch (and should be left alone).

  1. Smart Detection: git-chain uses Git's sophisticated "fork-point" detection, which is smarter than simple ancestry checking. It:
  2. First checks if your branch can be simply fast-forwarded
  3. If not, uses Git's history records (reflog) to find the original branching point
  4. Falls back to a regular merge-base if fork-point detection fails

Note on the Fallback Mechanism: Sometimes Git can't determine the fork-point, particularly in these situations: - When older reflog entries have been cleaned up by git gc - If you created your branch from an older commit (not the tip) of the parent branch - After certain operations that affect repository history

When Git's fork-point detection fails, git-chain automatically falls back to using git merge-base, which finds the most recent common ancestor between two branches. While this ensures rebasing can proceed, it might be less precise than using the true fork-point.

  1. Handling Squash Merges: If you've squash-merged a branch into its parent (combining all commits into one), git-chain detects this and prevents duplicate changes.

  2. The Actual Rebasing: For each branch, git-chain runs a command similar to: git rebase --keep-empty --onto <parent_branch> <fork_point> <branch> This moves your changes to sit on top of the updated parent branch.

To read more about fork-point, see: https://git-scm.com/docs/git-merge-base#_discussion_on_fork_point_mode

Command Options and Flags

Git Chain's rebase command offers customization through its flags:

  • --step, -s: Rebase one branch at a time, requiring manual confirmation between steps git chain rebase --step Perfect for carefully managing complex rebases where conflicts might occur.

  • --ignore-root, -i: Skip rebasing the first branch onto the root branch git chain rebase --ignore-root Useful when you want to update relationships between chain branches without incorporating root branch changes.

Examples (git chain rebase)

Here are some common scenarios and how to handle them with git-chain rebase:

1. Standard chain update

Scenario: You want to update all branches in the chain to incorporate changes from their parent branches.

Solution:

git chain rebase

This rebases all branches in the chain sequentially, starting from the one closest to the root branch.

2. Updating just the relationship between chain branches

Scenario: You want to update only relationships between branches in a chain, not incorporating new root branch changes.

Solution:

git chain rebase --ignore-root

This skips rebasing the first branch onto the root branch.

3. Careful rebasing with potential conflicts

Scenario: You anticipate conflicts and want to handle each branch separately.

Solution:

git chain rebase --step

This rebases one branch at a time, waiting for your confirmation between steps.

Handling Rebase Conflicts

When rebasing branches in a chain, conflicts can sometimes occur. Git Chain handles conflicts as follows:

  1. Conflict Detection: When a rebase conflict occurs, git-chain:
  2. Pauses the rebasing process at the conflicted commit
  3. Leaves the repository in a conflicted state for you to resolve
  4. Provides information about which branch is being rebased and where the conflict occurred
  5. May create automatic backup branches if conflicts are detected

  6. Resolution Process:

  7. The conflicted files will be marked with conflict markers (<<<<<<<, =======, >>>>>>>)
  8. Resolve conflicts manually by editing the conflicted files
  9. Add the resolved files with git add <file>
  10. Continue the rebase with git rebase --continue

  11. Continuing After Resolution:

  12. After resolving the conflicts and continuing the rebase for the current branch, you can resume updating the chain: git chain rebase
  13. Git Chain will pick up where it left off, continuing with the remaining branches

  14. Aborting a Problematic Rebase:

  15. If you decide not to resolve the conflicts, you can abort the current rebase: git rebase --abort
  16. Then, if you created backup branches, you can restore from them: git checkout branch-name git reset --hard branch-name-backup

Example Conflict Workflow:

$ git chain rebase
Rebasing branch feature/auth onto master...
Auto-merging src/auth.js
CONFLICT (content): Merge conflict in src/auth.js
error: could not apply 1a2b3c4... Add authentication feature

# Resolve the conflict
$ vim src/auth.js
$ git add src/auth.js
$ git rebase --continue
Successfully rebased branch feature/auth

Rebasing branch feature/profiles onto feature/auth...
# Continues with remaining branches

Recovery Options

If a rebase goes wrong, Git Chain provides several recovery options:

  1. Backup Branches: If you used --backup, you can restore using: git checkout branch-name git reset --hard branch-name-backup

  2. Reflog: Even without backups, you can recover using Git's reflog: git checkout branch-name git reflog git reset --hard branch-name@{1} # Reset to previous state

  3. Abort In-Progress Rebase: If a rebase is still in progress: git rebase --abort

Merge Strategy: Preserving Branch History

Basic Concept

When you run git chain merge, git-chain cascades merges through your branch chain by merging each parent branch into its child branch. Unlike rebasing, merging preserves the original commit history by creating merge commits that link branches together.

How It Works

  1. Order Matters: Branches are updated in the order they appear in the chain, starting from the one closest to the root branch. Each branch incorporates changes from its parent through a merge.

  2. Finding the Right Starting Point: Git Chain uses the same intelligent fork-point detection as in rebasing to identify the best common ancestor for each merge.

  3. Smart Detection: Git Chain checks for special cases:

  4. If branches can be fast-forwarded (no merge needed)
  5. If a branch has been squash-merged (to avoid duplicate changes)
  6. If there are merge conflicts that need manual resolution

  7. The Actual Merging: For each branch, git-chain runs a command similar to: git checkout <branch> git merge <parent_branch> This incorporates all changes from the parent branch while preserving the branch's original commit history.

Command Options and Flags

Git Chain's merge command offers extensive customization through various flags and options:

Basic Options

  • --verbose, -v: Provides detailed output during the merging process git chain merge --verbose Shows exactly what's happening with each branch, including Git's merge output.

  • --ignore-root, -i: Skips merging the root branch into the first branch git chain merge --ignore-root Useful when you want to update relationships between branches in the chain without incorporating root branch changes.

  • --stay: Don't return to the original branch after merging git chain merge --stay By default, git-chain returns you to your starting branch. Use this flag to remain on the last merged branch.

  • --chain=<name>: Operate on a specific chain other than the current one git chain merge --chain=feature-x Allows you to merge a chain even when you're not on a branch that belongs to it.

Merge Behavior Controls

  • --simple, -s: Use simple merge mode without advanced detection git chain merge --simple Disables fork-point detection and squashed merge handling for a faster, simpler merge process.

  • --fork-point, -f: Use Git's fork-point detection (default behavior) git chain merge --fork-point Explicitly enables fork-point detection for finding better merge bases.

  • --no-fork-point: Disable fork-point detection, use regular merge-base git chain merge --no-fork-point Can be faster but potentially less accurate. Useful for repositories with limited reflog history.

  • --squashed-merge=<mode>: How to handle branches that appear squash-merged git chain merge --squashed-merge=reset # Default: reset to match parent branch git chain merge --squashed-merge=skip # Skip branches that appear squashed git chain merge --squashed-merge=merge # Force merge despite the detection Controls behavior when Git Chain detects that a branch appears to have been squash-merged into its parent.

Git Merge Options

  • Fast-forward behavior: git chain merge --ff # Allow fast-forward if possible (default) git chain merge --no-ff # Always create a merge commit git chain merge --ff-only # Only allow fast-forward merges Controls how Git handles cases where a branch can be fast-forwarded.

  • --squash: Create a single commit instead of a merge commit git chain merge --squash Combines all changes from the source branch into a single commit.

  • --strategy=<strategy>: Use a specific Git merge strategy git chain merge --strategy=recursive git chain merge --strategy=ours Specifies which Git merge strategy to use (e.g., recursive, resolve, octopus).

  • --strategy-option=<option>: Pass strategy-specific options git chain merge --strategy=recursive --strategy-option=ignore-space-change git chain merge --strategy=recursive --strategy-option=patience Customizes the behavior of the selected merge strategy.

Reporting Options

  • Adjusting report detail: git chain merge --report-level=minimal # Basic success/failure messages git chain merge --report-level=standard # Summary with counts (default) git chain merge --report-level=detailed # Comprehensive per-branch details git chain merge --no-report # Suppress merge summary report git chain merge --detailed-report # Same as --report-level=detailed Controls how much information is displayed after the merge completes.

Examples (git chain merge)

Here are some common scenarios and how to handle them with git-chain merge:

1. Updating PRs without breaking review comments

Scenario: You have multiple PRs open,

Extension points exported contracts — how you extend this code

ErrorExt (Interface)
For API consistency, we create our own Error variants [1 implementers]
src/error.rs

Core symbols most depended-on inside this repo

checkout_branch
called by 274
tests/common/mod.rs
create_new_file
called by 248
tests/common/mod.rs
run_git_command
called by 185
tests/common/mod.rs
commit_all
called by 174
tests/common/mod.rs
create_branch
called by 117
tests/common/mod.rs
run_test_bin_expect_ok
called by 96
tests/common/mod.rs
get_current_branch_name
called by 73
tests/common/mod.rs
run_test_bin
called by 57
tests/common/mod.rs

Shape

Function 99
Method 70
Class 6
Enum 5
Interface 1

Languages

Rust100%

Modules by API surface

tests/common/mod.rs26 symbols
tests/merge.rs24 symbols
src/git_chain/core.rs20 symbols
src/branch.rs18 symbols
src/chain.rs17 symbols
src/git_chain/merge.rs14 symbols
src/types.rs9 symbols
tests/pr.rs8 symbols
src/git_chain/operations.rs7 symbols
tests/rebase.rs6 symbols
tests/merge_base_failures.rs5 symbols
tests/fork_point_failure.rs4 symbols

For agents

$ claude mcp add git-chain \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact