Skip to content

Commit 9e2b700

Browse files
ferdinandybgitster
authored andcommitted
fetch set_head: add warn-if-not-$branch option
Currently if we want to have a remote/HEAD locally that is different from the one on the remote, but we still want to get a warning if remote changes HEAD, our only option is to have an indiscriminate warning with "follow_remote_head" set to "warn". Add a new option "warn-if-not-$branch", where $branch is a branch name we do not wish to get a warning about. If the remote HEAD is $branch do not warn, otherwise, behave as "warn". E.g. let's assume, that our remote origin has HEAD set to "master", but locally we have "git remote set-head origin seen". Setting 'remote.origin.followRemoteHEAD = "warn"' will always print a warning, even though the remote has not changed HEAD from "master". Setting 'remote.origin.followRemoteHEAD = "warn-if-not-master" will squelch the warning message, unless the remote changes HEAD from "master". Note, that should the remote change HEAD to "seen" (which we have locally), there will still be no warning. Improve the advice message in report_set_head to also include silencing the warning message with "warn-if-not-$branch". Signed-off-by: Bence Ferdinandy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ad739f5 commit 9e2b700

File tree

5 files changed

+66
-10
lines changed

5 files changed

+66
-10
lines changed

Documentation/config/remote.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,12 @@ remote.<name>.followRemoteHEAD::
106106
How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`.
107107
The default value is "create", which will create `remotes/<name>/HEAD`
108108
if it exists on the remote, but not locally, but will not touch an
109-
already existing local reference. Setting to "warn" will print
109+
already existing local reference. Setting to "warn" will print
110110
a message if the remote has a different value, than the local one and
111-
in case there is no local reference, it behaves like "create". Setting
112-
to "always" will silently update it to the value on the remote.
111+
in case there is no local reference, it behaves like "create".
112+
A variant on "warn" is "warn-if-not-$branch", which behaves like
113+
"warn", but if `HEAD` on the remote is `$branch` it will be silent.
114+
Setting to "always" will silently update it to the value on the remote.
113115
Finally, setting it to "never" will never change or create the local
114116
reference.
115117
+

builtin/fetch.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,10 +1584,12 @@ static void set_head_advice_msg(const char *remote, const char *head_name)
15841584
const char message_advice_set_head[] =
15851585
N_("Run 'git remote set-head %s %s' to follow the change, or set\n"
15861586
"'remote.%s.followRemoteHEAD' configuration option to a different value\n"
1587-
"if you do not want to see this message.");
1587+
"if you do not want to see this message. Specifically running\n"
1588+
"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n"
1589+
"until the remote changes HEAD to something else.");
15881590

15891591
advise_if_enabled(ADVICE_FETCH_SET_HEAD_WARN, _(message_advice_set_head),
1590-
remote, head_name, remote);
1592+
remote, head_name, remote, remote, head_name);
15911593
}
15921594

15931595
static void report_set_head(const char *remote, const char *head_name,
@@ -1612,7 +1614,8 @@ static void report_set_head(const char *remote, const char *head_name,
16121614
strbuf_release(&buf_prefix);
16131615
}
16141616

1615-
static int set_head(const struct ref *remote_refs, int follow_remote_head)
1617+
static int set_head(const struct ref *remote_refs, int follow_remote_head,
1618+
const char *no_warn_branch)
16161619
{
16171620
int result = 0, create_only, is_bare, was_detached;
16181621
struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT,
@@ -1669,7 +1672,9 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head)
16691672
result = 1;
16701673
goto cleanup;
16711674
}
1672-
if (follow_remote_head == FOLLOW_REMOTE_WARN && verbosity >= 0)
1675+
if (verbosity >= 0 &&
1676+
follow_remote_head == FOLLOW_REMOTE_WARN &&
1677+
(!no_warn_branch || strcmp(no_warn_branch, head_name)))
16731678
report_set_head(remote, head_name, &b_local_head, was_detached);
16741679

16751680
cleanup:
@@ -1898,7 +1903,8 @@ static int do_fetch(struct transport *transport,
18981903
"you need to specify exactly one branch with the --set-upstream option"));
18991904
}
19001905
}
1901-
if (set_head(remote_refs, transport->remote->follow_remote_head))
1906+
if (set_head(remote_refs, transport->remote->follow_remote_head,
1907+
transport->remote->no_warn_branch))
19021908
;
19031909
/*
19041910
* Way too many cases where this can go wrong

remote.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,14 +515,23 @@ static int handle_config(const char *key, const char *value,
515515
return parse_transport_option(key, value,
516516
&remote->server_options);
517517
} else if (!strcmp(subkey, "followremotehead")) {
518+
const char *no_warn_branch;
518519
if (!strcmp(value, "never"))
519520
remote->follow_remote_head = FOLLOW_REMOTE_NEVER;
520521
else if (!strcmp(value, "create"))
521522
remote->follow_remote_head = FOLLOW_REMOTE_CREATE;
522-
else if (!strcmp(value, "warn"))
523+
else if (!strcmp(value, "warn")) {
523524
remote->follow_remote_head = FOLLOW_REMOTE_WARN;
524-
else if (!strcmp(value, "always"))
525+
remote->no_warn_branch = NULL;
526+
} else if (skip_prefix(value, "warn-if-not-", &no_warn_branch)) {
527+
remote->follow_remote_head = FOLLOW_REMOTE_WARN;
528+
remote->no_warn_branch = no_warn_branch;
529+
} else if (!strcmp(value, "always")) {
525530
remote->follow_remote_head = FOLLOW_REMOTE_ALWAYS;
531+
} else {
532+
warning(_("unrecognized followRemoteHEAD value '%s' ignored"),
533+
value);
534+
}
526535
}
527536
return 0;
528537
}

remote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ struct remote {
116116
struct string_list server_options;
117117

118118
enum follow_remote_head_settings follow_remote_head;
119+
const char *no_warn_branch;
119120
};
120121

121122
/**

t/t5510-fetch.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,44 @@ test_expect_success "fetch test followRemoteHEAD warn quiet" '
182182
)
183183
'
184184

185+
test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is same" '
186+
test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
187+
(
188+
cd "$D" &&
189+
cd two &&
190+
git rev-parse --verify refs/remotes/origin/other &&
191+
git remote set-head origin other &&
192+
git rev-parse --verify refs/remotes/origin/HEAD &&
193+
git rev-parse --verify refs/remotes/origin/main &&
194+
git config set remote.origin.followRemoteHEAD "warn-if-not-main" &&
195+
actual=$(git fetch) &&
196+
test "z" = "z$actual" &&
197+
head=$(git rev-parse refs/remotes/origin/HEAD) &&
198+
branch=$(git rev-parse refs/remotes/origin/other) &&
199+
test "z$head" = "z$branch"
200+
)
201+
'
202+
203+
test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is different" '
204+
test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
205+
(
206+
cd "$D" &&
207+
cd two &&
208+
git rev-parse --verify refs/remotes/origin/other &&
209+
git remote set-head origin other &&
210+
git rev-parse --verify refs/remotes/origin/HEAD &&
211+
git rev-parse --verify refs/remotes/origin/main &&
212+
git config set remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" &&
213+
git fetch >actual &&
214+
echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
215+
"but we have ${SQ}other${SQ} locally." >expect &&
216+
test_cmp expect actual &&
217+
head=$(git rev-parse refs/remotes/origin/HEAD) &&
218+
branch=$(git rev-parse refs/remotes/origin/other) &&
219+
test "z$head" = "z$branch"
220+
)
221+
'
222+
185223
test_expect_success "fetch test followRemoteHEAD always" '
186224
test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
187225
(

0 commit comments

Comments
 (0)