Skip to content

Commit 5f611f8

Browse files
ferdinandybttaylorr
authored andcommitted
fetch set_head: handle mirrored bare repositories
When adding a remote to bare repository with "git remote add --mirror", running fetch will fail to update HEAD to the remote's HEAD, since it does not know how to handle bare repositories. On the other hand HEAD already has content, since "git init --bare" has already set HEAD to whatever is the default branch set for the user. Unless this - by chance - is the same as the remote's HEAD, HEAD will be pointing to a bad symref. Teach set_head to handle bare repositories, by overwriting HEAD so it mirrors the remote's HEAD. Note, that in this case overriding the local HEAD reference is necessary, since HEAD will exist before fetch can be run, but this should not be an issue, since the whole purpose of --mirror is to be an exact mirror of the remote, so following any changes to HEAD makes sense. Also note, that although "git remote set-head" also fails when trying to update the remote's locally tracked HEAD in a mirrored bare repository, the usage of the command does not make much sense after this patch: fetch will update the remote HEAD correctly, and setting it manually to something else is antithetical to the concept of mirroring. Signed-off-by: Bence Ferdinandy <[email protected]> Signed-off-by: Taylor Blau <[email protected]>
1 parent ac92804 commit 5f611f8

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

builtin/fetch.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,14 +1632,22 @@ static int set_head(const struct ref *remote_refs)
16321632
else
16331633
head_name = xstrdup(heads.items[0].string);
16341634
if (head_name) {
1635-
strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
1636-
strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
1635+
int is_bare = is_bare_repository();
1636+
if (is_bare) {
1637+
strbuf_addstr(&b_head, "HEAD");
1638+
strbuf_addf(&b_remote_head, "refs/heads/%s", head_name);
1639+
} else {
1640+
strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
1641+
strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
1642+
}
16371643
/* make sure it's valid */
1638-
if (!refs_ref_exists(refs, b_remote_head.buf))
1644+
if (!is_bare && !refs_ref_exists(refs, b_remote_head.buf)) {
16391645
result = 1;
1646+
}
16401647
else if (refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
1641-
"fetch", &b_local_head, 1))
1648+
"fetch", &b_local_head, !is_bare)) {
16421649
result = 1;
1650+
}
16431651
else
16441652
report_set_head(remote, head_name, &b_local_head);
16451653

t/t5505-remote.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,16 @@ test_expect_success 'add --mirror && prune' '
545545
)
546546
'
547547

548+
test_expect_success 'add --mirror setting HEAD' '
549+
mkdir headmirror &&
550+
(
551+
cd headmirror &&
552+
git init --bare -b notmain &&
553+
git remote add --mirror -f origin ../one &&
554+
test "$(git symbolic-ref HEAD)" = "refs/heads/main"
555+
)
556+
'
557+
548558
test_expect_success 'add --mirror=fetch' '
549559
mkdir mirror-fetch &&
550560
git init -b main mirror-fetch/parent &&

0 commit comments

Comments
 (0)