Who authored that commit, really?
I do not mean the chat persona. I mean git log.
Chat is a story. Git objects are evidence. I keep hearing five identity myths on borrowed boxes. They survive green tests. They survive a confident model. This FAQ is a gate, not a vibe check.
What we are actually checking
Git authorship is configuration. It is not conversation.
The model cannot "become you" by using your name in prose. A hostname cannot either. Three files beat the transcript:
-
.git/configinside the repo -
~/.gitconfigfor the account on that box -
/etc/gitconfigif the image shipped defaults
Ask one rude question before every commit. Who will git log show tomorrow?
Q1. I told the model my name. That is the author, right?
No. That is prompt text.
user.name and user.email live in git config. The model can claim it set them. A claim is not a config file. Do not ask the chat. Run this.
git config --show-origin --get-regexp '^user\.'
git log -1 --format=fuller
--show-origin tells you which file won. That is the whole game.
Myth: the chat greeting is identity.
Evidence: a config path, or an empty result.
Corrected model: identity is a file. The file can be missing. The file can say root. The file can still hold the last tenant's name.
If the two commands disagree, believe git log after the commit. Before the commit, believe --show-origin. A polite assistant does not override that order.
Q2. A free server will inherit my laptop git config
Why would it?
Your laptop is not in the image. Your global config did not teleport. A free remote box is another machine. I treat every new box as amnesiac. That is physics, not mood.
echo "local: $(git config --local --get user.name || echo unset)"
echo "global: $(git config --global --get user.name || echo unset)"
echo "system: $(git config --system --get user.name || echo unset)"
hostname
id
pwd
If local is unset, git walks upward. Global on the box is not global on your laptop. System may be a distro default. Sometimes it prints Ubuntu. Sometimes git blocks the commit. Sometimes it is worse. It commits anyway with a guessed value.
Myth: my usual git setup followed me.
Evidence: three scopes, printed, not summarized.
Corrected model: a free server starts as a stranger. You attach identity on purpose. Or you ship a stranger's name.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. This gate belongs on borrowed environments. MonkeyCode's free model access is one such environment. The free server option is another. The commands do not depend on that product. Strip the names. The FAQ still works.
Q3. The model will refuse a wrong email
Will it?
Models do not own user.email. They do not know your company domain. They do not know your GitHub noreply address. They do not enforce Name <email> policy. A free model can help the refactor. It is not a policy engine.
Try this drill in a throwaway clone. Do not push it.
git config --local user.name "Trap User"
git config --local user.email "trap@invalid.example"
git commit --allow-empty -m "identity trap"
git log -1 --format='%an <%ae>'
git reset --soft HEAD~1
Label it a drill. If the commit succeeds, the myth is dead. The model did not save you. Git did exactly what config said.
Myth: the assistant is a compliance layer.
Evidence: one local commit you immediately reset.
Corrected model: policy lives in hooks. It lives in branch rules. It lives in you. It does not live in the chat.
Want a second check after you restore identity? Use a local hook, not a promise.
mkdir -p .git/hooks
cat > .git/hooks/pre-commit <<'HOOK'
#!/usr/bin/env bash
email=$(git config --get user.email || true)
case "$email" in
""|*root*|*invalid*|*example.com*)
echo "pre-commit: refusing email '$email'" >&2
exit 1
;;
esac
HOOK
chmod +x .git/hooks/pre-commit
That hook is local. It does not travel with a patch. Clone again and it vanishes. That is a feature. You must reinstall it on the next box.
Q4. Push succeeded, so the remote thinks I am me
Push success means a credential worked.
Which credential? You do not know yet. It might be HTTPS with a cached helper. It might be GIT_ASKPASS. It might be gh auth. It might be a deploy key for one repo. It might be a leftover helper on a reused image. Do not assume.
Do not print secrets. Print shapes.
git remote -v
git config --show-origin --get-regexp 'remote\..*\.url'
env | awk -F= '/^(GIT_|GH_|GITHUB_|SSH_)/ {print $1}'
command -v gh >/dev/null && gh auth status || echo "gh not logged in"
That list is variable names. Not values. If a value appears, stop. Rotate it. Do not paste it into chat. Do not paste it into a ticket.
Myth: a green push is personal authorship.
Evidence: remote URL plus auth method, without dumping tokens.
Corrected model: transport identity and commit identity are different. Both can be wrong at once. A bot can push your typo. You can author a commit the bot then pushes. git log still names a person. The person may not have been at the keyboard.
Read the object, not the UI badge.
git log -1 --format='author: %an <%ae>%ncommitter: %cn <%ce>%nsha: %H'
Author can be you. Committer can be the box. Or the reverse. A Co-authored-by trailer will not fix that. Trailers are optional text. They are not signatures.
Q5. Temporary box, so leftover identity does not matter
Temporary for whom?
You may leave. Logs may not. A later session may reuse a volume. I do not know a vendor's disk policy. I refuse to guess it in a FAQ. So I do not store SSH private keys on a free box. I do not paste PATs into the prompt. I do not write production .env files "just for the demo."
The myth is not "the vendor is evil." The myth is "short session equals no footprint."
ls -la ~/.git-credentials 2>/dev/null || true
ls -la ~/.ssh 2>/dev/null || true
git config --get credential.helper || echo "no helper"
If ~/.ssh has keys you did not mount on purpose, stop committing. Treat the box as hostile storage. Copy the diff off. Review it locally.
Myth: free and short means consequence-free.
Evidence: files that can outlive a tab.
Corrected model: identity and secrets are sticky. Code output can be copied. Credentials should never arrive.
Artifact: a twelve-command identity gate
Paste this as a script. Run it before git commit. Run it again before git push. I labeled it proposed. You still read the output. The model does not "approve" it.
#!/usr/bin/env bash
# identity-gate.sh — proposed checks, throwaway clones only
set -euo pipefail
fail() { echo "FAIL: $*" >&2; exit 1; }
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || fail "not a git repo"
echo "--- scopes ---"
printf 'local.name %s\n' "$(git config --local --get user.name || echo UNSET)"
printf 'local.email %s\n' "$(git config --local --get user.email || echo UNSET)"
printf 'global.name %s\n' "$(git config --global --get user.name || echo UNSET)"
printf 'global.email %s\n' "$(git config --global --get user.email || echo UNSET)"
echo "--- origin of user.* ---"
git config --show-origin --get-regexp '^user\.' || echo "user.* completely unset"
echo "--- process ---"
printf 'uid %s\n' "$(id -un)"
printf 'host %s\n' "$(hostname)"
printf 'cwd %s\n' "$(pwd)"
printf 'git %s\n' "$(command -v git)"
echo "--- remotes ---"
git remote -v || true
echo "--- credential helper names only ---"
git config --show-origin --get-regexp '^credential' || echo "no credential.* set"
echo "--- env names only ---"
env | awk -F= '/^(GIT_|GH_|GITHUB_|SSH_)/ {print $1}' | sort -u
echo "--- last commit if any ---"
git log -1 --format='author %an <%ae>%ncommitter %cn <%ce>%n%s' 2>/dev/null || echo "no commits"
echo "--- working tree (names only) ---"
git status --short
Add one human rule. If local.email contains root, invalid, example.com, or the box hostname, do not push. If command -v git points at a wrapper you did not install, stop. Re-read type git.
Decision table
| You observe | Myth it feeds | What it actually means | Do this |
|---|---|---|---|
| Chat says "committed as Jordan" | Chat is git | A sentence was generated | Run git log -1 --format=fuller
|
user.name unset in local |
Git will ask me | Global or system may silently win |
--show-origin on user.*
|
git commit works as root |
Box is mine | Image default authored the object | Set local config or stop |
git push is fast and green |
I am authenticated as me | Some credential cached | Inspect remote URL and helper name |
| Model offers to "fix git config" | Assistant owns identity | It may write the wrong file | Re-run the gate yourself |
Empty ~/.ssh
|
No credential risk | HTTPS helper may still exist | Check credential.helper
|
Co-authored-by trailer present |
Authorship is honest | Trailers are optional text | Compare author vs committer |
None of these rows need a benchmark. They need a command. They need a human reading the command.
How to read a failure
The gate can fail in boring ways. Boring is good.
-
Both name and email UNSET. Git may abort. Or a hook may invent values. Set
--localyourself. -
Origin is
/etc/gitconfig. The image owns you. Override with--local. - Remote URL embeds a token. Stop. Rotate. Rewrite the remote to SSH or a clean HTTPS URL.
- Author and committer disagree. Someone amended. Or a tool restamped. Ask why before you push.
-
ghis logged in, git remote is HTTPS. Two identities may exist. Pick one on purpose.
What does a pass look like? Three boring lines.
author: Your Name <you@your-domain>
source: file:.git/config
remote: git@github.com:org/repo.git
If the model cannot produce those from commands, it did not check. It narrated.
Limitations
This gate does not sign commits. It does not talk to your IdP. It does not prove the patch is correct. It does not prove the free server is isolated. It does not measure model quality. It does not replace git verify-commit when you actually need signatures.
--show-origin can still lie if a wrapper shadows git. Check type git. Hooks can rewrite authors after you look. prepare-commit-msg is real. Re-run git log after the commit, not only before.
I am not giving you a secret-scanning product. env | awk prints names. If your shell prints values, stop. Rotate. Do not use this FAQ as permission to put deploy keys on a free box. The opposite.
Who should not use this approach
- Anyone who cannot send the repo off their laptop.
- Anyone whose org forbids unsigned commits.
- Anyone about to paste a PAT "just to finish."
- Anyone treating a free server as a secret store.
- Anyone who needs hardware-backed SSH and does not have the key on that box.
If that is you, stay local. Copy the diff as a patch. Review it on hardware you control. Let the model propose hunks. Do not let it own user.email.
What I want instead of a story
I want the gate output in the review. I do not want a paragraph that says "committed as you."
Run the twelve commands. Then let the model keep writing code. Authorship is not its job. If git user is root, the model did not become you. It became the image default. That is the whole FAQ.
Top comments (0)