git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v10 8/8] fetch set_head: handle mirrored bare repositories

From
Bence Ferdinandy <bence@ferdinandy.com>
Date
Oct 21, 2024, 13:37 UTC
Message-ID
<20241021134354.705636-9-bence@ferdinandy.com>
In-Reply-To
<20241021134354.705636-1-bence@ferdinandy.com>
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 <bence@ferdinandy.com>
---
Notes:
    v10: - new patch
         - handles the issue discovered in
           https://lore.kernel.org/git/D4ZAELFWJMKN.S88LJ6YK31LZ@ferdinandy.com/T/
 builtin/fetch.c   | 16 ++++++++++++----
 t/t5505-remote.sh | 10 ++++++++++
 2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 31edc67447..249556c9c6 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1632,14 +1632,22 @@ static int set_head(const struct ref *remote_refs)
 	else
 		head_name = xstrdup(heads.items[0].string);
 	if (head_name) {
-		strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
-		strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
+		int is_bare = is_bare_repository();
+		if (is_bare) {
+			strbuf_addstr(&b_head, "HEAD");
+			strbuf_addf(&b_remote_head, "refs/heads/%s", head_name);
+		} else {
+			strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
+			strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
+		}
 		/* make sure it's valid */
-		if (!refs_ref_exists(refs, b_remote_head.buf))
+		if (!is_bare && !refs_ref_exists(refs, b_remote_head.buf)) {
 			result = 1;
+		}
 		else if (refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
-					"fetch", &b_local_head, 1))
+					"fetch", &b_local_head, !is_bare)) {
 			result = 1;
+		}
 		else
 			report_set_head(remote, head_name, &b_local_head);
 
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 4990d00209..dfa78f3e8d 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -545,6 +545,16 @@ test_expect_success 'add --mirror && prune' '
 	)
 '
 
+test_expect_success 'add --mirror setting HEAD' '
+	mkdir headmirror &&
+	(
+		cd headmirror &&
+		git init --bare -b notmain &&
+		git remote add --mirror -f origin ../one &&
+		test "$(git symbolic-ref HEAD)" = "refs/heads/main"
+	)
+'
+
 test_expect_success 'add --mirror=fetch' '
 	mkdir mirror-fetch &&
 	git init -b main mirror-fetch/parent &&
-- 
2.47.0.94.g8861098b6d
Previous: Bence FerdinandyNext: Bence Ferdinandy
Message 8 of 15 in “set-head/fetch remote/HEAD updates”
  1. 0/8 set-head/fetch remote/HEAD updatesBence Ferdinandy, Oct 21, 2024
  2. 1/8 t/t5505-remote: set default branch to mainBence Ferdinandy, Oct 21, 2024
  3. 2/8 refs: atomically record overwritten ref in update_symrefBence Ferdinandy, Oct 21, 2024
  4. 3/8 remote set-head: refactor for readabilityBence Ferdinandy, Oct 21, 2024
  5. 4/8 remote set-head: better output for --autoBence Ferdinandy, Oct 21, 2024
  6. 5/8 refs: add TRANSACTION_CREATE_EXISTS errorBence Ferdinandy, Oct 21, 2024
  7. 6/8 refs: add create_only option to refs_update_symref_extendedBence Ferdinandy, Oct 21, 2024
  8. 8/8 fetch set_head: handle mirrored bare repositoriesBence Ferdinandy, Oct 21, 2024
  9. 7/8 fetch: set remote/HEAD if it does not existBence Ferdinandy, Oct 21, 2024
  10. Taylor BlauOct 21, 2024
  11. Bence FerdinandyOct 21, 2024
  12. Taylor BlauOct 22, 2024
  13. Bence FerdinandyOct 22, 2024
  14. Taylor BlauOct 22, 2024
  15. Bence FerdinandyOct 22, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.