Message ID | 06a2cea051c01ebee38c9910425171f112daf41a.1591823971.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Allow overriding the default name of the default branch | expand |
On Wed, Jun 10, 2020 at 09:19:23PM +0000, Johannes Schindelin via GitGitGadget wrote: > @@ -2099,7 +2100,10 @@ struct ref *guess_remote_head(const struct ref *head, > > /* If refs/heads/master could be right, it is. */ > if (!all) { > - r = find_ref_by_name(refs, "refs/heads/master"); > + char *name = git_default_branch_name(0); > + > + r = find_ref_by_name(refs, name); > + free(name); > if (r && oideq(&r->old_oid, &head->old_oid)) > return copy_ref(r); > } You'd perhaps want to update the comment above, too. However, I think we should be a bit more lenient on the "reading" side default names. Just because "foo" is _my_ default branch name, does not mean it is the default on the remote side. We cannot know what the other side's default preference is, but in a world where we have 15 years of repos that may have been created with "master", it is probably still a good guess. I.e., I think this probably ought to check the preferred name, and then fall back to the existing behavior, like: if (!all) { char *name; /* try the user's preferred default branch name */ name = git_default_branch_name(0); r = find_ref_by_name(refs, name); free(name); if (r && oideq(&r->old_oid, &head->old_oid)) return copy_ref(r); /* otherwise, try "master", which is the historical default */ r = find_ref_by_name(refs, "refs/heads/master"); if (r && oideq(&r->old_oid, &head->old_oid)) return copy_ref(r); } That will help minimize fallout when git_default_branch_name() changes, either by user config or if we switch the baked-in default. In the latter case, we might also consider hard-coding that as a guess between the user's preferred name and the historical "master". Hopefully this would not matter _too_ much either way, as most servers would support the symref extension these days. But I still think we should do our best to minimize spots where the user may see a regression. -Peff
Hi Peff, On Tue, 16 Jun 2020, Jeff King wrote: > On Wed, Jun 10, 2020 at 09:19:23PM +0000, Johannes Schindelin via GitGitGadget wrote: > > > @@ -2099,7 +2100,10 @@ struct ref *guess_remote_head(const struct ref *head, > > > > /* If refs/heads/master could be right, it is. */ > > if (!all) { > > - r = find_ref_by_name(refs, "refs/heads/master"); > > + char *name = git_default_branch_name(0); > > + > > + r = find_ref_by_name(refs, name); > > + free(name); > > if (r && oideq(&r->old_oid, &head->old_oid)) > > return copy_ref(r); > > } > > You'd perhaps want to update the comment above, too. > > However, I think we should be a bit more lenient on the "reading" side > default names. Just because "foo" is _my_ default branch name, does not > mean it is the default on the remote side. We cannot know what the other > side's default preference is, but in a world where we have 15 years of > repos that may have been created with "master", it is probably still a > good guess. > > I.e., I think this probably ought to check the preferred name, and then > fall back to the existing behavior, like: > > if (!all) { > char *name; > > /* try the user's preferred default branch name */ > name = git_default_branch_name(0); > r = find_ref_by_name(refs, name); > free(name); > if (r && oideq(&r->old_oid, &head->old_oid)) > return copy_ref(r); > > /* otherwise, try "master", which is the historical default */ > r = find_ref_by_name(refs, "refs/heads/master"); > if (r && oideq(&r->old_oid, &head->old_oid)) > return copy_ref(r); > } > > That will help minimize fallout when git_default_branch_name() changes, > either by user config or if we switch the baked-in default. In the > latter case, we might also consider hard-coding that as a guess between > the user's preferred name and the historical "master". > > Hopefully this would not matter _too_ much either way, as most servers > would support the symref extension these days. But I still think we > should do our best to minimize spots where the user may see a > regression. Sure, we could just leave this alone, or we can just ditch the special-casing of `master` here. As you say, this does not affect any modern Git version, and IIRC the code after that special-casing tries to find any remote ref that matches the remote `HEAD`. So it's not like we _need_ this special-casing, anyway. Ciao, Dscho
On Thu, Jun 18, 2020 at 12:21:30PM +0200, Johannes Schindelin wrote: > > Hopefully this would not matter _too_ much either way, as most servers > > would support the symref extension these days. But I still think we > > should do our best to minimize spots where the user may see a > > regression. > > Sure, we could just leave this alone, or we can just ditch the > special-casing of `master` here. > > As you say, this does not affect any modern Git version, and IIRC the code > after that special-casing tries to find any remote ref that matches the > remote `HEAD`. I think we need to be a little careful with "any modern Git", because a modern client against an old (or perhaps an alternative implementation) server might still use it. I have to imagine it's pretty rare, but I think it's still useful to return _some_ value. But as you note, even without a symref extension, we already try to guess based on a unique branch. Probably even choosing the first one alphabetically would be reasonable. But I'd rather err on the side of historical compatibility if we can do so easily. Looking for init.mainBranch, followed by master, accomplishes that and isn't many lines of code. -Peff
Hi Peff, On Thu, 18 Jun 2020, Jeff King wrote: > On Thu, Jun 18, 2020 at 12:21:30PM +0200, Johannes Schindelin wrote: > > > > Hopefully this would not matter _too_ much either way, as most servers > > > would support the symref extension these days. But I still think we > > > should do our best to minimize spots where the user may see a > > > regression. > > > > Sure, we could just leave this alone, or we can just ditch the > > special-casing of `master` here. > > > > As you say, this does not affect any modern Git version, and IIRC the code > > after that special-casing tries to find any remote ref that matches the > > remote `HEAD`. > > I think we need to be a little careful with "any modern Git", because a > modern client against an old (or perhaps an alternative implementation) > server might still use it. I have to imagine it's pretty rare, but I > think it's still useful to return _some_ value. > > But as you note, even without a symref extension, we already try to > guess based on a unique branch. Probably even choosing the first one > alphabetically would be reasonable. But I'd rather err on the side of > historical compatibility if we can do so easily. Looking for > init.mainBranch, followed by master, accomplishes that and isn't many > lines of code. I ended up using `init.defaultBranch` as preference, falling back to `master`, and then falling back to the first ref matching the given commit hash. That should be safe enough. Ciao, Dscho
diff --git a/remote.c b/remote.c index 534c6426f1e..95fa8cc78e0 100644 --- a/remote.c +++ b/remote.c @@ -256,7 +256,7 @@ static void read_remotes_file(struct remote *remote) static void read_branches_file(struct remote *remote) { - char *frag; + char *frag, *default_branch_name = NULL; struct strbuf buf = STRBUF_INIT; FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r"); @@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote) /* * The branches file would have URL and optionally - * #branch specified. The "master" (or specified) branch is + * #branch specified. The default (or specified) branch is * fetched and stored in the local branch matching the * remote name. */ @@ -284,7 +284,7 @@ static void read_branches_file(struct remote *remote) if (frag) *(frag++) = '\0'; else - frag = "master"; + frag = default_branch_name = git_default_branch_name(1); add_url_alias(remote, strbuf_detach(&buf, NULL)); strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s", @@ -299,6 +299,7 @@ static void read_branches_file(struct remote *remote) strbuf_addf(&buf, "HEAD:refs/heads/%s", frag); refspec_append(&remote->push, buf.buf); remote->fetch_tags = 1; /* always auto-follow */ + free(default_branch_name); strbuf_release(&buf); } @@ -2099,7 +2100,10 @@ struct ref *guess_remote_head(const struct ref *head, /* If refs/heads/master could be right, it is. */ if (!all) { - r = find_ref_by_name(refs, "refs/heads/master"); + char *name = git_default_branch_name(0); + + r = find_ref_by_name(refs, name); + free(name); if (r && oideq(&r->old_oid, &head->old_oid)) return copy_ref(r); }