Refolk
ReferenceProcess, data, and compliance

The Git Commit Metadata Reference: Which Fields You Can Trust

For any field in a commit record you will be able to say what it proves, how it can be forged or degraded, and whether it is safe as evidence.

16 min readLast reviewed August 17, 2026Read as Markdown

Key takeaways

  • Every author and committer field - name, email, and both timestamps - is set from client-side inputs and can be typed to any value, so a bare name with no signature is a claim, not evidence.
  • The Verified badge binds only the committer's identity, not the author's, so a signed commit can still carry a spoofed author email.
  • Only the ID-prefixed noreply address (ID+USERNAME@users.noreply.github.com, used by accounts created after 2017-07-18) survives a username change; the legacy username-only form silently loses attribution.
  • Push-blocking checks only the most recent commit, so a person's real email routinely persists deeper in a branch's history and is still harvestable.
  • Co-authored-by is an unsigned free-text message trailer, so a named co-author is unauthenticated and easy to fabricate.
  • With 49,362 US Software Engineers listing Git in Refolk's index and 7,010 in the UK, per-profile signature checking does not scale and field-trust rules must be set programmatically.

You are ingesting git and GitHub commit data into a sourcing or intelligence pipeline, and you need to know which fields carry weight as evidence of who did what. This reference treats every commit field as a data-integrity question - trustworthy, spoofable, or privacy-degraded - for the person answerable for how the pipeline's records were gathered. Jump to the field you are looking at, read what it proves and how it lies, and leave with a verdict.

This is not a skill assessment. Other guides in the library grade a contributor's ability from their repository history. This one asks a narrower, harder question: for a given commit record, can you defend the claim that this person did this thing? Most of the fields you would reach for cannot support that claim on their own, and the ones that can are narrower than they look.

What is inside a commit, and who sets each part

A git commit object is plain keyed text, and almost every field in it is typed by the client, not assigned by a trusted host. The object stores the tree, the parent or parents, an author line, a committer line, and the message. The first word on a line is the key, the rest is the value, an empty line separates the header from the message, and the very first key is tree, whose value defines the file structure and content.

The author and committer lines each carry a name, an email, and a timestamp. All of them come from client-side inputs. When git creates the commit object, it reads these environment variables first and falls back to configuration only if they are absent. The precedence is explicit: the --author flag wins, then the GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL environment variables, then user.name and user.email config - repo-local first, then global, then system.

Two things in a commit are not freely typed. The SHA is a hash computed over the content, including the author and committer fields, so any change to those fields produces a different commit with a different SHA. And on the host, the verification record - the signature check that renders as Verified - is computed by GitHub, not supplied by the committer. Everything else is free text.

That is the whole shape of the problem. The fields you most want - who wrote this, when - are exactly the fields the writer controls. The field the host controls, the verification record, answers a different question than the one you are asking.

The commit field trust map

This is the lookup table. Find your field, read the verdict, then read the sections below for the mechanism. The setter column tells you who can change the value; the verdict tells you whether it can stand as evidence.

FieldWho sets itEvidence verdict
Author name + emailCommitter, client-sideSpoofable
Committer name + emailClient-side, or host on web editsSpoofable, except host-signed web commits
Author / committer timestampClient-sideSpoofable
Co-authored-by trailerFree text in the messageSpoofable
ID-prefixed noreply emailDerived from account user IDReliable link to account, degraded PII
Verified badge / signatureCryptographic, host-validatedTrustworthy for the signer

Three verdicts do the work here. Spoofable means the field can be set to any value with no barrier and cannot be authenticated after the fact. Reliable link to account, degraded PII means the value genuinely resolves to a GitHub account but was published precisely because the person did not want their real address exposed - so it is good for attribution and poor as a contact address you can defend. Trustworthy for the signer means a signature was cryptographically validated, but read the next section before you assume that covers the author.

Trust layers in a commit record

  1. Author name and email
    Free text, set by --author or config, no barrier to forge
  2. Committer and timestamps
    Free text, or host-set only on web edits
  3. Co-authored-by trailer
    Free text inside the message body
  4. ID-prefixed noreply email
    Derived from the account user ID, resolves reliably
  5. Verified signature and SHA
    Cryptographic, host-validated, binds the signer only
Each layer down is harder to forge, and the layers you care about most sit at the top where forgery is trivial.

