Skip to content

Mirror branches and tags with slashes in their name - #30

Merged
ocean90 merged 1 commit into
masterfrom
fix/mirror-nested-refs
Jul 21, 2026
Merged

Mirror branches and tags with slashes in their name#30
ocean90 merged 1 commit into
masterfrom
fix/mirror-nested-refs

Conversation

@ocean90

@ocean90 ocean90 commented Jul 21, 2026

Copy link
Copy Markdown
Member

Problem

1.3.0 (#28) stopped mirroring branches and tags whose names contain a slash, e.g. feature/foo or release/1.0.0. Reported in #27.

The whitelist step excluded the heads/tags namespaces with a glob:

git for-each-ref --format 'delete %(refname)' \
	--exclude 'refs/heads/*' --exclude 'refs/tags/*' refs | git update-ref --stdin

git for-each-ref matches patterns path-aware: * does not cross a /. So refs/heads/* matches refs/heads/main but not refs/heads/feature/foo. The nested ref was therefore not excluded, got deleted before the push, and silently disappeared from the mirror (no error — the push still succeeded).

Fix

Exclude the bare namespaces without a glob. A pattern without wildcards is matched literally "completely or from the beginning up to a slash", i.e. it matches the whole hierarchy including nested refs:

git for-each-ref --format 'delete %(refname)' \
	--exclude refs/heads --exclude refs/tags refs | git update-ref --stdin

Test

The existing CI test only used single-level refs (main, v1), so it passed against the buggy script — the bug was invisible. This PR adds a nested branch (feature/foo) and tag (release/1.0.0) to the fixture and asserts the exact destination ref set, so a regression here fails the job.

Verified locally: the hardened test passes on this fix and fails on 1.3.0.

Fixes #27.

1.3.0 excluded the heads/tags namespaces with a glob (`refs/heads/*`), but
git for-each-ref matches patterns path-aware: `*` does not cross a `/`, so a
ref like `refs/heads/feature/foo` was not excluded and got deleted before the
push — silently dropping any branch or tag with a slash in its name.

Drop the glob and exclude the bare namespaces (`refs/heads`, `refs/tags`),
which match the whole hierarchy including nested refs.

The CI test is extended with a nested branch and tag to cover this: it would
pass against the buggy script (which drops them without error) only because
the old assertion just checked for the single-level refs.
@ocean90
ocean90 merged commit 9082f94 into master Jul 21, 2026
2 checks passed
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