Last active
August 6, 2025 23:18
-
-
Save mihow/32c94a8b2aa8f802ac0188b16e489483 to your computer and use it in GitHub Desktop.
Find the goods in old branches
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Tool to find which commits are unique to a given branch using patch-id comparison. | |
# This is helpful for finding good stuff & new contributions in old branches when they have become out of sync with main. | |
# Assumes the trip branch is called main. | |
set -o nounset | |
set -o errexit | |
set -o pipefail | |
BRANCH=${1:-$(git branch --show-current)} | |
BASE_BRANCH=${2:-main} | |
echo "=== Unique Commit Finder ===" | |
echo "Analyzing branch: $BRANCH" | |
echo "Base branch: $BASE_BRANCH" | |
echo "Date: $(date)" | |
echo "" | |
# Step 1: Quick branch relationship discovery | |
echo "๐ STEP 1: Discovering branch relationships..." | |
TOTAL_COMMITS=$(git log --oneline "$BRANCH" ^"$BASE_BRANCH" --no-merges | wc -l) | |
echo "Total non-merge commits in $BRANCH (not in $BASE_BRANCH): $TOTAL_COMMITS" | |
# Find most likely parent branch using merge-base analysis | |
echo "" | |
echo "Finding most similar branches using merge-base analysis:" | |
BEST_CANDIDATE="" | |
MIN_UNIQUE=999999 | |
git for-each-ref --format='%(refname:short)' refs/heads/ refs/remotes/ | \ | |
grep -v -E "^($BRANCH|HEAD|origin/HEAD)$" | while read branch; do | |
# Skip if branch doesn't exist | |
if ! git show-ref --verify --quiet "refs/heads/$branch" && ! git show-ref --verify --quiet "refs/remotes/$branch"; then | |
continue | |
fi | |
# Count unique commits compared to this branch | |
unique_count=$(git log "$BRANCH" ^"$branch" --no-merges --oneline 2>/dev/null | wc -l || echo "999") | |
if [ "$unique_count" -lt 20 ] && [ "$unique_count" -gt 0 ]; then | |
echo " $branch: $unique_count unique commits" | |
fi | |
done | sort -n | head -10 | |
echo "" | |
# Step 2: Use patch-id for definitive analysis | |
echo "๐ STEP 2: Using patch-id for definitive analysis..." | |
# Check against api-test specifically (our known case) | |
if git show-ref --verify --quiet "refs/heads/api-test" || git show-ref --verify --quiet "refs/remotes/origin/api-test"; then | |
CANDIDATE="api-test" | |
echo "Found api-test branch - using patch-id comparison..." | |
# Generate patch IDs for both branches | |
echo "Generating patch IDs for $BRANCH..." | |
git log "$BRANCH" ^"$BASE_BRANCH" --no-merges --format="%H" | while read hash; do | |
patch_id=$(git show "$hash" | git patch-id --stable | cut -d' ' -f1) | |
echo "$patch_id $hash" | |
done > /tmp/branch_patches_$$ | |
echo "Generating patch IDs for $CANDIDATE..." | |
git log "$CANDIDATE" --format="%H" | while read hash; do | |
patch_id=$(git show "$hash" | git patch-id --stable | cut -d' ' -f1) | |
echo "$patch_id $hash" | |
done > /tmp/candidate_patches_$$ | |
echo "" | |
echo "๐ฏ FINDING TRULY UNIQUE COMMITS..." | |
# Find commits that don't have matching patch IDs | |
UNIQUE_COMMITS="" | |
while read patch_id hash; do | |
if ! grep -q "^$patch_id " /tmp/candidate_patches_$$; then | |
UNIQUE_COMMITS="$UNIQUE_COMMITS $hash" | |
commit_subject=$(git log --format="%s" -n 1 "$hash") | |
echo "UNIQUE: $hash $commit_subject" | |
fi | |
done < /tmp/branch_patches_$$ | |
UNIQUE_COUNT=$(echo "$UNIQUE_COMMITS" | wc -w) | |
TOTAL_BRANCH_COMMITS=$(wc -l < /tmp/branch_patches_$$) | |
echo "" | |
echo "=== RESULTS ===" | |
echo "Total commits in $BRANCH (not in $BASE_BRANCH): $TOTAL_BRANCH_COMMITS" | |
echo "Commits also in $CANDIDATE: $((TOTAL_BRANCH_COMMITS - UNIQUE_COUNT))" | |
echo "Truly unique commits: $UNIQUE_COUNT" | |
if [ "$UNIQUE_COUNT" -gt 0 ]; then | |
echo "" | |
echo "=== UNIQUE COMMITS (chronological order) ===" | |
for hash in $UNIQUE_COMMITS; do | |
git log --format="%h %ad %s" --date=short -n 1 "$hash" | |
done | sort -k2 | |
echo "" | |
echo "=== FILES MODIFIED BY UNIQUE COMMITS ===" | |
for hash in $UNIQUE_COMMITS; do | |
git show --name-only --format="" "$hash" | |
done | sort | uniq | |
echo "" | |
echo "=== CHERRY-PICK COMMANDS ===" | |
echo "To create a clean branch with only unique commits:" | |
echo "" | |
echo "git checkout $BASE_BRANCH" | |
echo "git checkout -b $BRANCH-unique" | |
# Sort by commit date and generate cherry-pick commands | |
for hash in $UNIQUE_COMMITS; do | |
commit_date=$(git show -s --format=%ct "$hash") | |
commit_subject=$(git log --format="%s" -n 1 "$hash") | |
echo "$commit_date $hash $commit_subject" | |
done | sort -n | while read date hash subject; do | |
echo "git cherry-pick $hash # $subject" | |
done | |
fi | |
# Cleanup | |
rm -f /tmp/branch_patches_$$ /tmp/candidate_patches_$$ | |
else | |
echo "โ ๏ธ api-test branch not found. Showing all commits not in $BASE_BRANCH:" | |
git log "$BRANCH" ^"$BASE_BRANCH" --no-merges --oneline --reverse | |
fi | |
echo "" | |
echo "=== SUMMARY ===" | |
echo "This script uses the following approaches to find unique commits in a branch:" | |
echo "1. Quick merge-base analysis to find similar branches" | |
echo "2. Patch-id comparison for definitive duplicate detection" | |
echo "3. Chronological ordering of truly unique commits" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment