# The Repo-Sourced Field Reference: What Each Value Proves and How It Lies

*You can take any field in a repo-sourced contact record and state what it identifies, its spoofing and error risk, its personal-data sensitivity, and how often to re-verify it.*

- Canonical URL: https://www.refolk.ai/guides/repo-sourced-field-reference
- Pillar: Process, data, and compliance
- Format: Reference
- Published: 2026-09-20
- Last reviewed: 2026-09-20
- Reading time: 16 min
- Keywords: git commit metadata fields explained, commit author email vs committer, github profile field reliability, repo sourced contact data fields, spoofable git commit fields, github noreply email meaning

## Key takeaways

- Author email drives GitHub's contributor attribution but is plain text set by local git config, so the field recruiters lean on hardest is the one an attacker overwrites in a single command.
- A Verified badge is frozen at push time and never re-run, so a commit stays Verified even after its signing key is revoked or expired - the badge proves a past event, not present identity.
- The REST profile email is null whenever no public primary is set, so pipelines that read null as 'unreachable' discard people whose email sits in the commit metadata.
- Under GDPR Article 4 the author name and a personal email are personal data even when scraped from a fully public repo, so a 'public data' defense does not remove retention or lawful-basis obligations.
- The same Software Engineer plus Git and GitHub filter returns 53,125 profiles in the US versus 4,637 in Germany in Refolk's index, an 11.5x gap, with German talent roughly 40% concentrated in Berlin.
- A rebase keeps the author line but rewrites the committer, the commit date, and the SHA, so a record keyed on SHA silently breaks after a history rewrite while the human identity looks unchanged.

When you build or audit a contact record mined from repositories, you need to know, field by field, what each value actually proves. This is the data dictionary for that job: for recruiting and revenue operations and anyone answerable for how the data was gathered. Jump to the row you are settling, read what the field identifies, how it can be spoofed or go wrong, whether it counts as personal data, and how fast it decays.

The other repository guides in this library cover lawful clearance, the cleanup pipeline, batch teardowns, and grading a single email. This one is different: it is the per-field lookup you open mid-task to settle one cell. Every section opens with a direct answer you can quote on its own, then elaborates.

## Which fields are verifiable and which are just plain text?

Only a cryptographic signature is verifiable. Author name and email, committer name and email, and the profile email are all plain text or user-set, which means they can be wrong or forged without any hacking.

The single most important fact in repo-sourced data is that GitHub attributes a commit to a person by matching the commit's author email against current user accounts. The email lives inside the commit as plain text set by local git config. Anyone can run `git config user.email` with someone else's address, push, and GitHub will display that person as the author. No password, no exploit - this is how Git was designed to work.

That is why the field recruiters and researchers lean on hardest, the author line, is the one an attacker overwrites in a single command. The only field that carries cryptographic weight is a GPG, SSH, or S/MIME signature, and only when GitHub could verify it against a key bound to the account.

**53,125 - US profiles titled Software Engineer with Git and GitHub skills, in Refolk's index**

The same filter returns 4,637 in Germany, an 11.5x gap - so identical repo-sourcing tactics yield very different pool sizes by market.

Table A is the spine of this reference. Read it as: what the field claims, whether that claim can be forged, and whether anything binds the claim to a real identity.

### Table A - Field trust classification

| Field | What it proves | Spoofable | Cryptographically verifiable |
|---|---|---|---|
| Author email | Claimed original writer | Yes | No |
| Committer email | Claimed last applier | Yes | No |
| Pusher (GitHub) | Authenticated account that pushed | No (server-side) | Indirectly, via account auth |
| GPG/SSH signature | Key holder signed the commit | No if enforced | Yes |
| Profile email (REST) | Public primary email, if set | Partially | No |

The pusher is worth calling out because it is easy to miss. It is a GitHub-side attribute: the authenticated account that actually pushed the commit, distinct from author and committer. You cannot set it from your local config the way you set the author, so it is server-side trustworthy - but it tells you who pushed, not who wrote or last applied the change.

