--- name: git-merge-auditor description: > Audits whether a target branch contains all commits and changes from a source branch. Use this skill whenever you want to verify that a merge, rebase, or cherry-pick operation did not miss any updates — before or after merging. Do NOT use this skill to perform the merge itself; for that, use the git-merge-conflict-resolver skill. --- # Git Merge Auditor This **skill** is for developers, tech leads, and CI reviewers who need to confirm that a target branch is fully up-to-date with a source branch. It detects missing commits, unmerged file changes, and divergent history segments so that nothing is silently dropped during integration workflows. ## Inputs - **source_branch** (required): The branch whose changes must be present in the target branch (e.g. `main`, `develop`, `hotfix/1.2.3`). - **target_branch** (required): The branch being audited — the branch that is expected to contain all changes from the source (e.g. `release/2.0`, `feature/payment`). - **remote** (optional): The remote name to fetch from before auditing (e.g. `origin`). Defaults to `origin`. If not applicable (local-only repo), the fetch step is skipped. - **ignore_merge_commits** (optional): Whether to exclude merge commits from the missing-commit list. Defaults to `true`, because merge commits are not cherry-pickable and their absence is usually expected. ## Task priorities 1. **Priority 1 – Completeness of detection** Every commit and file change present in the source branch but absent from the target branch must be identified. False negatives (missed divergences) are worse than false positives. 2. **Priority 2 – Clarity of reporting** Results must be concise and actionable: exact commit hashes, messages, and affected files. The developer must be able to act on the report without further investigation. 3. **Priority 3 – Safety** This skill is read-only. It must never modify any branch, commit, or working tree. No `git merge`, `git rebase`, `git reset`, or `git push` commands are executed. ## Workflow ### Step 1 – Fetch latest remote state Ensure local refs are up to date before comparing: ```bash git fetch ``` If the repository is local-only (no remote configured) or **remote** was explicitly set to `none`, skip this step. Verify that both branches exist: ```bash git rev-parse --verify git rev-parse --verify ``` If either branch does not exist, stop and report the error to the user. ### Step 2 – Identify the merge base Find the common ancestor commit of both branches: ```bash git merge-base ``` Record this as ``. All comparisons are relative to this point. ### Step 3 – List commits in source branch not in target branch Enumerate commits that exist in **source_branch** but are not reachable from **target_branch**: ```bash git log .. --oneline --no-merges ``` If **ignore_merge_commits** is `false`, also include merge commits: ```bash git log .. --oneline ``` Record the full list as **missing commits**. If the list is empty, proceed to Step 4 to confirm at the file level before declaring the audit clean. ### Step 4 – Check for unmerged file differences Even when all commits appear present (e.g. after a squash merge), individual file content may differ. Compare the diff between the merge base and the tip of each branch: ```bash # Changes introduced by source_branch since the merge base git diff .. --name-status # Changes introduced by target_branch since the merge base git diff .. --name-status ``` Identify files that were modified in **source_branch** but whose changes are not reflected in **target_branch** by comparing the two diff outputs. Any file path that appears in the source diff but is absent from or has a different final state in the target diff is flagged as a **divergent file**. For each flagged file, produce a focused diff to show what is missing: ```bash git diff .. -- ``` ### Step 4.5 – Audit binary file changes Binary files (e.g. `*.jar`, `*.exe`, `*.dll`, `*.so`, `*.zip`, `*.war`) cannot be line-diffed. Confirm whether each binary change performed in **source_branch** — added, replaced, or removed — is mirrored in **target_branch**. #### 4.5.1 — Identify binary files changed in source branch Binary files are detected via `--numstat`, which outputs `-` for both counts when a file is not text-diffable: ```bash git diff .. --numstat | awk '$1 == "-" && $2 == "-" { print $3 }' ``` For each file returned, determine the operation performed in the source branch: ```bash git diff .. --name-status -- ``` Status letters: - `A` — Added (file did not exist at the merge base) - `M` — Modified / Replaced (file existed but its content changed) - `D` — Deleted (file was removed) #### 4.5.2 — Confirm the same operation in the target branch For each binary file identified, check what the target branch did with it: ```bash git diff .. --name-status -- ``` Then compare object hashes to verify content parity: ```bash git rev-parse : git rev-parse : ``` Classify each binary file as: - **✅ Synced** — same operation and identical content hash in both branches - **⚠️ Partial / Hash mismatch** — operation is present in target but content differs - **❌ Missing** — the source operation is not reflected in the target at all ### Step 5 – Detect cherry-pick equivalence (optional refinement) When commits are missing by hash (Step 3) but the target branch may have applied equivalent changes via cherry-pick or rebase, check whether the patch content is already present: ```bash git log --oneline --grep="" ``` For each commit in the missing list whose subject is found in the target history, mark it as **possibly included (different hash)**. These are lower-severity findings that still warrant manual review. ### Step 6 – Compile and present the audit report Produce a structured Markdown report using the format defined in **Output format**. Always include the report regardless of whether findings exist. ## Output format Always respond using this structure: ```markdown ## Git Merge Audit Report **Source branch:** `` **Target branch:** `` **Merge base:** `` **Audit date:** --- ### Summary | Check | Result | |---|---| | Missing commits | | | Divergent files | | | Binary file changes | | | Possibly included (different hash) | | | **Overall status** | ✅ Clean / ⚠️ Needs Review / ❌ Missing Changes | --- ### Missing Commits > Commits present in `` but not reachable from ``. | Hash | Message | Author | Date | |---|---|---|---| | `` | | | | _None_ — if no missing commits. --- ### Divergent Files > Files changed in `` whose changes are not fully present in ``. | File | Status in Source | Notes | |---|---|---| | `` | Added / Modified / Deleted | | For each divergent file, include the focused diff: \`\`\`diff .. -- > \`\`\` _None_ — if no divergent files. --- ### Binary File Changes > Binary files (*.jar, *.exe, etc.) changed in ``. Confirms whether each add/replace/remove was applied to ``. | File | Source Operation | Target Status | Notes | |---|---|---|---| | `` | Added / Replaced / Removed | ✅ Synced / ⚠️ Hash mismatch / ❌ Missing | | _None_ — if no binary files were changed in the source branch. --- ### Possibly Included (Different Hash) > Source commits not present by hash, but whose subject line was found in target history. Manual review recommended. | Source Hash | Source Message | Matching Target Commit | |---|---|---| | `` | | `` | _None_ — if no such commits. --- ### Recommendations - List concrete next actions (e.g. "Cherry-pick commit `abc1234` into ``", "Review divergence in `src/payments/processor.ts`"). - If the audit is clean, state: "No action required. `` contains all changes from ``." ``` ## Assumptions and known limits - **Assumes** both branches are accessible in the local repository (after the optional fetch step). Branches on forks not configured as remotes are out of scope. - **Assumes** a linear or standard merge-based history. Orphan branches or `--orphan` histories may produce misleading merge-base results. - **Binary detection** uses `--numstat` to identify non-text-diffable files. Files that Git treats as text despite a binary extension (e.g. text-encoded XML inside a `.jar` wrapper) will not be captured here; they are covered by Step 4's file diff instead. - **Does not** account for reverted commits — a commit that was applied and then reverted in the target branch will appear as missing even though its net effect is zero. Flag these for manual review. - **Does not** perform the merge or any write operation. It is strictly diagnostic. - **Cherry-pick equivalence** (Step 5) is a best-effort heuristic based on commit subject line matching. It may produce false positives when two unrelated commits share the same summary. ## Validation 1. Create a test scenario: branch `feature` off `main`, add two commits to `feature`, merge only one into `target`. Run the audit and confirm exactly one commit and its associated file appear in the report. 2. Run the audit on a branch that is fully merged; confirm the report shows "✅ Clean" with zero missing commits and zero divergent files. 3. Test squash-merge detection: squash-merge `feature` into `target`, then run the audit. Confirm missing commits are flagged but the divergent-files section shows "None" (since content was applied).