@@ -49,34 +49,64 @@ static int should_setup_rebase(const char *origin)
49
49
return 0 ;
50
50
}
51
51
52
- static const char tracking_advice [] =
53
- N_ ("\n"
54
- "After fixing the error cause you may try to fix up\n"
55
- "the remote tracking information by invoking\n"
56
- "\"git branch --set-upstream-to=%s%s%s\"." );
57
-
58
- int install_branch_config (int flag , const char * local , const char * origin , const char * remote )
52
+ /**
53
+ * Install upstream tracking configuration for a branch; specifically, add
54
+ * `branch.<name>.remote` and `branch.<name>.merge` entries.
55
+ *
56
+ * `flag` contains integer flags for options; currently only
57
+ * BRANCH_CONFIG_VERBOSE is checked.
58
+ *
59
+ * `local` is the name of the branch whose configuration we're installing.
60
+ *
61
+ * `origin` is the name of the remote owning the upstream branches. NULL means
62
+ * the upstream branches are local to this repo.
63
+ *
64
+ * `remotes` is a list of refs that are upstream of local
65
+ */
66
+ static int install_branch_config_multiple_remotes (int flag , const char * local ,
67
+ const char * origin , struct string_list * remotes )
59
68
{
60
69
const char * shortname = NULL ;
61
70
struct strbuf key = STRBUF_INIT ;
71
+ struct string_list_item * item ;
62
72
int rebasing = should_setup_rebase (origin );
63
73
64
- if (skip_prefix (remote , "refs/heads/" , & shortname )
65
- && !strcmp (local , shortname )
66
- && !origin ) {
67
- warning (_ ("Not setting branch %s as its own upstream." ),
68
- local );
69
- return 0 ;
70
- }
74
+ if (!remotes -> nr )
75
+ BUG ("must provide at least one remote for branch config" );
76
+ if (rebasing && remotes -> nr > 1 )
77
+ die (_ ("cannot inherit upstream tracking configuration of "
78
+ "multiple refs when rebasing is requested" ));
79
+
80
+ /*
81
+ * If the new branch is trying to track itself, something has gone
82
+ * wrong. Warn the user and don't proceed any further.
83
+ */
84
+ if (!origin )
85
+ for_each_string_list_item (item , remotes )
86
+ if (skip_prefix (item -> string , "refs/heads/" , & shortname )
87
+ && !strcmp (local , shortname )) {
88
+ warning (_ ("not setting branch '%s' as its own upstream." ),
89
+ local );
90
+ return 0 ;
91
+ }
71
92
72
93
strbuf_addf (& key , "branch.%s.remote" , local );
73
94
if (git_config_set_gently (key .buf , origin ? origin : "." ) < 0 )
74
95
goto out_err ;
75
96
76
97
strbuf_reset (& key );
77
98
strbuf_addf (& key , "branch.%s.merge" , local );
78
- if (git_config_set_gently (key .buf , remote ) < 0 )
99
+ /*
100
+ * We want to overwrite any existing config with all the branches in
101
+ * "remotes". Override any existing config, then write our branches. If
102
+ * more than one is provided, use CONFIG_REGEX_NONE to preserve what
103
+ * we've written so far.
104
+ */
105
+ if (git_config_set_gently (key .buf , NULL ) < 0 )
79
106
goto out_err ;
107
+ for_each_string_list_item (item , remotes )
108
+ if (git_config_set_multivar_gently (key .buf , item -> string , CONFIG_REGEX_NONE , 0 ) < 0 )
109
+ goto out_err ;
80
110
81
111
if (rebasing ) {
82
112
strbuf_reset (& key );
@@ -87,29 +117,40 @@ int install_branch_config(int flag, const char *local, const char *origin, const
87
117
strbuf_release (& key );
88
118
89
119
if (flag & BRANCH_CONFIG_VERBOSE ) {
90
- if (shortname ) {
91
- if (origin )
92
- printf_ln (rebasing ?
93
- _ ("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing." ) :
94
- _ ("Branch '%s' set up to track remote branch '%s' from '%s'." ),
95
- local , shortname , origin );
96
- else
97
- printf_ln (rebasing ?
98
- _ ("Branch '%s' set up to track local branch '%s' by rebasing." ) :
99
- _ ("Branch '%s' set up to track local branch '%s'." ),
100
- local , shortname );
120
+ struct strbuf tmp_ref_name = STRBUF_INIT ;
121
+ struct string_list friendly_ref_names = STRING_LIST_INIT_DUP ;
122
+
123
+ for_each_string_list_item (item , remotes ) {
124
+ shortname = item -> string ;
125
+ skip_prefix (shortname , "refs/heads/" , & shortname );
126
+ if (origin ) {
127
+ strbuf_addf (& tmp_ref_name , "%s/%s" ,
128
+ origin , shortname );
129
+ string_list_append_nodup (
130
+ & friendly_ref_names ,
131
+ strbuf_detach (& tmp_ref_name , NULL ));
132
+ } else {
133
+ string_list_append (
134
+ & friendly_ref_names , shortname );
135
+ }
136
+ }
137
+
138
+ if (remotes -> nr == 1 ) {
139
+ /*
140
+ * Rebasing is only allowed in the case of a single
141
+ * upstream branch.
142
+ */
143
+ printf_ln (rebasing ?
144
+ _ ("branch '%s' set up to track '%s' by rebasing." ) :
145
+ _ ("branch '%s' set up to track '%s'." ),
146
+ local , friendly_ref_names .items [0 ].string );
101
147
} else {
102
- if (origin )
103
- printf_ln (rebasing ?
104
- _ ("Branch '%s' set up to track remote ref '%s' by rebasing." ) :
105
- _ ("Branch '%s' set up to track remote ref '%s'." ),
106
- local , remote );
107
- else
108
- printf_ln (rebasing ?
109
- _ ("Branch '%s' set up to track local ref '%s' by rebasing." ) :
110
- _ ("Branch '%s' set up to track local ref '%s'." ),
111
- local , remote );
148
+ printf_ln (_ ("branch '%s' set up to track:" ), local );
149
+ for_each_string_list_item (item , & friendly_ref_names )
150
+ printf_ln (" %s" , item -> string );
112
151
}
152
+
153
+ string_list_clear (& friendly_ref_names , 0 );
113
154
}
114
155
115
156
return 0 ;
@@ -118,14 +159,36 @@ int install_branch_config(int flag, const char *local, const char *origin, const
118
159
strbuf_release (& key );
119
160
error (_ ("Unable to write upstream branch configuration" ));
120
161
121
- advise (_ (tracking_advice ),
122
- origin ? origin : "" ,
123
- origin ? "/" : "" ,
124
- shortname ? shortname : remote );
162
+ advise (_ ("\nAfter fixing the error cause you may try to fix up\n"
163
+ "the remote tracking information by invoking:" ));
164
+ if (remotes -> nr == 1 )
165
+ advise (" git branch --set-upstream-to=%s%s%s" ,
166
+ origin ? origin : "" ,
167
+ origin ? "/" : "" ,
168
+ remotes -> items [0 ].string );
169
+ else {
170
+ advise (" git config --add branch.\"%s\".remote %s" ,
171
+ local , origin ? origin : "." );
172
+ for_each_string_list_item (item , remotes )
173
+ advise (" git config --add branch.\"%s\".merge %s" ,
174
+ local , item -> string );
175
+ }
125
176
126
177
return -1 ;
127
178
}
128
179
180
+ int install_branch_config (int flag , const char * local , const char * origin ,
181
+ const char * remote )
182
+ {
183
+ int ret ;
184
+ struct string_list remotes = STRING_LIST_INIT_DUP ;
185
+
186
+ string_list_append (& remotes , remote );
187
+ ret = install_branch_config_multiple_remotes (flag , local , origin , & remotes );
188
+ string_list_clear (& remotes , 0 );
189
+ return ret ;
190
+ }
191
+
129
192
/*
130
193
* This is called when new_ref is branched off of orig_ref, and tries
131
194
* to infer the settings for branch.<new_ref>.{remote,merge} from the
0 commit comments