Did I just push with the wrong account? Check first
You finish a feature in your client’s repository, push, and deploy. Then you see it: the commits say your personal email, and the preview deployment went to your personal Vercel team.
Every one of these tools can tell you who it thinks you are before anything leaves your PC. This post collects the read-only checks for each, a Git hook that blocks the most common mistake, and the fix for commits that are not pushed yet.
The short answer
Section titled “The short answer”Run these from the project folder before you push or deploy:
git var GIT_AUTHOR_IDENT # who your next commit will be bygit log --format='%h %an <%ae> %s' '@{u}..' # commits not pushed yet, with their emailgit remote -v # HTTPS or SSH: which login will pushgh auth status --active # the gh account in useThen the check for the tool you are about to deploy with, from the table further down. All of these only read.
Commits: who is the author?
Section titled “Commits: who is the author?”git var GIT_AUTHOR_IDENT prints the name, email and time stamp that Git would use for a commit made right now. If the email is wrong, find out where it came from:
git config --show-origin user.emailThat prints the config file that won. It may be your global .gitconfig, a folder rule file, or the repository’s own .git\config. For the folder rule setup, see a different Git email per folder.
To see commits you made but have not pushed:
git log --format='%h %an <%ae> %s' '@{u}..'@{u} means “the upstream branch”. The quotes matter in PowerShell, where @{ starts a hashtable. We ran this exact line in Windows PowerShell 5.1 and PowerShell 7.
Pushes: which GitHub account?
Section titled “Pushes: which GitHub account?”The commit email is not the account that pushes. That depends on the remote:
git remote -v- HTTPS remote (
https://github.com/...). Your credential helper picks the login. If you use Git Credential Manager with a user name per folder,git config --get-urlmatch credential.username https://github.comshows which one this folder asks for. If you useghas the helper,gh auth status --activeshows the account. - SSH remote (
git@github.com:...). The SSH key picks the account.ssh -T git@github.comanswers “Hi USERNAME! You’ve successfully authenticated, but GitHub does not provide shell access.”
Do not use gh auth status --show-token or gh auth token for this. They print the token, and the user name is all you need.
More on how each method chooses: Multiple GitHub accounts on one PC.
Deploys: who is signed in to each CLI?
Section titled “Deploys: who is signed in to each CLI?”| Tool | Read-only check | What to look at |
|---|---|---|
| Vercel | vercel whoami |
Your user name. Teams are separate: vercel teams ls lists yours, and in a linked folder .vercel\project.json holds the orgId and projectId it deploys to. |
| Firebase | firebase login:list |
The README says “the default account for the current context will be listed first”. Never add --json: in firebase-tools 15.32.1 that output includes tokens. |
| Supabase | supabase projects list |
Projects the signed-in user can access. Recent versions also have supabase whoami, which is not in the reference docs yet. |
| Cloudflare | wrangler whoami |
The user and the accounts it can reach. --json “exits with a non-zero status if not authenticated”. |
| Convex | Read CONVEX_DEPLOYMENT in .env.local |
Convex picks the deployment per project from that file. |
| Claude Code | claude auth status |
JSON with loggedIn, email, orgName and configDirectory, the account folder that was used. It exits with 1 when not signed in. |
Two of these need a word of care:
- Vercel’s team is a separate switch.
vercel switchchanges “to a different team scope”, not to a different account. You can be the right person in the wrong team. - Firebase also remembers an account per folder.
firebase login:usesets “the default account to use for this project”. That is a feature, but it means two folders can quietly use two accounts.
The hidden winner: environment variables
Section titled “The hidden winner: environment variables”Many CLIs let a token in an environment variable override the saved login. GitHub CLI says GH_TOKEN “takes precedence over previously stored credentials”. Wrangler puts CLOUDFLARE_API_TOKEN first in its order. Claude Code uses ANTHROPIC_API_KEY “instead of your Claude Pro, Max, Team, or Enterprise subscription even if you are logged in”.
To check which of these are set, without printing their values:
'GH_TOKEN','GITHUB_TOKEN','VERCEL_TOKEN','CLOUDFLARE_API_TOKEN','SUPABASE_ACCESS_TOKEN','CONVEX_DEPLOY_KEY','ANTHROPIC_API_KEY','CLAUDE_CONFIG_DIR' | Where-Object { Test-Path "Env:$_" }It prints only the names that exist. If a name appears that you did not expect, find out where it is set before you trust any whoami.
Fix commits before you push
Section titled “Fix commits before you push”If the last commit has the wrong email, fix your config first, then:
git commit --amend --reset-author --no-editThe Git docs say --reset-author declares “that the authorship of the resulting commit now belongs to the committer”. For several unpushed commits, rewrite each one with the new identity:
git rebase --exec 'git commit --amend --no-edit --reset-author' '@{u}'We tested both in a throwaway repository in PowerShell 5.1 and 7: every unpushed commit got the new email, and the pushed ones were left alone. Both commands rewrite commits, so only use them on commits nobody else has.
Already pushed?
Section titled “Already pushed?”GitHub links a commit to a user “by matching the email address in the commit header to an email address on a GitHub account”. If the email simply belongs to you, adding it to the right account may be enough, though GitHub warns that “old commits might not be linked after you update your email settings”.
Rewriting pushed commits means a force push and new commit IDs for everyone. On a shared branch, ask first. If you do, use git push --force-with-lease, which refuses to update the remote branch if it changed since you last fetched it.
Stop it next time: a pre-push hook
Section titled “Stop it next time: a pre-push hook”Git runs .git\hooks\pre-push before every push. Git for Windows runs hooks with its own sh, so this script works on Windows as it is. Save it as .git\hooks\pre-push in the repository, and set the email:
#!/bin/sh# Stop a push that carries commits made with another email.expected="you@work.example"zero=$(git hash-object --stdin </dev/null | tr '0-9a-f' '0')
while read local_ref local_oid remote_ref remote_oiddo if [ "$local_oid" = "$zero" ]; then continue # deleting a branch, nothing to check fi if [ "$remote_oid" = "$zero" ]; then range="$local_oid --not --remotes" # new branch else range="$remote_oid..$local_oid" fi wrong=$(git log --format='%h %ae %s' $range | grep -v "^[0-9a-f]* $expected ") if [ -n "$wrong" ]; then echo "pre-push: these commits are not by $expected:" >&2 echo "$wrong" >&2 exit 1 fidoneexit 0We tested it against a local remote: a clean push went through, and a push with one commit by another email stopped with the list of bad commits, on an existing branch and on a new one. Hooks are per repository and are not pushed, so each clone needs its own copy.
How Devpit does the same check
Section titled “How Devpit does the same check”Devpit’s Accounts page is this whole post as one screen. For the folder you are in, it lists every supported tool with three columns: the tool, the account, and why that account applies (a folder rule, “everywhere”, or “set by this project’s .env.local” for Convex). See Accounts.
- Press v to verify. Each tool gets one live row with the expected account next to the actual one, and a one-key fix when they differ.
- Verify also catches the quiet causes from this post: a Git line that overrides Devpit’s rule (found with
--show-origin), a repository’s ownuser.email, and a PowerShell function or alias with the tool’s name that runs before Devpit’s shim. - From a script or an AI agent,
devpit accounts verify --jsongives the same result as JSON and exits with code 4 when it finds a mismatch. See the command line reference. - The checks only read. Devpit asks each tool its own “who am I” question and never shows, saves or logs a token.
Checklist
Section titled “Checklist”git var GIT_AUTHOR_IDENTbefore the first commit in a new folder.git log ... '@{u}..'before you push.git remote -v, then the helper orssh -T git@github.com.- The tool’s own
whoamibefore you deploy, and the team or project too. - Check for token environment variables by name.
- Add the pre-push hook to repositories where a wrong email would hurt.
Sources
Section titled “Sources”- Git: git-var
- Git: git-config (
--show-origin) - Git: git-commit (
--amend,--reset-author) - Git: git-push (
--force-with-lease) - Git: githooks (pre-push)
- GitHub CLI manual: gh auth status
- GitHub CLI manual: environment variables
- GitHub Docs: Testing your SSH connection
- GitHub Docs: Troubleshooting commits
- Vercel: vercel whoami
- Vercel: vercel teams and vercel switch
- Vercel: Linking projects (
.vercel/project.json) - firebase-tools README: Multiple accounts
- Supabase CLI reference
- Cloudflare: Wrangler general commands (
whoami,auth tokenorder) - Convex: CLI (
.env.localandCONVEX_DEPLOYMENT) - Claude Code: CLI reference (
claude auth status) - Claude Code: environment variables
Common questions
Can I fix the email on commits I already pushed?
Only by rewriting history and force-pushing, which changes the commit IDs for everyone who pulled them. On a shared branch, talk to your team first. Often it is enough to add the email to the right GitHub account, because GitHub links commits by email, although GitHub says old commits might not be linked after you change email settings.
Is it safe to run these check commands?
Yes. Every command in this post only reads. None of them prints a token, as long as you do not add options such as --show-token, and you never run firebase login:list with --json, which prints tokens.
Why does a tool ignore the account I signed in with?
An environment variable such as GH_TOKEN, VERCEL_TOKEN, CLOUDFLARE_API_TOKEN, SUPABASE_ACCESS_TOKEN or ANTHROPIC_API_KEY usually wins over the saved login. Check for them by name, as shown in this post.