> **Rule:** Author and committer are equally untrustworthy
>
> Both the author line and the committer line are plain text in the commit object. Neither is more reliable than the other, and neither means anything about identity without a valid signature bound to the account.

## What is inside a raw commit object?

A raw commit object holds a tree hash, one or more parent hashes, an author line, a committer line, and the message. Each of the author and committer lines carries four sub-fields: name, email, a unix timestamp, and a timezone offset.

Concretely, a commit reads like: `author Ivan Bessarabov <ivan@bessarabov.ru> 1565555421 +0300` followed by a committer line with the same four sub-fields. The message follows. The commit SHA is a 40-character checksum computed over that content, usually shown as the first 7 characters, and it changes any time the content or parent linkage changes.

This structure matters for two audit questions. First, the timezone offset in the author line is a weak signal about where the author was at commit time - weak because it is set locally and often left at a machine default. Second, and more important, the split between author and committer is where records quietly break.

#### The three layers of a repo-sourced record

1. **Derived enrichment** - Inferred employer, seniority, or contact - only as good as the layer beneath it
2. **GitHub profile and API fields** - login, id, name, company, location, blog, public email - user-set, nullable
3. **Git commit object** - author and committer name, email, dates, timezone, tree and parent hashes - plain text

*Each layer has its own trust rules; classify a value by the layer it came from before you judge it.*

On amend or rebase, the author and author date remain unchanged, while the committer and commit date update to reflect whoever performed the operation and when. The rewrite also produces a new SHA and a new parent linkage. So a record keyed on the SHA silently breaks after any history rewrite, while the human identity in the author line looks untouched. If you attribute work by reading the committer of a rebased commit, you credit whoever ran the rebase, not the person who wrote the code.

> A rebase keeps the author and rewrites everything else, so the SHA breaks while the name looks unchanged.

## What does the signature status actually tell you?

There are exactly three signature states, and each says something narrow. Verified means the commit is signed and the signature was successfully verified. Unverified means it is signed but the signature could not be verified. No verification status means it is not signed at all.

A Verified badge raises trust in the author line only to the extent the signing key is bound to that account. It is strong evidence, not proof, and there are two ways it misleads.

The first is time. Persistent verification reflects the verified state at the moment of verification. If a signing key is later revoked or expires, previously verified commits keep their Verified status, and GitHub will not re-verify them. The badge proves a past event, not present identity. Read the `verified_at` field from the REST commit response and confirm the key was valid at that time before you treat the badge as identity evidence.

The second is bypasses. Signature systems have had real failures. GitLab once attributed a Verified label to x509-signed commits without checking the signer's email against the account. A GitHub web-flow signing endpoint was abused with a zero-length author name. Treat Verified as a high-value signal you still corroborate, not a closed case.

One clean case: GitHub's own web-UI edits are GPG-signed by GitHub, so the committer shows as GitHub and the status shows Verified using the web-flow public key. That Verified badge tells you the edit happened in the browser, not that a specific human signed with their own key. And note enterprise managed-user accounts created after August 1, 2024 are unverified by default, which changes how you read a missing badge for those users.

> **Watch out:** A Verified badge ages into a false positive
>
> Because verification is frozen at push time and never re-run on key revocation, a commit stays Verified after its key dies. Always read verified_at; a badge with no date check is not proof of current identity.

## What do the GitHub profile and email fields resolve to?

The REST user endpoint returns profile fields, but the ones you care about most are nullable or scope-dependent. The public email field is null unless the user has set a public primary email, which most people never do.

The email key is the publicly visible email from the profile page. A user can select a primary email to be public; if they do not, the field has a value of null. This is the single most common false negative in repo sourcing: a pipeline reads null and marks the person unreachable, even though their email may sit in the commit metadata as the author address. Null means "no public primary," not "no email."

Then there is the noreply format, which is a genuine dead end. If a user keeps their commit email private, GitHub substitutes a proxy on `users.noreply.github.com`. Accounts created after July 18, 2017 use the form `ID+USERNAME@users.noreply.github.com`; accounts that enabled privacy before that date use `USERNAME@users.noreply.github.com`. Both bounce. The ID+USERNAME form looks like a mailbox and is not one, so it fools naive validators.