Author versus committer: two people, two fields

The author is the person who originally wrote the work; the committer is the person who last applied it. These are distinct fields and they diverge more often than pipelines assume. When you amend a commit, you update the committer aspects while the author aspects stay unchanged. A cherry-pick preserves the author and the author date but rewrites the committer and the commit date. Rebase, patch application, and web edits all do the same kind of thing.

This divergence is your friend when you are auditing. Run git log --format=fuller and both dates become visible. Any row where AuthorDate and CommitDate differ tells you the commit was replayed rather than written in place - a signal of a rebase, cherry-pick, web edit, or applied patch. That does not mean anything is wrong. It means the committer and author are not the same act, and you should not collapse them into one attribution.

The trap is the web edit. When the committer is GitHub itself, the commit was made in the browser, not on the named person's machine. That is a genuinely different provenance story: the code passed through GitHub's web interface, which is why GitHub can sign it automatically. Do not read a GitHub committer as evidence of local authorship.

What the Verified badge actually validates

The Verified badge means a signature was validated, and it binds the committer, not the author. By default GitHub marks a commit Verified when it is signed with a GPG, SSH, or S/MIME key that GitHub successfully verified against a key on the account. If a signature cannot be verified, GitHub marks it Unverified. In every other case - which is most public commits - GitHub displays no verification status at all.

That last point reshapes how you read the field. Absence of a badge is the default, not a red flag. Most public commits carry no verification status because most commits are unsigned. You cannot infer anything negative from a missing badge; you can only infer something positive from a present one, and only about the signer.

The scope is the load-bearing detail. GitLab states it precisely: the author writes the commit and the committer applies it, and commit signing verifies only the committer's identity. So a Verified commit whose author email differs from the signing committer proves the committer signed, and says nothing about the author. When you click a Verified status, GPG-signed commits show the key ID used and SSH-signed commits show the public key signature - capture that key detail, because it is the thing that actually resolves to an identity.

Two edge cases will bite an automated pipeline. First, verification is persistent: if a signing key is later revoked or expired, previously verified commits keep their Verified status, and GitHub will not re-verify or retroactively adjust them. A stale badge can outlive the trust it once represented. Second, a valid signature can carry a mismatched author email through a mailmap mapping; GitLab surfaces this as an orange rather than green verified label - a documented case where "verified" and "author trusted" legitimately diverge.

The badge and the author field measure different people, so a lone badge is never authorship proof.

A GitHub noreply email reliably resolves to an account, and its format tells you whether that resolution survives a rename. There are two populations, split by a single date. If the account was created after July 18, 2017, the noreply address is ID+USERNAME@users.noreply.github.com, where the numeric prefix is the account's stable user ID. If the account was created before that date and enabled email privacy before it, the address is USERNAME@users.noreply.github.com with no ID.

That numeric prefix is what makes attribution durable. Commits made with an ID-prefixed noreply stay associated with the account after a username change, because the ID never changes. Commits made with the username-only form silently lose their association when the username changes. So attribution reliability depends on account age, not on the current email string. GitHub App commits use a parallel format, USERID+APP-NAME[bot]@users.noreply.github.com, tied to the app's user ID, and it survives renames the same way.

FormatWhenSurvives username change
ID+USERNAME@users.noreplyAccounts after 2017-07-18Yes
USERNAME@users.noreplyPrivacy enabled before 2017-07-18No
USERID+APP-NAME[bot]@users.noreplyGitHub App commitsYes, tied to app user ID

For a sourcing pipeline the operational reading is: an ID-prefixed noreply is a good attribution key and a poor contact address. The person published it because they did not want their real address in public history. Resolve it to the account, use the account, and do not treat the noreply string as an outreach address you can defend.

That is the kind of field-level query Refolk is built for: you describe the signal in plain English and get the people it resolves to, without hand-parsing every commit header yourself. When your rule is "the ID-prefixed noreply resolves to an account but the username-only form does not," you want that logic applied across the whole index, not one repo at a time.

Where the real email leaks anyway

The two privacy settings that keep a real email out of history each have a gap, and the push-block gap is the one you will find in the data. GitHub offers "Keep my email addresses private" for web-based git operations and "Block command line pushes that expose my email" for command-line commits. Both have been available since April 2017.

