$npx -y skills add gadievron/raptor --skill github-commit-recoveryRecover deleted commits from GitHub using REST API, web interface, and git fetch. Use when you have commit SHAs and need to retrieve actual commit content, diffs, or patches. Includes techniques for accessing "deleted" commits that remain on GitHub servers.
| 1 | # GitHub Commit Recovery |
| 2 | |
| 3 | **Purpose**: Access commit content, diffs, and metadata directly from GitHub when you have commit SHAs. Includes methods for retrieving "deleted" commits that remain accessible on GitHub servers. |
| 4 | |
| 5 | ## When to Use This Skill |
| 6 | |
| 7 | - You have commit SHAs and need actual code content |
| 8 | - Investigating commits that were force-pushed over ("deleted") |
| 9 | - Need commit diffs, patches, or full file contents |
| 10 | - Verifying commit authorship or metadata |
| 11 | - Retrieving content from dangling commits |
| 12 | |
| 13 | **SHA Sources**: GitHub Archive, git reflog, CI/CD logs, PR comments, issue references, external archives, security reports. |
| 14 | |
| 15 | ## Core Principles |
| 16 | |
| 17 | **Deleted Commits Are Never Really Deleted**: |
| 18 | - When developers force push to "delete" commits, GitHub keeps them indefinitely |
| 19 | - Any commit SHA remains accessible if you know the hash |
| 20 | - GitHub displays a warning ("This commit does not belong to any branch") but serves the content |
| 21 | - Even 4 hex digits can access commits (with collision risk) |
| 22 | |
| 23 | **Rate Limits Matter**: |
| 24 | - Authenticated API: 5,000 requests/hour |
| 25 | - Unauthenticated API: 60 requests/hour |
| 26 | - Web interface: Undocumented limits, WAF may block heavy usage |
| 27 | - Git operations: No explicit limit, but excessive cloning may trigger throttling |
| 28 | |
| 29 | ## Quick Start |
| 30 | |
| 31 | **Access a "deleted" commit via web browser**: |
| 32 | ``` |
| 33 | https://github.com/org/repo/commit/FULL_COMMIT_SHA |
| 34 | ``` |
| 35 | |
| 36 | **Get commit as patch file**: |
| 37 | ```bash |
| 38 | curl -L https://github.com/org/repo/commit/FULL_COMMIT_SHA.patch |
| 39 | ``` |
| 40 | |
| 41 | **Query via REST API**: |
| 42 | ```bash |
| 43 | curl -H "Authorization: Bearer $GITHUB_TOKEN" \ |
| 44 | https://api.github.com/repos/org/repo/commits/FULL_COMMIT_SHA |
| 45 | ``` |
| 46 | |
| 47 | ## Accessing Deleted Commits |
| 48 | |
| 49 | ### Method 1: Direct Web Access |
| 50 | |
| 51 | GitHub serves "deleted" commits at predictable URLs. These commits show a warning banner but content remains fully accessible. |
| 52 | |
| 53 | **Commit View**: |
| 54 | ``` |
| 55 | https://github.com/<ORG>/<REPO>/commit/<SHA> |
| 56 | ``` |
| 57 | |
| 58 | **Patch Format** (raw diff with headers): |
| 59 | ``` |
| 60 | https://github.com/<ORG>/<REPO>/commit/<SHA>.patch |
| 61 | ``` |
| 62 | |
| 63 | **Diff Format** (unified diff only): |
| 64 | ``` |
| 65 | https://github.com/<ORG>/<REPO>/commit/<SHA>.diff |
| 66 | ``` |
| 67 | |
| 68 | **Example**: |
| 69 | ```bash |
| 70 | # View commit that was force-pushed over |
| 71 | curl -L https://github.com/grapefruit623/gcloud-python/commit/e9c3d31212847723aec86ef96aba0a77f9387493 |
| 72 | |
| 73 | # Download as patch |
| 74 | curl -L -o leaked_commit.patch \ |
| 75 | https://github.com/grapefruit623/gcloud-python/commit/e9c3d31212847723aec86ef96aba0a77f9387493.patch |
| 76 | ``` |
| 77 | |
| 78 | **Short SHA Access**: GitHub allows accessing commits with just 4+ hex characters (if unique): |
| 79 | ``` |
| 80 | https://github.com/org/repo/commit/e9c3 |
| 81 | ``` |
| 82 | |
| 83 | ### Method 2: REST API |
| 84 | |
| 85 | The GitHub REST API provides structured commit data including file changes, author info, and commit message. |
| 86 | |
| 87 | **Endpoint**: |
| 88 | ``` |
| 89 | GET https://api.github.com/repos/{owner}/{repo}/commits/{ref} |
| 90 | ``` |
| 91 | |
| 92 | **Example Request**: |
| 93 | ```bash |
| 94 | curl -H "Accept: application/vnd.github+json" \ |
| 95 | -H "Authorization: Bearer $GITHUB_TOKEN" \ |
| 96 | https://api.github.com/repos/org/repo/commits/abc123def456 |
| 97 | ``` |
| 98 | |
| 99 | **Response Structure**: |
| 100 | ```json |
| 101 | { |
| 102 | "sha": "abc123def456...", |
| 103 | "commit": { |
| 104 | "author": { |
| 105 | "name": "Developer Name", |
| 106 | "email": "dev@example.com", |
| 107 | "date": "2025-06-15T14:23:11Z" |
| 108 | }, |
| 109 | "message": "Commit message here" |
| 110 | }, |
| 111 | "files": [ |
| 112 | { |
| 113 | "filename": "src/config.js", |
| 114 | "status": "added", |
| 115 | "patch": "@@ -0,0 +1,3 @@\n+// config" |
| 116 | } |
| 117 | ] |
| 118 | } |
| 119 | ``` |
| 120 | |
| 121 | **Rate Limit Headers**: |
| 122 | ``` |
| 123 | x-ratelimit-limit: 5000 |
| 124 | x-ratelimit-remaining: 4999 |
| 125 | x-ratelimit-reset: 1623456789 |
| 126 | ``` |
| 127 | |
| 128 | ### Method 3: Git Fetch |
| 129 | |
| 130 | For bulk analysis or when you need full repository context, fetch specific commits via Git. |
| 131 | |
| 132 | **Minimal Clone + Fetch Specific Commit**: |
| 133 | ```bash |
| 134 | # Clone without file contents (just history/trees/commits) |
| 135 | git clone --filter=blob:none --no-checkout https://github.com/org/repo.git |
| 136 | cd repo |
| 137 | |
| 138 | # Fetch the specific "deleted" commit |
| 139 | git fetch origin <COMMIT_SHA> |
| 140 | |
| 141 | # View the commit |
| 142 | git show FETCH_HEAD |
| 143 | |
| 144 | # View specific file from that commit |
| 145 | git show FETCH_HEAD:path/to/file.txt |
| 146 | ``` |
| 147 | |
| 148 | **Why This Works**: |
| 149 | - `--filter=blob:none`: Omits file contents initially (fast clone) |
| 150 | - `--no-checkout`: Doesn't populate working directory |
| 151 | - `git fetch origin <SHA>`: Retrieves specific commit even if "deleted" |
| 152 | - Blobs are fetched on-demand when you access them |
| 153 | |
| 154 | ## Investigation Patterns |
| 155 | |
| 156 | ### Batch Download Patches |
| 157 | |
| 158 | **Scenario**: You have a list of commit SHAs to investigate and need their content. |
| 159 | |
| 160 | ```python |
| 161 | import requests |
| 162 | import time |
| 163 | |
| 164 | def download_commit_patch(repo, sha, token=None): |
| 165 | url = f"https://github.com/{repo}/commit/{sha}.patch" |
| 166 | headers = {"Authorization": f"Bearer {token}"} if token |