Skip to content

Commit b1b713f

Browse files
ferdinandybgitster
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: Junio C Hamano <[email protected]>
1 parent 3f763dd commit b1b713f

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

builtin/fetch.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,7 @@ static const char *strip_refshead(const char *name){
15841584

15851585
static int set_head(const struct ref *remote_refs)
15861586
{
1587-
int result = 0;
1587+
int result = 0, is_bare;
15881588
struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT;
15891589
const char *remote = gtransport->remote->name;
15901590
char *head_name = NULL;
@@ -1616,15 +1616,21 @@ static int set_head(const struct ref *remote_refs)
16161616

16171617
if (!head_name)
16181618
goto cleanup;
1619-
strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
1620-
strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
1619+
is_bare = is_bare_repository();
1620+
if (is_bare) {
1621+
strbuf_addstr(&b_head, "HEAD");
1622+
strbuf_addf(&b_remote_head, "refs/heads/%s", head_name);
1623+
} else {
1624+
strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
1625+
strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
1626+
}
16211627
/* make sure it's valid */
1622-
if (!refs_ref_exists(refs, b_remote_head.buf)) {
1628+
if (!is_bare && !refs_ref_exists(refs, b_remote_head.buf)) {
16231629
result = 1;
16241630
goto cleanup;
16251631
}
16261632
if (refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
1627-
"fetch", NULL, 1))
1633+
"fetch", NULL, !is_bare))
16281634
result = 1;
16291635

16301636
cleanup:

t/t5505-remote.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,16 @@ test_expect_success 'add --mirror && prune' '
569569
)
570570
'
571571

572+
test_expect_success 'add --mirror setting HEAD' '
573+
mkdir headmirror &&
574+
(
575+
cd headmirror &&
576+
git init --bare -b notmain &&
577+
git remote add --mirror -f origin ../one &&
578+
test "$(git symbolic-ref HEAD)" = "refs/heads/main"
579+
)
580+
'
581+
572582
test_expect_success 'add --mirror=fetch' '
573583
mkdir mirror-fetch &&
574584
git init -b main mirror-fetch/parent &&

0 commit comments

Comments
 (0)