Skip to content

Fix global auth when GIT_CONFIG_GLOBAL is set in the environment#2449

Open
nmoinvaz wants to merge 1 commit into
actions:mainfrom
nmoinvaz:fix/git-config-global-override
Open

Fix global auth when GIT_CONFIG_GLOBAL is set in the environment#2449
nmoinvaz wants to merge 1 commit into
actions:mainfrom
nmoinvaz:fix/git-config-global-override

Conversation

@nmoinvaz
Copy link
Copy Markdown

@nmoinvaz nmoinvaz commented Jun 5, 2026

Problem

When a checkout sets up global auth (e.g. submodules: true), configureTempGlobalConfig does:

  1. Copy ~/.gitconfig into a temp dir and override HOME to point at it.
  2. Write the auth token placeholder via git config --global …, expecting it to land in the temp config (because HOME now points there).
  3. Read the temp config back and swap the placeholder for the real token (replaceTokenPlaceholder).

The catch: GIT_CONFIG_GLOBAL overrides HOME when git locates the global config file. So if the environment already has GIT_CONFIG_GLOBAL set, step 2 writes to that file instead of the temp config. Step 3 then reads the temp config, doesn't find the placeholder, and fails:

##[error]Unable to replace auth placeholder in /.../_temp/<uuid>/.gitconfig

checkout only ever overrides HOME, never GIT_CONFIG_GLOBAL — so a GIT_CONFIG_GLOBAL set by the workflow or runner (a common way to isolate git config per job on self-hosted runners) silently wins.

Fix

Pin GIT_CONFIG_GLOBAL to the temporary config alongside the existing HOME override, and unset it again in removeGlobalConfig. Both env vars then point at the same temp file, so --global operations target it regardless of any inherited value. Backward compatible: older git that ignores GIT_CONFIG_GLOBAL still falls back to the HOME override (same file).

How it works

setEnvironmentVariable/removeEnvironmentVariable don't change the process environment — they edit the GitCommandManager's gitEnv map, which is overlaid on top of process.env each time checkout spawns a git subprocess:

const env = {}
for (const key of Object.keys(process.env)) { env[key] = process.env[key] }
for (const key of Object.keys(this.gitEnv)) { env[key] = this.gitEnv[key] } // overrides win
  • The set in configureTempGlobalConfig forces GIT_CONFIG_GLOBAL=<temp>/.gitconfig for checkout's git commands, shadowing any inherited value — this is the fix.
  • The remove in removeGlobalConfig is teardown that mirrors the existing HOME cleanup; the fix does not depend on it.

Reproduction (real git 2.54)

Inherited GIT_CONFIG_GLOBAL set to a decoy file, simulating checkout's git config --global write then the temp-config read:

--global write lands in placeholder in temp config result
HOME override only (today) the inherited file absent Unable to replace auth placeholder
HOME + GIT_CONFIG_GLOBAL pinned (this PR) the temp config present replace succeeds

Scope

The HOME-only override predates v6 — configureTempGlobalConfig has the same shape in v4 and v5 — so this affects v4/v5/v6. The fix applies cleanly in each.

Tests

  • configureGlobalAuth overrides GIT_CONFIG_GLOBAL — asserts the override points at the temp config.
  • removeGlobalConfig removes override — extended to assert GIT_CONFIG_GLOBAL is unset afterward.
  • dist/index.js rebuilt via npm run build.

🤖 Generated with Claude Code

configureTempGlobalConfig isolates global git config by overriding HOME to
a temporary directory. But GIT_CONFIG_GLOBAL takes precedence over HOME when
git locates the global config file, so when a workflow already has
GIT_CONFIG_GLOBAL set in the environment, 'git config --global' writes land
in that file instead of the temporary config. replaceTokenPlaceholder then
reads the temporary config, cannot find the placeholder, and fails with
'Unable to replace auth placeholder'.

Set GIT_CONFIG_GLOBAL to the temporary config alongside the HOME override so
global config operations always target the temp file regardless of any
inherited value, and unset it again in removeGlobalConfig.

Assisted-By: Claude Opus 4.8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant