githash home
What it does
githash gives you per-file git blob hashes for any GitHub commit, and lets you pivot any file into VirusTotal by its raw SHA-256. Two hashes per file, two different jobs:
- git blob SHA — identifies a file's bytes across all of GitHub. Great for cross-repo dedup ("does this exact file appear anywhere else?").
- SHA-256 of raw bytes — what VirusTotal and most security tools index. Computed on first click; cached forever.
Using the search bar
One input does two jobs depending on what you paste:
- GitHub repo
owner/repo,owner/repo@ref, or anyhttps://github.com/…URL → ingests the commit and renders its file tree.- Git blob hash
- 6–40 hex chars → finds every ingested file with these exact bytes.
If a hex prefix uniquely resolves to one blob, the URL auto-extends to the full 40-char SHA so the link you share is unambiguous.
Swap github.com → githash.org
You don't have to copy a repo into the search bar at all. Take any GitHub repo URL in your address bar and
change the host from github.com to githash.org — leave the rest of the path
untouched. githash reads the path, ingests that exact commit, and renders the file tree:
github.com/octocat/Hello-World
↓ (just change the host)
githash.org/octocat/Hello-World
The same path forms GitHub uses all carry over, so whatever page you're looking at maps cleanly:
- repo root
githash.org/owner/repo→ the default branch (HEAD)- branch / tag
githash.org/owner/repo/tree/main→ that ref, resolved to a commit- exact commit
githash.org/owner/repo/commit/<sha>→ that immutable snapshot- release tag
githash.org/owner/repo/releases/tag/v1.0.0→ the tagged ref- pull request
githash.org/owner/repo/pull/42→ ingests every commit in the PR and ties the PR to them, with the author and any Actions runs- a single file
githash.org/owner/repo/blob/main/path/to/file→ ingests the repo and opens that file's details panel
githash always ingests the whole repo at the given ref — a /blob/… URL just
auto-opens the one file you pointed at. Tip: in the browser address bar you can edit only the
github.com part and hit enter.
Once the page loads, githash rewrites the URL to a canonical hash route pinned to the resolved commit SHA (see how refs work), so the link you copy afterward won't drift.
Browsing a repo
The file tree mirrors the repo at the ingested commit. Folders collapse and expand. Click any file row to open its details panel:
- path, size, blob sha — all from GitHub's trees API
- sha-256 — computed on demand the first time you expand the row
- View on GitHub — deep link to the file at this commit
- Search Blob — switches to the blob view, showing every other place the same file bytes appear
Release artifacts
A GitHub release can ship uploaded files alongside the source — installers, binaries, packaged builds. These aren't part of the code tree, so they never show up in the file list. githash pulls them in separately and lists them in a releases panel below the tree.
Each artifact shows its SHA-256, size, download count, and a View on VirusTotal pivot — so you can vet a shipped binary the same way you'd vet any file in the repo.
Artifact names aren't clickable on purpose — githash never points a click straight at a release binary. Use the hash or the VirusTotal link to inspect it instead.
Cross-repo dedup
Two files with identical bytes have identical git blob SHAs — that's git's content-addressing guarantee. githash keys on the blob SHA, so the same jQuery file dropped into 100 repos shows up as one blob entry with 100 occurrences. Click "Search Blob" on any file to see those occurrences (owner/repo, commit, path) and deep-link into each.
How refs work (and why it matters)
GitHub refs — branches and tags — are mutable pointers, not snapshots. The same
v1.0.0 tag might point to a different commit today than it did last month. main
moves every time someone pushes. HEAD tracks whatever the default branch happens to point at.
Commit SHAs, on the other hand, are immutable. A commit SHA is a cryptographic hash of the snapshot, so it can never quietly change meaning.
When you ingest owner/repo@v1.0.0, githash resolves the ref to a commit SHA at that exact moment
and stores both. Every subsequent ingest re-resolves the ref and records what we see, preserving the ref's
history of commits.
A ref that points somewhere different than last time is a meaningful signal. The file contents at
v1.0.0 today are not what they were last week — the tag overlaps but the bytes diverge.
Common causes:
- A maintainer force-pushed a fix to an existing tag (sometimes a quiet security patch)
- A tag was re-cut from a different branch
- The repo was rewritten or rebased
Canonical links
After every ingest, githash rewrites the URL to use the resolved commit SHA, not the ref. Share that:
#/repo/octocat/Hello-World@7fd1a60b01f91b314f59955a4e4d4e80d8edf11d
Anyone opening it sees the exact same bytes you did. A link with @main drifts the next time
someone pushes.
External and ghost commits
Every fork of a repo shares the same underlying storage on GitHub. A side effect of that: a commit pushed to someone's fork can be opened under the original repo's URL — and the page looks completely legitimate, repo name and all. It's a favorite trick for making sketchy code appear to belong to a project you trust.
githash checks whether a commit is actually part of the repo you're viewing. When it isn't, githash splits the verdict in two depending on whether the source is still findable in the fork network:
changeset-release/main),
and in-flight feature work that hasn't merged.
For external commits with a live source, githash also snapshots the fork at ingest time so the file tree is preserved here even if the fork is later deleted. (The separate orphaned pill on individual commits is unrelated — that one means a commit was dropped from its ref by a non-fast-forward push.)
oidc-61fff775), that commit adds and runs a malicious “release” workflow — executing with the
repository's own publish/OIDC credentials — and then the branch is deleted. The run survives in the repo's
Actions history, but the commit it ran is a ghost: in the repo's history nowhere, on no live ref anywhere. Because
that run is keyed to a SHA nobody navigates to, a per-commit lookup never sees it — so githash sweeps the
repo's recent runs, classifies each run's head the same way it classifies commits, and surfaces any imposter run in
the Actions panel of every commit view, linked to the commit and the deleted branch it ran on.
The two hashes, explained
Every file has two fingerprints. They look alike but answer different questions — and mixing them up is the most common trip-up, so here's the plain version.
Git blob SHA — “is this the exact same file?”
The 40-character hash git uses to identify a file's contents. Two files with the same git blob SHA are byte-for-byte identical — that's how githash spots the same file showing up across different repos. It's the hash shown throughout the file tree, and the one the search bar matches when you paste a hash.
SHA-256 — “what do security tools call this file?”
The 64-character hash that VirusTotal and most security tools use to look up a file. GitHub doesn't provide it, so githash calculates it for you. The first time anyone needs a given file's SHA-256 there's a brief pause while it's computed; after that it's saved and instant for everyone.
Limits and gotchas
- 10 MB blob cap. Files larger than this aren't fetched or hashed; the trees-API size lets us skip them without trying.
- 100k entries / 7 MB tree cap. GitHub truncates the trees response for very large repos. We surface a banner and show the partial file list.
- Submodules are skipped. They're gitlinks to other repos, not files in this one. Ingest the target repo separately.
- Symlinks are stored but flagged. VirusTotal pivot is disabled — a symlink blob's "content" is the target path string, not a real file.
- One ref at a time. Each ingest captures the commit a ref resolves to right now. To compare two points in time, ingest both commit SHAs explicitly.
Privacy + data
githash only knows about public GitHub repos that someone has explicitly ingested through this tool. Nothing is crawled. File contents are fetched only when needed for SHA-256 computation and aren't stored — only the hashes, sizes, and paths. We do log each search and ingest (including IP address) for rate-limiting and abuse prevention.
For the full details, see the Privacy Policy and Terms of Service.