Skip to main content
AI/MLWaterplanAI

git-find-fork

Finds the true merge-base/fork-point of a git branch, detecting history rewrites from rebases and squashes. Handles unknown parent branches. Triggers on keywords: find fork, merge-base, branch fork point, where did branch start, git fork, branch origin

Stars
31
Source
WaterplanAI/agentic-config
Updated
2026-05-25
Slug
WaterplanAI--agentic-config--git-find-fork
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/WaterplanAI/agentic-config/HEAD/plugins/ac-git/skills/ac-git/git-find-fork/SKILL.md -o .claude/skills/git-find-fork.md

Drops the SKILL.md into .claude/skills/git-find-fork.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

Git Find Fork

Determines the true fork point of a branch, accounting for rebases, squashes, and unknown parent branches.

Workflow

Step 1: Identify Current State

BRANCH=$(git rev-parse --abbrev-ref HEAD)
HEAD_SHA=$(git rev-parse --short HEAD)

Step 2: Find Candidate Parent Branches

When parent is unknown, find closest by commit count:

git branch -a --format='%(refname:short)' | while read b; do
  [[ "$b" == "$BRANCH" ]] && continue
  base=$(git merge-base "$b" HEAD) || continue
  count=$(git rev-list --count "$base..HEAD")
  echo "$count $base $b"
done | sort -n | head -5

Lowest count = closest parent.

Step 3: Get Merge-Base

PARENT="main"  # or detected from Step 2
MERGE_BASE=$(git merge-base "$PARENT" HEAD)

Step 4: Detect History Rewriting

REFLOG_ORIGIN=$(git reflog show "$BRANCH" --format='%H %gs' | grep 'branch: Created' | awk '{print $1}')

if [[ "$REFLOG_ORIGIN" != "$MERGE_BASE" ]]; then
  echo "HISTORY REWRITTEN"
  # Check if reflog commit still ancestor
  git merge-base --is-ancestor "$REFLOG_ORIGIN" HEAD && echo "Partial rebase" || echo "Full rebase/squash"
fi

Step 5: Detect Squash

COMMIT_COUNT=$(git rev-list --count "$MERGE_BASE..HEAD")
[[ "$COMMIT_COUNT" -eq 1 ]] && echo "Branch appears SQUASHED"

Step 6: Find Orphaned References (Optional)

# Tags pointing to orphaned commits
for tag in $(git tag); do
  tag_sha=$(git rev-parse "$tag")
  git merge-base --is-ancestor "$tag_sha" HEAD || echo "Orphaned: $tag -> $tag_sha"
done

Output Format

Field Value
Branch {branch_name}
HEAD {sha}
Parent Branch {parent}
Merge-Base {sha} - "{commit message}"
Commits Since Fork {count}
History Rewritten Yes/No
Squashed Yes/No

Key Principle

git merge-base gives the fork point for CURRENT history state. Original fork point after rebase/squash must be recovered from reflog, tags, or dangling objects (none guaranteed to exist).