I ran this search: `Frontend engineers in Germany who contribute to open source but keep their commit email private via a noreply address.` - [see the full result list](https://www.refolk.ai/s/gqmppggjqf).

*Returns German frontend contributors whose commit email is a users.noreply.github.com proxy, so you know upfront which records need a different contact path.*

Some profile fields depend on the token, not the user. Tokens need the `read:user` or broader `user` scope to return the private user response, which adds fields such as `private_gists`, `total_private_repos`, `owned_private_repos`, `disk_usage`, `collaborators`, and `two_factor_authentication`. Tokens without those scopes get the public response. Separately, the private profile visibility setting can make values such as followers and following differ from an unauthenticated view, even though the token owner is authenticated. So do not expect a private profile's fields to come back blank just because you hold a token.

Finding the developers worth building a record for is the harder half. [Refolk](/) lets you ask for the people you want in plain English across the public GitHub graph, LinkedIn, and the open web, so you spend your time classifying fields rather than assembling the list.

## How do I classify personal-data sensitivity per field?

Under GDPR Article 4, a name, an identification number, and online identifiers are personal data. This holds even when you scraped the value from a fully public repository, so a "it was public" argument does not remove your obligations.

The practical test is individual versus generic. A personal business email such as `jane@company.com` is personal data. A generic role address such as `info@company.com` is not. Apply that test field by field. The author name and any personal email in the commit or profile carry personal-data flags and need a lawful-basis note; a role address does not. The two errors are symmetric: over-restricting a role address wastes effort, and under-protecting a personal email is a compliance failure.

The risk hides in the name, not the code. The commit content is not personal data, but the author name attached to it is. That is why the classification step belongs to whoever owns data protection, not to whoever wrote the scraper.

#### Personal-data sensitivity vs contactability

Horizontal axis runs from Not personal data to Personal data. Vertical axis runs from Not contactable to Contactable.

| Quadrant | What it means |
| --- | --- |
| Role address, no reply path | Low risk, low value - keep only if it aids resolution |
| Personal name only | Personal data, no reach - protect it, do not treat as a lead |
| Generic role mailbox | Contact freely, no Article 4 duty attaches |
| Personal deliverable email | Highest care - lawful basis and retention clock both apply |

*Place each identity field by whether it is personal data and whether it can reach a person, then handle each quadrant differently.*

## The field-by-field audit procedure

Run the record through seven steps, from splitting the layers to recording provenance. The whole pass is roughly 80 minutes for a single record and batches cleanly through the API for the signature and email checks.

#### Audit a repo-sourced contact record, field by field

1. **Pull the record and separate the layers** - Split each contact into git-commit fields, GitHub profile and API fields, and derived enrichment. Tag every value with its origin layer.
2. **Classify trust per field** - Mark each field spoofable or cryptographically verifiable using the commit-metadata rules. Remember author and committer are both plain text.
3. **Check signature state** - Read Verified, Unverified, or no status, and capture the verified_at timestamp from the REST commit response for each commit.
4. **Resolve email to identity** - Detect noreply addresses, map the ID+USERNAME format to a login, and flag any null REST email. Mark each email deliverable, noreply, or absent.
5. **Tag personal-data sensitivity** - Apply Article 4. Names and personal emails are personal data; generic role addresses are not. Attach a lawful-basis note to each personal-data field.
6. **Assign a re-verification interval** - Set a cadence per field class using each field's decay driver, from never for immutable hashes to three months for employer fields.
7. **Record provenance and retention** - Store the source URL or commit SHA plus the capture date for each value, so every field has auditable lineage.

On step 2, ignore any source that implies the committer is more trustworthy than the author. It is not. Both are plain text, and neither is verifiable without a signature.

## How often does each field need re-verifying?

No regulator or platform publishes field-level re-verification cadences for repo-sourced records, so treat every interval below as practitioner judgment tied to each field's decay driver, not a standard you can cite. What is sourced is the decay mechanics: emails move with privacy toggles and job changes, usernames get renamed, employers change.

### Table C - Re-verification cadence (derived, not a published standard)

| Field class | Decay driver | Suggested re-check |
|---|---|---|
| Commit SHA / tree / parent | Immutable unless history rewritten | Never; re-pull if branch rewritten |
| Author / committer name | Rare change | 12 months |
| Personal email | Privacy toggle, job change | 3-6 months |
| Employer / company | Job moves | 3 months |
| Location | Relocation | 6-12 months |

The immutable fields are the anchor and the trap. A SHA never decays on its own, so it looks like the safest key in the record. But a rebase or force-push rewrites it, so the "never re-check" rule carries a condition: if the branch was rewritten, re-pull, because your stored SHA now points at nothing.

#### Setting a next-check date per field

1. **Read field class** - Look up the field in the cadence table
2. **Identify decay driver** - Immutable, rare change, privacy toggle, job move, or relocation
3. **Apply interval** - Never, 12 months, 3-6 months, 3 months, or 6-12 months
4. **Stamp next-check date** - Write the date onto the record so the field expires on schedule

*Route each field by its decay driver to the interval that matches how fast it can silently go wrong.*

Employer decays fastest because job moves happen without any change to the repo, so a record that looked perfect at capture is wrong within a quarter. Location is slower but geographically consequential, which the pool data makes concrete.

## Where does the market skew, and why does that change your audit?

The same profile filter returns very different pools by geography, so the volume of records you audit and their spread differ sharply by market. In Refolk's index, a Software Engineer with Git and GitHub skills returns 53,125 profiles in the US and 4,637 in Germany.

### Table B - Refolk index pool comparison

| Market | Matching profiles | Top hub (sample share) | Ratio vs Germany (derived) |
|---|---|---|---|
| United States | 53,125 | NY / SF (split) | 11.5x |
| Germany | 4,637 | Berlin (~40%) | 1.0x |

The counts and hubs come from Refolk's index; the ratio and share are derived from those counts. Two consequences for the audit. First, the US pool is roughly 11.5x larger, so batching the signature and email checks through the API is not optional at that scale. Second, the geography concentrates differently: the German sample puts about 40% of top regions in Berlin, while the US sample splits across New York and San Francisco with no single region above roughly 16%. A location field that is stale in a Berlin-heavy pool is a bigger error, because more of your records claim the same place.

## How these records go wrong

The failure modes below are the highest-value part of this reference, because each one is a false positive that looks correct until it costs you. Every row pairs the mistake with the check that catches it.

- **Trusting the author field.** A commit "by" a senior maintainer that a stranger set via config. Check: is the commit signed and Verified, and does the signing key belong to that account.
- **Treating Verified as current identity proof.** A Verified badge on a commit signed with a key since revoked. Check: read `verified_at` and confirm the key was valid then; verification is frozen at push time.
- **Emailing a noreply address.** `ID+USERNAME@users.noreply.github.com` looks like a mailbox but bounces. Check: reject any address on `users.noreply.github.com`.
- **Assuming null API email means no email.** Marking a contactable person unreachable because REST returned null. Check: null only means no public primary; the email may still sit in commit metadata.
- **Believing committer is more trustworthy than author.** Both are plain text. Check: neither is verifiable without a signature.
- **Reading a rebased commit's committer as the author.** Attributing work to whoever ran the rebase. Check: read the author line, not the committer.
- **Misclassifying a role address as personal data, or the reverse.** Over-restricting `info@` or under-protecting `jane@company.com`. Check: apply the individual-versus-generic test.
- **Assuming private-profile fields hide via any token.** Expecting followers and following to be blank. Check: the token owner still authenticates, so values can differ from the unauthenticated view.

**Per-field audit annotation**

```
field: <field name>
origin_layer: commit | profile-api | derived
value: <captured value>
trust: spoofable | server-side | signature-verifiable
signature_state: verified | unverified | none | n/a
verified_at: <timestamp or n/a>
email_status: deliverable | noreply | null | n/a
personal_data: yes | no
lawful_basis: <note or n/a>
source: <url or commit SHA>
captured: <date>
next_check: <date>
```

*Attach one of these to every field in the record; the origin layer decides which rules apply.*

## Before you call the record clean

Run this checklist before you sign off. It is the difference between an auditable record and one that looks complete but breaks under a data-subject request or a rebase.

#### Sign-off checklist

- [ ] Every value is tagged with its origin layer: commit, profile/API, or derived.
- [ ] Each field carries a spoofable-versus-verifiable trust label.
- [ ] Signature state and verified_at are recorded for every commit, and revoked-key cases are flagged.
- [ ] Every email is marked deliverable, noreply, or absent, with no noreply address treated as reachable.
- [ ] No null REST email was treated as "no contact" before checking the commit layer.
- [ ] Each personal-data field has a flag and a lawful-basis note; role addresses are correctly excluded.
- [ ] Every field has a next-check date matching its decay driver.
- [ ] Every value has a source URL or commit SHA plus a capture date.

> **Tip:** Batch the mechanical checks
>
> Signature state, verified_at, and null-email detection are all API reads. Pull them in one pass per record set so the human time goes to trust classification and personal-data tagging, which do not automate.

To keep this reference current, re-check the two things that move: platform defaults and your own records. Platform behavior changes - the noreply format changed at a cutover date, and enterprise managed users flipped to unverified-by-default at another - so when a badge or an email format surprises you, confirm the current rule against the platform's own documentation rather than assuming last quarter's behavior. Your records move on the cadence in Table C. Set the next-check dates when you build the record, not when you remember, and the field-level decay will surface on schedule instead of surprising you inside a live search.

## Frequently asked questions

### What is the difference between the commit author email and the committer email?

The author is the claimed original writer of the change; the committer is whoever last applied it. Both live in the raw commit object as plain text with a name, email, unix timestamp, and timezone offset. Neither is verifiable without a signature. On a rebase or amend the author and author date stay unchanged while the committer and commit date update to whoever ran the operation, so the committer often is not the person who wrote the code.

### What does a github noreply email address mean and can I contact it?

A users.noreply.github.com address means the user chose to keep their commit email private, so GitHub substitutes a proxy. You cannot reach a person through it; mail to it bounces. Accounts created after July 18, 2017 use the ID+USERNAME@users.noreply.github.com form; older privacy-enabled accounts use USERNAME@users.noreply.github.com. Reject any address on users.noreply.github.com as undeliverable.

### If the GitHub REST API returns a null email, does the person have no email?

No. The REST email field is null whenever the user has not set a public primary email, which is the default. It is a completeness gap, not a reachability verdict. The person's email may still appear in commit metadata as the author or committer address. Treating null as 'no contact' silently discards contactable people, so check the commit layer before marking anyone unreachable.

### Can I trust a commit that shows a Verified badge?

A Verified badge means the commit was signed and the signature verified at push time, but only to the extent the signing key is bound to that account. Verification is frozen: if the key is later revoked or expires, the commit keeps its Verified status and GitHub does not re-verify. Read the verified_at timestamp and confirm the key was valid then. Signature systems have also had bypasses, so a badge is strong evidence, not proof.

### Is data scraped from a public GitHub repo still personal data under GDPR?

Yes. Under GDPR Article 4, a name, an identification number, and online identifiers are personal data regardless of whether the source is public. A personal business email such as jane@company.com is personal data; a generic role address such as info@company.com is not. A 'it was public' argument does not remove your lawful-basis and retention obligations for the author name and personal email in a repo-sourced record.

### How often should I re-verify repo-sourced contact fields?

No regulator or platform publishes field-level cadences, so treat any interval as practitioner judgment tied to each field's decay driver. Immutable hashes never need re-checking unless the branch is rewritten. Author and committer names change rarely, so roughly twelve months. Personal emails move with privacy toggles and job changes, so three to six months. Employer fields move fastest, around three months, and location every six to twelve.

---

*From the Refolk guide library. I revise these guides rather than replacing them, so the current version is always at https://www.refolk.ai/guides/repo-sourced-field-reference*
