From: Jon Simons Date: Fri, 09 Oct 2026 19:29:41 GMT Subject: [PATCH 03/15] t5510: document fetch with "./"-prefixed branch..merge Message-ID: <20261009192953.81794-4-jon@jonsimons.org> In-Reply-To: <20261009192953.81794-1-jon@jonsimons.org> refname_match() formats each candidate through mkpath(), which strips a leading "./", so a branch..merge value of "./refs/heads/main" matches "refs/heads/main" in both places that fetch compares them: - branch_merge_matches() when marking fetched refs for merge in FETCH_HEAD - find_ref_by_name_abbrev() when the merge source is not covered by the fetch refspec and is looked up amongst the remote advertised refs Only a hand-edited config reaches these paths: clone, branch --set-upstream-to, fetch --set-upstream, and push -u write only names that have passed check_refname_format(), which rejects a leading "./". Add two fetch tests asserting that such a "./"-prefixed value does not match for these cases. Both are test_expect_failure because the name matches today: - The default fetch refspec should not match "./refs/heads/main" with fetched "refs/heads/main" and mark the ref for merge. - A protocol v0 fetch with refspec that omits "refs/heads/main" should not match "./refs/heads/main" against the remote advertised "refs/heads/main". An upcoming commit stops using mkpath() in refname_match(), at which point the tests are toggled to test_expect_success. Signed-off-by: Jon Simons --- t/t5510-fetch.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 300bd5396d..0303784b1f 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -1074,6 +1074,50 @@ test_expect_success 'LHS of refspec follows ref disambiguation rules' ' ) ' +test_expect_failure 'fetch with "./"-prefixed branch..merge does not mark any ref for merge' ' + mkdir dotslash-merge-default-refspec && + ( + cd dotslash-merge-default-refspec && + git init -b main server && + test_commit -C server one && + git -C server branch other && + test_commit -C server two && + + # The bogus ./refs/heads/main should not match the remote refs/heads/main. + git clone server client && + git -C client config branch.main.merge ./refs/heads/main && + git -C client fetch && + { + echo "$(git -C server rev-parse main) not-for-merge" && + echo "$(git -C server rev-parse other) not-for-merge" + } >expect && + cut -f -2 client/.git/FETCH_HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_failure 'fetch protocol v0 with "./"-prefixed branch..merge does not match any remote ref' ' + mkdir dotslash-merge-fetch-protocol-v0 && + ( + cd dotslash-merge-fetch-protocol-v0 && + git init -b main server && + test_commit -C server one && + git -C server branch other && + test_commit -C server two && + + # Omit refs/heads/main from the fetch refspec so that the merge + # source is instead looked up among the refs the remote advertised. + git clone server client-v0 && + git -C client-v0 config remote.origin.fetch \ + +refs/heads/other:refs/remotes/origin/other && + git -C client-v0 config branch.main.merge ./refs/heads/main && + git -C client-v0 -c protocol.version=0 fetch && + echo "$(git -C server rev-parse other) not-for-merge" >expect && + cut -f -2 client-v0/.git/FETCH_HEAD >actual && + test_cmp expect actual + ) +' + test_expect_success 'fetch.writeCommitGraph' ' git clone three write && ( -- 2.55.0