Repository navigation
fix: sanitize slashes in remote ref when building the checkout dir name - #1486
Merged
mrexox merged 2 commits intoSep 23, 2026
Merged
Conversation
RemoteDirectoryName() appended a remote's ref straight onto the directory name it builds (e.g. "lefthook-test-feat/test-branch" for ref "feat/test-branch"). RemoteFolder() then joins that name onto the remotes directory with filepath.Join, so the slash turns into an actual path separator and lefthook clones into a nested directory instead of the single flat one it expects. This breaks two things: the initial checkout is written one level deeper than lefthook looks for it (scripts and merged configs from the remote can't be found), and the stale-remote cleanup in loadFullConfig only lists the top-level entries of the remotes directory, so it sees just the ref's first path segment, never matches it against the expected full path, and deletes it as stale on every single run — forcing a full reclone every time regardless of refetch_frequency. Replace "/" with "-" in the ref before appending it, keeping the result a single path component. Fixes evilmartians#1478
Replacing every "/" with "-" let distinct refs alias onto the same checkout directory (e.g. "feat/a-b" and "feat/a/b" both sanitized to "feat-a-b"), letting synchronizing one ref silently overwrite the checkout and cached state used by the other. Escape literal "-" to "--" before mapping "/" to "-": every single "-" in the result now unambiguously came from a "/", and every "--" from a literal "-". Also switches the test to the table-driven map[string]struct + testify/assert style used elsewhere in this package, and adds a regression test asserting a set of refs that previously collided now sanitize to distinct names.
mrexox
approved these changes
Sep 23, 2026
1 task
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.
RemoteDirectoryName() appended a remote's ref straight onto the directory name it builds (e.g. "lefthook-test-feat/test-branch" for ref "feat/test-branch"). RemoteFolder() then joins that name onto the remotes directory with filepath.Join, so the slash turns into an actual path separator and lefthook clones into a nested directory instead of the single flat one it expects.
This breaks two things: the initial checkout is written one level deeper than lefthook looks for it (scripts and merged configs from the remote can't be found), and the stale-remote cleanup in loadFullConfig only lists the top-level entries of the remotes directory, so it sees just the ref's first path segment, never matches it against the expected full path, and deletes it as stale on every single run -- forcing a full reclone every time regardless of refetch_frequency.
Replace "/" with "-" in the ref before appending it, keeping the result a single path component. Escape literal "-" to "--" first so the mapping can't collide two distinct refs onto the same directory (e.g. "feat/a-b" and "feat/a/b" would otherwise both sanitize to "feat-a-b").
Fixes #1478
Context
Remote branches whose ref contains a slash (e.g. "feat/x") broke checkout entirely and forced a full reclone on every single run.
Changes
internal/git/remote.go: RemoteDirectoryName() now escapes literal "-" to "--" before mapping "/" to "-", making the sanitized name collision-free. internal/git/remote_test.go: switched to the table-driven map[string]struct + testify/assert style used elsewhere in this package, and added a regression test proving previously-colliding refs now sanitize to distinct names.
Confidence Score: 4/5
The PR is not yet safe to merge because distinct valid refs can still resolve to the same remote checkout directory.
Escaping hyphens as doubled hyphens before converting slashes to hyphens remains ambiguous: refs such as
-/and/-both produce the same suffix, preserving the checkout and cache aliasing reported in the earlier thread.Files Needing Attention: internal/git/remote.go
Reviews (2): Last reviewed commit: "fix: make remote ref sanitization collis..." | Re-trigger Greptile