Skip to content

Commit 6fd5512

Browse files
Add workflow to validate branch ancestry and prevent old git history
This workflow prevents branches containing pre-initialization git history from being merged into dev/main, protecting against re-introduction of sensitive data that was removed during the December 22, 2025 repository re-initialization. ## How It Works The workflow runs on every push and pull request, performing these steps: 1. Checks out full git history (fetch-depth: 0) 2. Finds ALL root commits of the branch using git rev-list --max-parents=0 3. Validates each root commit against a list of valid initialization commits 4. FAILS if ANY root commit doesn't match the valid list 5. PASSES if all root commits are valid Valid root commit (Dec 22, 2025 initialization): 97e73c5 ## What Happens When It Runs **Valid Branch (created from current dev/main):** - Workflow passes with ✅ - Branch can proceed to merge (if other checks pass) **Invalid Branch (contains old git history):** - Workflow FAILS with clear error message - Shows which root commits are invalid - Provides step-by-step remediation instructions - Branch CANNOT be merged if branch protection is configured ## Security Features - Multi-root detection: Handles merged branches with multiple histories - Empty line handling: Robust parsing of git output - Clear error messages: Developers know exactly how to fix the issue - Minimal permissions: Only requires contents:read and pull-requests:read - No tokens needed: Uses built-in GITHUB_TOKEN automatically - Timeout protection: 10-minute limit prevents runaway workflows ## Branch Protection Configuration Required After merging, these branch protection rules MUST be configured to actually block invalid branches from merging: ### For 'dev' branch: 1. Go to: Settings → Branches → Edit 'dev' protection rule 2. Under 'Require status checks to pass before merging' 3. Click 'Add status check' 4. Search for and add: 'Validate Clean History' 5. Save changes ### For 'main' branch: 1. Go to: Settings → Branches → Edit 'main' protection rule 2. Under 'Require status checks to pass before merging' 3. Click 'Add status check' 4. Search for and add: 'Validate Clean History' 5. Save changes **IMPORTANT:** Without this configuration, the workflow will alert but will NOT block merges. The check must run successfully at least once before it appears in the status check dropdown. ## Future Maintenance If the repository is re-initialized again: 1. Edit .github/workflows/validate-branch-history.yml 2. Add the new root commit to VALID_ROOTS array (line 32) 3. Commit and push the change ## Testing This workflow was designed to block branch 'origin/nps-am-25120' which contains 1,545 commits from before Dec 22, 2025, including sensitive customer data (e.g., woodmenlife.org domain references). ## No Configuration Needed - No secrets or tokens to configure - No repository variables to set - Uses built-in GITHUB_TOKEN automatically - Works immediately upon merge Only action required: Configure branch protection rules (see above).
1 parent 6d2217a commit 6fd5512

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: Validate Branch History
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
pull_request:
8+
types: [opened, synchronize, reopened]
9+
10+
env:
11+
SECURITY_CONTACT: 'jake-mahon-netwrix'
12+
13+
jobs:
14+
validate-history:
15+
name: Validate Clean History
16+
runs-on: ubuntu-latest
17+
timeout-minutes: 10
18+
permissions:
19+
contents: read
20+
pull-requests: read
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
with:
25+
fetch-depth: 0
26+
27+
- name: Check branch ancestry
28+
id: check_ancestry
29+
run: |
30+
# Valid root commits
31+
VALID_ROOTS=(
32+
"97e73c5cc4a29296024f23499ef5e60bc7db755b"
33+
)
34+
35+
echo "🔍 Validating branch ancestry..."
36+
37+
# Get ALL root commits (handles merged branches with multiple roots)
38+
BRANCH_ROOTS=$(git rev-list --max-parents=0 HEAD)
39+
40+
echo "Found root commit(s):"
41+
echo "$BRANCH_ROOTS"
42+
43+
# Check each root commit
44+
INVALID_ROOTS=()
45+
while IFS= read -r branch_root; do
46+
# Skip empty lines
47+
[[ -z "$branch_root" ]] && continue
48+
49+
VALID=false
50+
for valid_root in "${VALID_ROOTS[@]}"; do
51+
if [ "$branch_root" = "$valid_root" ]; then
52+
VALID=true
53+
break
54+
fi
55+
done
56+
57+
if [ "$VALID" = false ]; then
58+
INVALID_ROOTS+=("$branch_root")
59+
fi
60+
done <<< "$BRANCH_ROOTS"
61+
62+
# If any invalid roots found, fail
63+
if [ ${#INVALID_ROOTS[@]} -gt 0 ]; then
64+
echo "❌ ERROR: This branch contains invalid root commits"
65+
echo ""
66+
echo "Expected all root commits to be one of:"
67+
for root in "${VALID_ROOTS[@]}"; do
68+
echo " - $root"
69+
done
70+
echo ""
71+
echo "Found invalid root commit(s):"
72+
for invalid in "${INVALID_ROOTS[@]}"; do
73+
echo " - $invalid"
74+
done
75+
echo ""
76+
echo "This repository was re-initialized to remove sensitive data from git history."
77+
echo "Branches must be created from the current dev/main branches."
78+
echo ""
79+
echo "To fix this:"
80+
echo "1. Save your changes as a patch: git diff origin/dev > my-changes.patch"
81+
echo "2. Create a fresh branch from current dev: git checkout -b my-branch origin/dev"
82+
echo "3. Apply your patch: git apply my-changes.patch"
83+
echo "4. Commit and push the clean branch"
84+
echo "5. Delete the invalid branch (replace BRANCH_NAME with your branch name):"
85+
echo " git push origin --delete BRANCH_NAME"
86+
echo ""
87+
echo "Contact @${{ env.SECURITY_CONTACT }} if you need assistance."
88+
exit 1
89+
fi
90+
91+
echo "✅ Branch ancestry validation passed"

0 commit comments

Comments
 (0)