The push block is narrow by design. Each time you push, GitHub checks the most recent commit, and if its author email is a private address on your account, it blocks the push. Because it inspects only the most recent commit, earlier commits on the same branch can still carry the real email. Those addresses persist unless someone rewrites history. In practice, real emails routinely sit deeper in a branch than the tip, and they are still harvestable from the raw log.

49,362
US Software Engineers listing Git as a skill in Refolk's index
With 7,010 more in the UK and 4,573 in Germany, per-profile signature checking does not scale and field-trust rules must be set programmatically.

The lesson for a pipeline is that you cannot assume any privacy setting scrubbed a branch. If you are relying on a person having hidden their address, check the full history, not the tip. And if you are the one accountable for lawful use, remember that a real email surfacing deeper in history was published by the tooling's gap, not by the person's choice.

The ingestion procedure

Ingest everything first, then verify the sample that carries weight. Security write-ups often verify signatures first, as a gate. Operations pipelines usually do the reverse, because most public commits are unsigned and gating on signatures would discard almost all of your data. Ingest, tag, then verify where trust matters.

Ingesting commit data with a defensible trust verdict

  1. Fetch the raw object, not the rendered UI
    Pull each commit via git cat-file or git log with an explicit format so author, committer, both timestamps, and message trailers are separate values. Done when every field is its own column, not a display string.
  2. Separate author from committer
    Run git log --format=fuller so AuthorDate and CommitDate are both visible, and flag rows where they differ. Divergence marks a rebase, cherry-pick, web edit, or patch.
  3. Parse email type per row
    Classify each email as real, ID-prefixed noreply, legacy username-only noreply, or bot noreply. Done when every email is tagged and ID-prefixed rows carry the stable user ID.
  4. Pull the host verification record
    Via the API, record verified, unverified, or partially-verified state and the signing key ID and type. Store verification state alongside each commit.
  5. Extract and normalize Co-authored-by trailers
    Capture each co-author as its own row with its own email tag and its own verification status. The trailer is unsigned.
  6. Run signature verification where trust matters
    On the sample that will carry weight, run git verify-commit or git log --show-signature and record the cryptographic pass or fail, not just the badge.
  7. Assign an evidence verdict per field
    Label each field trustworthy, spoofable, or privacy-degraded with the reason. This is the artifact the person accountable for provenance signs off on.

The verify-a-sample pipeline

  1. Fetch raw
    Every field a separate column
  2. Split identities
    Author versus committer, both dates
  3. Tag emails
    Real, noreply, legacy, bot
  4. Verify sample
    git verify-commit on what matters
  5. Verdict
    Trustworthy, spoofable, or privacy-degraded per field
Ingest all fields as columns, tag them, then spend signature checks only on the commits whose trust you will lean on.

How this goes wrong: the false positives

Every failure mode below is a place a pipeline records a confident fact that the data does not support. Each row names the false positive and the check that catches it.

  • Trusting the author field as identity. A commit "by" a senior engineer that anyone typed via git config. Check: is it signed and verified? If unverified, the name and email are a claim only.
  • Reading Verified as "this author wrote it." A verified badge on a commit whose author differs from the signing committer. Check: compare author versus committer; signing covers only the committer.
  • Assuming web-edited commits are locally authored. A committer of GitHub means the commit was made in the browser, not on the person's machine. Check: read the committer field, not just the author.
  • Treating a username-only noreply as durable. Attribution silently breaks after a rename; only the ID-prefixed form survives. Check: is there a numeric ID prefix?
  • Believing push-blocking scrubbed the whole branch. The real email still sits in older commits because only the most recent commit is checked. Check: scan the full history, not the tip.
  • Counting Co-authored-by as verified collaborators. An unsigned trailer can name anyone; it is not authenticated and is easy to fabricate. Check: treat the co-author as a claim with its own verification status.
  • Assuming timestamps are real. The author date can be set to any value via GIT_AUTHOR_DATE, and an amend keeps the old author date while the committer date jumps. Check: compare the two dates and distrust either in isolation.
  • Trusting a stale verified badge. A commit signed with a since-revoked key still reads Verified. Check: capture the key ID and its status, not just the badge state.

The through-line is that a signature is the only field that resists forgery, and it binds one person - the committer or, more precisely, the signer. Everything you build on top of unsigned author and committer fields is provenance you asserted, not provenance you verified. That is fine for volume work, but label it as such so the person accountable for the pipeline knows which records would survive a challenge.

