fetch: add configuration for set_head behaviour
In the current implementation, if refs/remotes/$remote/HEAD does not exist, running fetch will create it, but if it does exist it will not do anything, which is a somewhat safe and minimal approach. Unfortunately, for users who wish to NOT have refs/remotes/$remote/HEAD set for any reason (e.g. so that `git rev-parse origin` doesn't accidentally point them somewhere they do not want to), there is no way to remove this behaviour. On the other side of the spectrum, users may want fetch to automatically update HEAD or at least give them a warning if something changed on the remote. Introduce a new setting, remote.$remote.followRemoteHEAD with four options: - "never": do not ever do anything, not even create - "create": the current behaviour, now the default behaviour - "warn": print a message if remote and local HEAD is different - "always": silently update HEAD on every change Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
761e62a09a
commit
b7f7d16562
@ -1579,10 +1579,35 @@ static const char *strip_refshead(const char *name){
|
||||
return name;
|
||||
}
|
||||
|
||||
static int set_head(const struct ref *remote_refs)
|
||||
static void report_set_head(const char *remote, const char *head_name,
|
||||
struct strbuf *buf_prev, int updateres) {
|
||||
struct strbuf buf_prefix = STRBUF_INIT;
|
||||
const char *prev_head = NULL;
|
||||
|
||||
strbuf_addf(&buf_prefix, "refs/remotes/%s/", remote);
|
||||
skip_prefix(buf_prev->buf, buf_prefix.buf, &prev_head);
|
||||
|
||||
if (prev_head && strcmp(prev_head, head_name)) {
|
||||
printf("'HEAD' at '%s' is '%s', but we have '%s' locally.\n",
|
||||
remote, head_name, prev_head);
|
||||
printf("Run 'git remote set-head %s %s' to follow the change.\n",
|
||||
remote, head_name);
|
||||
}
|
||||
else if (updateres && buf_prev->len) {
|
||||
printf("'HEAD' at '%s' is '%s', "
|
||||
"but we have a detached HEAD pointing to '%s' locally.\n",
|
||||
remote, head_name, buf_prev->buf);
|
||||
printf("Run 'git remote set-head %s %s' to follow the change.\n",
|
||||
remote, head_name);
|
||||
}
|
||||
strbuf_release(&buf_prefix);
|
||||
}
|
||||
|
||||
static int set_head(const struct ref *remote_refs, int follow_remote_head)
|
||||
{
|
||||
int result = 0, is_bare;
|
||||
struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT;
|
||||
int result = 0, create_only, is_bare, was_detached;
|
||||
struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT,
|
||||
b_local_head = STRBUF_INIT;
|
||||
const char *remote = gtransport->remote->name;
|
||||
char *head_name = NULL;
|
||||
struct ref *ref, *matches;
|
||||
@ -1603,6 +1628,8 @@ static int set_head(const struct ref *remote_refs)
|
||||
string_list_append(&heads, strip_refshead(ref->name));
|
||||
}
|
||||
|
||||
if (follow_remote_head == FOLLOW_REMOTE_NEVER)
|
||||
goto cleanup;
|
||||
|
||||
if (!heads.nr)
|
||||
result = 1;
|
||||
@ -1614,6 +1641,7 @@ static int set_head(const struct ref *remote_refs)
|
||||
if (!head_name)
|
||||
goto cleanup;
|
||||
is_bare = is_bare_repository();
|
||||
create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !is_bare;
|
||||
if (is_bare) {
|
||||
strbuf_addstr(&b_head, "HEAD");
|
||||
strbuf_addf(&b_remote_head, "refs/heads/%s", head_name);
|
||||
@ -1626,9 +1654,14 @@ static int set_head(const struct ref *remote_refs)
|
||||
result = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
|
||||
"fetch", NULL, !is_bare))
|
||||
was_detached = refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
|
||||
"fetch", &b_local_head, create_only);
|
||||
if (was_detached == -1) {
|
||||
result = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (follow_remote_head == FOLLOW_REMOTE_WARN && verbosity >= 0)
|
||||
report_set_head(remote, head_name, &b_local_head, was_detached);
|
||||
|
||||
cleanup:
|
||||
free(head_name);
|
||||
@ -1636,6 +1669,7 @@ cleanup:
|
||||
free_refs(matches);
|
||||
string_list_clear(&heads, 0);
|
||||
strbuf_release(&b_head);
|
||||
strbuf_release(&b_local_head);
|
||||
strbuf_release(&b_remote_head);
|
||||
return result;
|
||||
}
|
||||
@ -1855,7 +1889,7 @@ static int do_fetch(struct transport *transport,
|
||||
"you need to specify exactly one branch with the --set-upstream option"));
|
||||
}
|
||||
}
|
||||
if (set_head(remote_refs))
|
||||
if (set_head(remote_refs, transport->remote->follow_remote_head))
|
||||
;
|
||||
/*
|
||||
* Way too many cases where this can go wrong
|
||||
|
Reference in New Issue
Block a user