branch: expose helpers for finding the remote owning a tracking ref
The remote-lookup that setup_tracking() does is useful outside branch.c too; for example, deciding which remote to "git fetch" from given a remote-tracking ref. Move 'struct tracking' to branch.h and add two helpers backed by the existing for_each_remote walk: find_tracking_remote_for_ref() and advise_ambiguous_fetch_refspec(). setup_tracking() uses both. No behavior change. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Harald Nordgren committed
Jun 24, 2026 at 21:54 UTC
f4914a86e11be463819175ce769c3b689bbb9994
2 files changed
+68
-44
branch.c
+52
-44
@@ -20,16 +20,9 @@
20
#include "run-command.h"
21
#include "strmap.h"
22
23
-struct tracking {
24
- struct refspec_item spec;
25
- struct string_list *srcs;
26
- const char *remote;
27
- int matches;
28
-};
29
-
23
struct find_tracked_branch_cb {
24
struct tracking *tracking;
32
- struct string_list ambiguous_remotes;
25
+ struct string_list *ambiguous_remotes;
26
};
27
28
static int find_tracked_branch(struct remote *remote, void *priv)
@@ -45,10 +38,10 @@ static int find_tracked_branch(struct remote *remote, void *priv)
38
break;
39
case 2:
40
/* there are at least two remotes; backfill the first one */
48
- string_list_append(&ftb->ambiguous_remotes, tracking->remote);
41
+ string_list_append(ftb->ambiguous_remotes, tracking->remote);
42
/* fall through */
43
default:
51
- string_list_append(&ftb->ambiguous_remotes, remote->name);
44
+ string_list_append(ftb->ambiguous_remotes, remote->name);
45
free(tracking->spec.src);
46
string_list_clear(tracking->srcs, 0);
47
break;
@@ -59,6 +52,51 @@ static int find_tracked_branch(struct remote *remote, void *priv)
52
return 0;
53
}
54
55
+void find_tracking_remote_for_ref(struct tracking *tracking,
56
+ struct string_list *ambiguous_remotes)
57
+{
58
+ struct find_tracked_branch_cb ftb_cb = {
59
+ .tracking = tracking,
60
+ .ambiguous_remotes = ambiguous_remotes,
61
+ };
62
+
63
+ for_each_remote(find_tracked_branch, &ftb_cb);
64
+}
65
+
66
+void advise_ambiguous_fetch_refspec(const char *dst,
67
+ const struct string_list *ambiguous_remotes)
68
+{
69
+ struct strbuf remotes_advice = STRBUF_INIT;
70
+ struct string_list_item *item;
71
+
72
+ if (!advice_enabled(ADVICE_AMBIGUOUS_FETCH_REFSPEC))
73
+ return;
74
+
75
+ for_each_string_list_item(item, ambiguous_remotes)
76
+ /*
77
+ * TRANSLATORS: This is a line listing a remote with duplicate
78
+ * refspecs in the advice message below. For RTL languages you'll
79
+ * probably want to swap the "%s" and leading " " space around.
80
+ */
81
+ strbuf_addf(&remotes_advice, _(" %s\n"), item->string);
82
+
83
+ /*
84
+ * TRANSLATORS: The second argument is a \n-delimited list of
85
+ * duplicate refspecs, composed above.
86
+ */
87
+ advise(_("There are multiple remotes whose fetch refspecs map to the remote\n"
88
+ "tracking ref '%s':\n"
89
+ "%s"
90
+ "\n"
91
+ "This is typically a configuration error.\n"
92
+ "\n"
93
+ "To support setting up tracking branches, ensure that\n"
94
+ "different remotes' fetch refspecs map into different\n"
95
+ "tracking namespaces."), dst,
96
+ remotes_advice.buf);
97
+ strbuf_release(&remotes_advice);
98
+}
99
+
100
static int should_setup_rebase(const char *origin)
101
{
102
switch (autorebase) {
@@ -254,11 +292,8 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
292
{
293
struct tracking tracking;
294
struct string_list tracking_srcs = STRING_LIST_INIT_DUP;
295
+ struct string_list ambiguous_remotes = STRING_LIST_INIT_DUP;
296
int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
258
- struct find_tracked_branch_cb ftb_cb = {
259
- .tracking = &tracking,
260
- .ambiguous_remotes = STRING_LIST_INIT_DUP,
261
- };
297
298
if (!track)
299
BUG("asked to set up tracking, but tracking is disallowed");
@@ -267,7 +302,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
302
tracking.spec.dst = (char *)orig_ref;
303
tracking.srcs = &tracking_srcs;
304
if (track != BRANCH_TRACK_INHERIT)
270
- for_each_remote(find_tracked_branch, &ftb_cb);
305
+ find_tracking_remote_for_ref(&tracking, &ambiguous_remotes);
306
else if (inherit_tracking(&tracking, orig_ref))
307
goto cleanup;
308
@@ -293,34 +328,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
328
if (tracking.matches > 1) {
329
int status = die_message(_("not tracking: ambiguous information for ref '%s'"),
330
orig_ref);
296
- if (advice_enabled(ADVICE_AMBIGUOUS_FETCH_REFSPEC)) {
297
- struct strbuf remotes_advice = STRBUF_INIT;
298
- struct string_list_item *item;
299
-
300
- for_each_string_list_item(item, &ftb_cb.ambiguous_remotes)
301
- /*
302
- * TRANSLATORS: This is a line listing a remote with duplicate
303
- * refspecs in the advice message below. For RTL languages you'll
304
- * probably want to swap the "%s" and leading " " space around.
305
- */
306
- strbuf_addf(&remotes_advice, _(" %s\n"), item->string);
307
-
308
- /*
309
- * TRANSLATORS: The second argument is a \n-delimited list of
310
- * duplicate refspecs, composed above.
311
- */
312
- advise(_("There are multiple remotes whose fetch refspecs map to the remote\n"
313
- "tracking ref '%s':\n"
314
- "%s"
315
- "\n"
316
- "This is typically a configuration error.\n"
317
- "\n"
318
- "To support setting up tracking branches, ensure that\n"
319
- "different remotes' fetch refspecs map into different\n"
320
- "tracking namespaces."), orig_ref,
321
- remotes_advice.buf);
322
- strbuf_release(&remotes_advice);
323
- }
331
+ advise_ambiguous_fetch_refspec(orig_ref, &ambiguous_remotes);
332
exit(status);
333
}
334
@@ -347,7 +355,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
355
356
cleanup:
357
string_list_clear(&tracking_srcs, 0);
350
- string_list_clear(&ftb_cb.ambiguous_remotes, 0);
358
+ string_list_clear(&ambiguous_remotes, 0);
359
}
360
361
int read_branch_desc(struct strbuf *buf, const char *branch_name)
branch.h
+16
@@ -1,9 +1,25 @@
1
#ifndef BRANCH_H
2
#define BRANCH_H
3
4
+#include "refspec.h"
5
+
6
+struct string_list;
7
struct repository;
8
struct strbuf;
9
10
+struct tracking {
11
+ struct refspec_item spec;
12
+ struct string_list *srcs;
13
+ const char *remote;
14
+ int matches;
15
+};
16
+
17
+void find_tracking_remote_for_ref(struct tracking *tracking,
18
+ struct string_list *ambiguous_remotes);
19
+
20
+void advise_ambiguous_fetch_refspec(const char *dst,
21
+ const struct string_list *ambiguous_remotes);
22
+
23
enum branch_track {
24
BRANCH_TRACK_UNSPECIFIED = -1,
25
BRANCH_TRACK_NEVER = 0,