The pre-publish checklist

Run this before any commit-derived record leaves your pipeline as evidence of who did what.

Before a commit record is called evidence

  • Every commit field was pulled from the raw object, not scraped from the rendered UI.
  • Author and committer are stored as separate identities, with both AuthorDate and CommitDate captured.
  • Each email is tagged as real, ID-prefixed noreply, legacy username-only noreply, or bot.
  • ID-prefixed noreply emails are resolved to the stable user ID, and username-only ones are marked as rename-fragile.
  • Verification state and the signing key ID and type are stored alongside each commit, not inferred from a badge.
  • Co-authored-by trailers are captured as separate rows, each with its own email tag and verification status.
  • Signatures were verified with git verify-commit on the sample that trust rests on, and the cryptographic result, not the badge, is recorded.
  • Each field carries a written verdict of trustworthy, spoofable, or privacy-degraded, with the reason.

Keeping the rules current

The mechanisms in this reference are stable, but two values will drift and one behavior can change under you. Re-check them rather than trusting a cached answer.

The noreply cutoff date, July 18, 2017, and the format strings are set by GitHub and could be extended; when you see a new noreply shape, confirm whether it carries a numeric ID prefix, because that single feature decides whether attribution survives a rename. The signature verification tooling evolves too - S/MIME verification, for instance, requires Git 2.19 or later - so pin the git version your pipeline verifies with and re-confirm after upgrades. And because verification is persistent, a key revocation that happens today does not touch yesterday's Verified commits; if you need current trust, verify the key's status at read time, not the badge's state at commit time.

Set your field-trust rules programmatically and version them. With 49,362 US Software Engineers listing Git in Refolk's index, plus 7,010 in the UK and 4,573 in Germany, the volume rules out per-profile hand-checking. The rules in the trust map are the durable part; the field values are not. Keep the map, re-verify the values, and let the signature - the one field that cannot be typed - carry the weight whenever a record has to stand up.

Questions practitioners ask

Is the git commit author field reliable as identity evidence?

No. The author name and email are set from client-side inputs - the --author flag, then GIT_AUTHOR_* environment variables, then user.* config - so anyone can commit under another person's name and address. On its own, an author field is a claim. It becomes evidence only when a valid signature binds the identity, and even then the signature verifies the committer, not the author.

What does the GitHub Verified badge actually prove?

It proves a commit was signed with a GPG, SSH, or S/MIME key that GitHub could validate against a key on the signer's account. Critically, commit signing verifies only the committer's identity, not the author's. So a Verified commit can still carry a spoofed author email. Treat the badge as proof about the signer, not about whoever the author field names.

What is the GitHub noreply email format and does it survive a rename?

Accounts created after July 18, 2017 get ID+USERNAME@users.noreply.github.com, where the numeric prefix is the stable user ID; those commits stay attributed after a username change. Accounts that enabled email privacy before that date got USERNAME@users.noreply.github.com, which loses attribution when the username changes. GitHub App commits use USERID+APP-NAME[bot]@users.noreply.github.com.

How do I detect a spoofed or amended commit?

For spoofing, run git verify-commit or git log --show-signature: an unsigned commit cannot be authenticated at all, and a spoofed one shows as Unverified once flagging mode is on. For amends and rebases, use git log --format=fuller and compare AuthorDate to CommitDate - divergence signals the commit was replayed. Any content change also produces a new SHA.

Are Co-authored-by trailers trustworthy for collaboration evidence?

No. Co-authored-by is an unsigned message trailer, not a structured authenticated field, so anyone can name anyone. Attribution to a GitHub account only works when the trailer uses the email tied to that account, but nothing verifies the person consented or contributed. Capture co-authors as separate rows with their own verification status and treat the trailer itself as a claim.

Try it on your own search

Stop building boolean strings. Just describe the person.

Type one sentence and I plan the search, read GitHub, public LinkedIn and Crunchbase records, and the open web live, then hand back a ranked shortlist with the reasoning behind every name. No filters to learn, no export to clean up, no sales call to sit through.

  • One sentence in, a ranked shortlist out. No boolean, no filters, no seat to buy.
  • Read live at search time, not from a database that went stale last quarter.
  • Watch every step as it runs, and see why each name made the list.

500 free credits on sign-up. No card, no demo call. See real searches.

Read next