Skip to content

storage: filesystem, Add support for worktreeConfig extension#1877

Merged
pjbgf merged 7 commits intomainfrom
worktree-config
Mar 3, 2026
Merged

storage: filesystem, Add support for worktreeConfig extension#1877
pjbgf merged 7 commits intomainfrom
worktree-config

Conversation

@pjbgf
Copy link
Member

@pjbgf pjbgf commented Mar 2, 2026

Previous to #1850, go-git was oblivious to Git extensions, which meant that at times it would try to handle repositories where the underlying feature was not fully supported.

An example of that being worktreeConfig, meaning that any worktree-specific config were being ignored.

This PR adds that support to storage/filesystem, resulting into worktree configs being overlayed over the local config, providing parity with upstream Git.

Other changes were required in order to support this feature properly:

  • Fix of config.Merge bug whereby a nil or empty map resulted in incorrect merge. For example, if local config had remotes and worktree didn't, the resulting merge would not contain any remotes.
  • Removal of PlainOpenOptions.EnableDotGitCommonDir, making commondir detection unconditional, abstracting this complexity away from callers.
  • Update SetConfig so that it can distinguish delta changes and save them to the worktree-specific config only.

Follow-up from #1850 and #1808.
Relates to #1812.

Copilot AI review requested due to automatic review settings March 2, 2026 15:14
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds extensions.worktreeConfig support to the filesystem-backed storage so linked worktrees can read and overlay per-worktree config.worktree onto the common .git/config, aligning behavior with upstream Git worktree configuration.

Changes:

  • Overlay .git/worktrees/<name>/config.worktree onto the base repo config when extensions.worktreeConfig=true (filesystem storage only).
  • Fix config.Merge behavior for map fields so nil/empty maps don’t wipe previously-merged entries.
  • Remove PlainOpenOptions.EnableDotGitCommonDir and make commondir detection unconditional.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
storage/filesystem/config.go Reads config.worktree (when enabled) and merges it into the returned config.
config/config.go Adds Extensions.WorktreeConfig, improves map merge semantics, and marshals/unmarshals the new extension key.
storage/filesystem/storage.go Declares filesystem storage support for worktreeconfig extension.
storage/filesystem/dotgit/dotgit.go Adds helpers to open/create config.worktree.
repository.go Makes commondir detection unconditional; improves nil options handling and not-exist checks.
options.go Removes EnableDotGitCommonDir from PlainOpenOptions.
repository_extensions.go Normalizes v0-valid extension keys to lowercase and documents the requirement.
config/config_test.go Expands merge tests to cover map merge behavior and new extension field.
x/plumbing/worktree/worktree_test.go Adds coverage for reading overlaid config.worktree in linked worktrees.
worktree_test.go Updates linked-worktree open tests to reflect new PlainOpen behavior.
COMPATIBILITY.md Documents worktreeConfig and config --worktree behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pjbgf added 4 commits March 3, 2026 13:40
The extension matching is case insensitive, so keep references to them
in lower case format, as that is what is used during the matching
process.

Signed-off-by: Paulo Gomes <[email protected]>
EnableDotGitCommonDir was an opt-in flag to detect and honor the
commondir mechanism used by Git linked worktrees.

Requiring callers to explicitly enable this behavior is both surprising
and error-prone. Consumers of PlainOpen should not need to know whether
a repository is a primary working tree or a linked worktree, nor whether
it relies on a shared common directory.

This distinction directly impacts core repository semantics, including
object resolution and configuration lookup. Leaving it opt-in can lead
to subtle and inconsistent behavior.

Making commondir detection unconditional, abstracting this complexity
away from callers, ensures a consistent and predictable repository
handling which aligns with upstream Git.

Signed-off-by: Paulo Gomes <[email protected]>
Previous to #1850, go-git was oblivious to Git extensions, which
meant that at times it would try to handle repositories where the
underlying feature was not fully supported.

An example of that being worktreeConfig, meaning that any worktree
specific config were being ignored.

This commit adds that support to storage/filesystem, resulting into
worktree configs being overlayed the local config, providing upstream
parity with upstream Git.

References:
- https://git-scm.com/docs/git-worktree#_configuration_file

Signed-off-by: Paulo Gomes <[email protected]>
@pjbgf pjbgf force-pushed the worktree-config branch from 4170f46 to 524f02e Compare March 3, 2026 14:37
pjbgf added 3 commits March 3, 2026 15:44
The internal merge helper had no case for reflect.Map, so map-typed
fields (Remotes, Branches, Submodules, URLs) fell through to the default
branch which called df.Set(sf), replacing the destination map wholesale.

This caused two bugs:

* An empty but non-nil source map (as produced by NewConfig) would
  overwrite a populated destination map, silently discarding all
  accumulated entries.

* A non-empty source map would replace the destination map entirely,
  dropping any destination keys absent from the source instead of
  merging them together.

Add a reflect.Map case that skips empty source maps unchanged and
otherwise copies entries one-by-one, so destination keys not present
in the source are preserved and source entries override same-key
destination entries.

Add table-driven tests covering nil source map, empty source map,
disjoint key sets, and same-key override.

Signed-off-by: Paulo Gomes <[email protected]>
When the worktreeConfig extension is active and a config.worktree file
already exists, only the delta — options whose values are absent from or
differ from the base config — is written to config.worktree. The base
config is left untouched in that case.

This mirrors the behaviour of 'git config --worktree' to some extend, and
enable the use case whereby worktree-specific overrides live in config.worktree
while shared settings remain in the common config.

Signed-off-by: Paulo Gomes <[email protected]>
@pjbgf pjbgf force-pushed the worktree-config branch from 524f02e to ca02134 Compare March 3, 2026 16:06
@pjbgf pjbgf merged commit ee63665 into main Mar 3, 2026
16 checks passed
@pjbgf pjbgf deleted the worktree-config branch March 3, 2026 22:11
charithe added a commit to charithe/cerbos that referenced this pull request Mar 9, 2026
v5.17.0 includes strict extension checks (go-git/go-git#1861) but it
causes problems for `worktreeconfig` because it wasn't added to the
supported extension list until go-git/go-git#1877. Until it's released,
we need to keep the version back.

Signed-off-by: Charith Ellawala <[email protected]>
charithe added a commit to cerbos/cerbos that referenced this pull request Mar 9, 2026
v5.17.0 includes strict extension checks (go-git/go-git#1861) but it
causes problems for `worktreeconfig` because it wasn't added to the
supported extension list until go-git/go-git#1877. Until it's released,
we need to keep the version back.

Signed-off-by: Charith Ellawala <[email protected]>

Signed-off-by: Charith Ellawala <[email protected]>
haines pushed a commit to haines/cerbos that referenced this pull request Mar 16, 2026
v5.17.0 includes strict extension checks (go-git/go-git#1861) but it
causes problems for `worktreeconfig` because it wasn't added to the
supported extension list until go-git/go-git#1877. Until it's released,
we need to keep the version back.

Signed-off-by: Charith Ellawala <[email protected]>
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.

2 participants