Repository navigation
Give a workspace the git identity of its repository - #28
Merged
Merged
Conversation
DevPod gave the dev container the identity from `git config --global`, which only reads ~/.gitconfig and doesn't follow its include or includeIf directives. A work identity kept in an includeIf block was ignored, so workspaces committed with the global (often personal) email. `devpod up` now resolves the identity where the workspace comes from (its local folder, or the directory `devpod up` runs in) with `git -C <dir> config`, which includes the repository's config and the matching includes, falling back to `git config --global --includes`. It saves the identity with the workspace when it has none yet, so later connections from any directory use the same one, and the tunnel server serves it to the container. The new `--git-user-name` and `--git-user-email` options of `devpod up` set it explicitly. The container still only fills in a name or email it doesn't have yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tests wrote Windows paths into git config files, where git takes a backslash as an escape character and rejected the file. Write them with forward slashes, which git accepts and gitdir patterns need, and match the gitdir case insensitively, like Windows paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review findings on the git identity change: - `devpod up` saved whatever identity it found, also outside any repository (e.g. from the desktop app), and never looked it up again, so a workspace could keep a personal or outdated identity for good. It now only saves a value given with --git-user-name/--git-user-email or found in the workspace's repository. Otherwise the container gets the current global identity when it connects. An empty flag value removes the saved one. - Check that the directory is in a repository git can use with `git rev-parse`, and log why not at debug level, so a repository git doesn't trust (safe.directory) no longer silently gives the global identity. - SetUser ran `git config` through a shell with the value in double quotes, so a name with a quote or `$` broke the container's credentials server. It now runs git directly on the same config file GetUser reads. - `devpod up` passes the directory it runs in to Resolve instead of Resolve reading the process's working directory. - Keep the tests from finding a repository that the temporary directory is in, and cover the new cases. - Docs and CHANGELOG: existing containers keep their identity until `devpod up --recreate`, the container only checks the user's ~/.gitconfig, and safe.directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
DevPod gives the dev container a git identity by asking the host, which ran
git config --global user.name/user.email.--globalreads only~/.gitconfigand doesn't followinclude/includeIf, so a work identity kept in anincludeIf "gitdir:~/work/"block was ignored and workspaces committed (and pushed) with the global, often personal, email, even whendevpod upran inside a work repository.Fix
gitcredentials.GetRepositoryUser(dir)checks thatdiris in a repository git can use (git -C <dir> rev-parse --git-dir), then runsgit -C <dir> config user.name|user.email(no--global). That includes the repository's config and matchinginclude/includeIfdirectives.GetGlobalUser()runsgit config --global --includes.devpod uplooks the identity up in the repository the workspace comes from: its local folder, or the directorydevpod upruns in, whichcmd/up.gopasses toworkspace.Resolve. It saves it inworkspace.jsonasgitUser, before the workspace client is created. The container asks for the identity on everydevpod ssh/IDE connection, which can run from any directory, so it has to be saved. A saved identity isn't looked up again, so a laterdevpod up wsfrom elsewhere doesn't change it.safe.directory; logged at debug level), nothing is saved. The tunnel server then serves the current global identity (with includes) when the container connects, so it doesn't go stale.devpod up --git-user-name/--git-user-emailset it explicitly (e.g.me+devpod@company.com) and are saved with the workspace. An empty value removes the saved one, so DevPod looks it up again.configureGitUserLocally) still only fills in a name or email that the user's~/.gitconfigdoesn't have, so a devcontainer's own start command can still set the identity. Its check now follows includes.SetUserused to rungit configthroughsh -c/su -cwith the value in double quotes. Since the new flag passes values straight to it, a name with",$or a backtick broke the credentials server. It now runs git directly on the same fileGetUserreads (then chowns it, likeConfigureHelper).devpod builddoesn't connect to the container, so it doesn't look up an identity.The protocol between CLI and agent is unchanged. The new
gitUserfield isomitempty, and older agents ignore it.Docs: a new "Git identity" section in
developing-in-workspaces/credentials.mdx, plus CHANGELOG entries.Testing
includeIfin a repository and a subdirectory of itSetUser/GetUserround trip with quotes,$and backticksGIT_CEILING_DIRECTORIES, so they still pass withTMPDIRinside a repository.go vet ./...,go test ./pkg/... ./cmd/...and golangci-lint v1.60.1 (CI flags) all pass.me@personal.com,includeIfgivingme@company.com):me@company.comme@personal.com--git-user-name 'Ann "Nan $HOME' --recreate→ container has the literal name--git-user-name ''→ saved name removedNotes
devpod up --recreateapplies a new one.devpod ssh --commandcan run before the credentials server has set the identity.🤖 Generated with Claude Code