Skip to content

fix(server): projects no longer show another repo's Git state when T3 starts inside a Git command - #28795

Open
only21mil wants to merge 4 commits into
pingdotgg:mainfrom
only21mil:fix/audit-m115
Open

only21mil wants to merge 4 commits into
pingdotgg:mainfrom
only21mil:fix/audit-m115

Conversation

@only21mil

Copy link
Copy Markdown
Contributor

Problem

When T3 Code starts inside a Git command, every project's Git commands can run against the wrong repository. In a linked worktree, Git hooks and git rebase --exec export an absolute GIT_DIR (commit hooks also export GIT_INDEX_FILE). A T3 server started from there passes those variables to all of its Git subprocesses. Every project then shows that worktree's branch, status and repository identity, and checkpoints are written into it.

Reproduction: make two repositories, demo-project on feature/demo-project and inherited-other on wrong-repository-branch. Start the server with GIT_DIR=<inherited-other>/.git, then add demo-project. The sidebar labels it example/inherited-other and the branch picker shows wrong-repository-branch.

Change

gitProcessEnv in VcsProcess.ts builds the environment for a Git child process. It first unsets the repository selectors the server inherited (GIT_DIR, GIT_WORK_TREE, GIT_COMMON_DIR, GIT_INDEX_FILE, GIT_OBJECT_DIRECTORY, GIT_ALTERNATE_OBJECT_DIRECTORIES, the same list #12181 clears), then applies the caller's env, then the existing safe.bareRepository=explicit config from #20440. Selectors a caller sets on purpose still win, such as a checkpoint's private GIT_INDEX_FILE or worktree removal's bound GIT_DIR.

It is used at the three places that spawn Git and already added the bare-repository config: GitVcsDriverCore, VcsProcess (checkpoints, file listing, source-control CLIs) and RepositoryIdentityResolver.

The checkpoint commit env no longer spreads process.env itself, because that spread re-added the inherited selectors as if the caller had set them. #12181's nested-repository probe no longer needs its own cleared env, so that block is removed.

Other GIT_* variables are left alone, including config, auth, SSH and locale. Provider CLIs and terminals still inherit the server's environment unchanged.

Scope and approval

This is a small, focused fix for an obvious bug: Git commands for one project run against a different repository. It uses the CONTRIBUTING exception for obvious bugs, with no issue or discussion. It extends the narrow fix in #12181 to the shared Git spawn paths and clears only the variables #12181 clears.

Maintainers to confirm: the scope covers Git subprocesses only. Provider and terminal environments are unchanged.

Verification

Tests, on macOS with git 2.56. Each fails on main and passes on this branch:

  • GitVcsDriverCore.test.ts "ignores repository selectors inherited by the server". On main, status reports the other repo's branch: expected 'other-repository' to equal 'main'. It also covers a private GIT_INDEX_FILE commit context and an explicit bare GIT_DIR.
  • GitVcsDriver.test.ts "checkpoint capture ignores repository selectors inherited by the server" extends the fix(server): checkpoint workspaces with empty nested repositories #12181 test. The inherited GIT_DIR, GIT_WORK_TREE and GIT_INDEX_FILE now point at a second repository. On main, the checkpoint ref is written there instead. It also checks the second repository is untouched, the fix(server): checkpoint workspaces with empty nested repositories #12181 nested-HEAD exclusion still holds, and an explicit bare GIT_DIR still works on this path.
  • RepositoryIdentityResolver.test.ts "ignores repository selectors inherited by the server". On main it fails with expected 'github.com/t3tools/other' to be 'github.com/t3tools/t3code'.

Runs:

  • vp run check:changed 1d626d02d95f9a2343553f6498037ee82290d304: format, lint, knip and typecheck pass. Tests: 321 passed, 4 failed.
  • vp test run on src/vcs, src/sourceControl, src/workspace, src/checkpointing and the resolver test: 460 passed, 4 failed.
  • The 4 failures are the same in both runs and also fail on unmodified main on this machine. Three come from a global url.insteadOf rewrite in this machine's Git config, and one from macOS /var vs /private/var temp paths. With GIT_CONFIG_GLOBAL=/dev/null and a resolved TMPDIR, they pass.

Which Git contexts set these, checked with a hook that prints them (git 2.56): in a linked worktree, pre-commit, post-commit, post-checkout and git rebase --exec export an absolute GIT_DIR, and commit hooks an absolute GIT_INDEX_FILE. In a primary checkout, commit hooks export only a relative GIT_INDEX_FILE.

UI, on each client. I ran the dev server with GIT_DIR set to the second repository and a fresh, isolated database, once on main and once on this branch. Every client shows the same synthetic demo-project (a free replay turn). Machine names are blanked out.

Web, before on main: the sidebar and thread details show the other repository's name and branch.

Web before: demo-project labelled example/inherited-other on wrong-repository-branch

Web, after on this branch: the project shows its own name and feature/demo-project.

Web after: demo-project labelled demo-project on feature/demo-project

Desktop, iOS and Android, with the same server runs:

Before (main) After (this branch)
Desktop Desktop before Desktop after
iOS iOS before iOS after
Android Android before Android after

Not checked

  • Windows. Matching the variable names case-insensitively follows gitConfigEnv, but it was not run on Windows.
  • Git versions other than 2.56.

Prior PRs

Generated with Claude Opus 5.5 and GPT-6.1 Terra and GPT-6.1 Sol in T3 Code Nightly

…rited

A T3 server started from a Git hook or `git rebase --exec` in a linked
worktree inherits GIT_DIR and GIT_INDEX_FILE, and every project's Git
commands then read and write that worktree instead of the project.

gitProcessEnv builds the Git child environment at the three Git spawn
sites (GitVcsDriverCore, VcsProcess, RepositoryIdentityResolver): it
unsets inherited repository selectors, then applies the caller's env, so
deliberate private-index and bare-repository overrides still win. The
nested-repository probe from pingdotgg#12181 no longer needs an env of its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Nov 1, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 7ba2d9a

Macroscope's review found this PR approvable — Git commands now ignore inherited repository selectors so each project uses its own repository rather than the server’s launch context. Explicit command overrides and existing bare-repository safeguards are preserved.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Git subprocess environments now remove inherited repository-selection variables before applying caller-provided values. Repository identity resolution, status checks, and checkpoint operations use this environment construction. Regression tests cover inherited selectors that point to another repository and explicit selection of a bare repository.

Changes: Git subprocess environment isolation

Layer / File(s) Summary
Build Git subprocess environments
apps/server/src/vcs/VcsProcess.ts, apps/server/src/vcs/GitVcsDriverCore.ts
gitProcessEnv removes inherited Git repository selectors, applies caller-provided environment values, and adds safe.bareRepository=explicit. VcsProcess.spawn and GitVcsDriverCore use it.
Use isolated environments for repository identity
apps/server/src/project/RepositoryIdentityResolver.ts, apps/server/src/project/RepositoryIdentityResolver.test.ts
Repository-root detection and remote discovery use gitProcessEnv. Tests cover identity resolution when inherited selectors point to another repository and set GIT_CEILING_DIRECTORIES for nested workspace resolution.
Keep checkpoint operations on the requested repository
apps/server/src/vcs/GitVcsDriver.ts, apps/server/src/vcs/GitVcsDriver.test.ts, apps/server/src/vcs/GitVcsDriverCore.test.ts
Checkpoint HEAD checks no longer accept an environment override. Checkpoint commit environment construction no longer copies process.env, and nested-repository recovery no longer builds a sanitized environment. Tests check index and checkpoint-ref behavior when inherited selectors point elsewhere and confirm explicit bare-repository selection.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related PRs

  • pingdotgg/t3code#24105: Preserves GIT_ASKPASS for selected background fetches, which is relevant to preserving caller-provided environment values.
  • pingdotgg/t3code#29259: Handles inherited GIT_OBJECT_DIRECTORY during checkpoint commands, which is also removed by this change.

Suggested reviewers: juliusmarminge, saphid

Merge Risk: Minimal · up to c7a1c

The previously identified repository-selection risk is addressed. No actionable merge-blocking issue remains after normal checks.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the main change: the server no longer lets an inherited Git command environment point project Git state at another repository. The changeset matches this. The gitProcessEnv helper in…
Description check Passed The description follows the template's main sections: Problem, Change, Scope and approval, and Verification. It explains the bug with a reproduction and identifies the affected Git contexts. It descri…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: the server no longer lets an inherited Git command environment point project Git state at another repository. The changeset matches this. The gitProcessEnv helper in VcsProcess.ts unsets inherited repository selectors such as GIT_DIR, GIT_WORK_TREE, and GIT_INDEX_FILE for Git child processes. It is used by GitVcsDriverCore, VcsProcess, and RepositoryIdentityResolver. The title is 97 characters long, which is longer than the concise style the guidelines prefer, but it remains specific and accurate.

Full details: Description check

Explanation

The description follows the template's main sections: Problem, Change, Scope and approval, and Verification. It explains the bug with a reproduction and identifies the affected Git contexts. It describes the fix and the files it touches, and it names the three helper call sites. It cites the prior PRs it extends. The scope section explains why no linked issue exists by invoking the obvious-bug exception. The verification section lists specific failing-then-passing tests, full run results, the four pre-existing failures with their causes, and the UI screenshots for each client. It also states what was not checked, which is Windows and Git versions other than 2.56. The description has a few gaps. The template asks for a triaged issue or maintainer approval, or an explanation of why the fix qualifies as an obvious bug. The author gives that explanation but notes that maintainers must still confirm scope. The description also includes a comment-style note from the template (the title guidance and the model attribution line) that was left in place, which is acceptable. Overall the description is mostly complete.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Usage-based review receipt

Note

This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.

Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between f4eca04 and c7a1c4e.

Files selected for processing: 5

  • apps/server/src/project/RepositoryIdentityResolver.test.ts
  • apps/server/src/vcs/GitVcsDriver.test.ts
  • apps/server/src/vcs/GitVcsDriver.ts
  • apps/server/src/vcs/GitVcsDriverCore.test.ts
  • apps/server/src/vcs/GitVcsDriverCore.ts

Limit details: You’ve used all 10 included reviews currently available.

@maria-rcks

maria-rcks commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by claude-opus-5-5 on behalf of Maria

Merged current main into this branch again without rebasing (c7a1c4e570). Main's HostProcess.Environment refactor (#31218) conflicted with this change in three files:

  • GitVcsDriver.ts: kept this PR's removal of the host-env spread in the checkpoint commit env and of nestedRepoEnv, since gitProcessEnv already clears inherited selectors.
  • GitVcsDriverCore.ts: the status env now spreads HostProcess.Environment (main's side) and then gitProcessEnv (this PR's side).
  • GitVcsDriver.test.ts: kept this PR's inherited-selector checkpoint test, which points GIT_DIR, GIT_WORK_TREE and GIT_INDEX_FILE at another repo.

No other behavior changes. The diff against main is still seven files. Blacksmith vp run check:changed github/main passed: format, lint, knip, GraphQL, three affected typechecks, and all 354 tests across five files.

Earlier history: merged main once before (66763a2be2). f4eca04c94 cleared inherited GIT_CEILING_DIRECTORIES before caller overrides, per review.

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread apps/server/src/vcs/VcsProcess.ts Resolved
# Conflicts:
#	apps/server/src/vcs/GitVcsDriver.test.ts
#	apps/server/src/vcs/GitVcsDriver.ts
#	apps/server/src/vcs/GitVcsDriverCore.ts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants