diff mbox series

[RFC/PATCH] tests: support testing with an arbitrary default branch (sort of)

Message ID 20201113161320.16458-1-avarab@gmail.com (mailing list archive)
State New, archived
Headers show
Series [RFC/PATCH] tests: support testing with an arbitrary default branch (sort of) | expand

Commit Message

Ævar Arnfjörð Bjarmason Nov. 13, 2020, 4:13 p.m. UTC
Since 704fed9ea2 ("tests: start moving to a different default main
branch name", 2020-10-23) we've been needlessly skipping tests if the
branch is "master" in preparation for an eventual switch to another name.

As I noted in [1] I don't see why we shouldn't be doing a more
graceful approach here where we don't start skipping unrelated tests
just because some s/master/main/g changes are in flight.

Furthermore the seeming goal of eliminating the string "master" from
anywhere in git's sources results in needless patch churn, and has
nothing to do with the goal of changing the branch name in the UX.

This patch demonstrates that things could be much simpler if we don't
set ourselves that requirement. Now we:

 * Can set GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=<some-name>, but this
   no longer overrides config, so it behaves like other GIT_TEST_*
   variables.

 * Have a test-tool helper that gives us refs.c's idea of the main
   branch name to share the logic between the tests and the main C
   code.

 * A lot of tests (but a small minority of the total) have master
   "master" hardcoded in some way. We now inventory them in
   tests-that-need-master.txt, we can still remove the names from that
   file and manually change the code later, but this accomplishes a
   clean test run with a relatively easy-to-review diff.

   We ignore GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=<name> when it comes
   to these files, unless
   GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME_HARDER=true is set.

 * The changes to t5515-fetch-merge-logic.sh and
   t5560-http-backend-noserver.sh show how much easier it is to just
   punt on certain tests. In these tests that heavily rely on the
   "master" name (not inherently, it's just hardcoded in a lot of
   places) we just give up and keep using "master".

1. https://lore.kernel.org/git/87pn4hfmc4.fsf@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---

I need to walk away from the computer now, but this is an RFC of what
I was commenting on upthread.

 Makefile                            |   1 +
 config.c                            |  10 +
 config.h                            |   1 +
 refs.c                              |   7 +-
 t/helper/test-default-branch-name.c |  16 ++
 t/helper/test-tool.c                |   1 +
 t/helper/test-tool.h                |   1 +
 t/t0001-init.sh                     |   2 +-
 t/t5515-fetch-merge-logic.sh        |   3 +
 t/t5560-http-backend-noserver.sh    |   4 +
 t/test-lib.sh                       |  27 ++-
 t/tests-that-need-master.txt        | 343 ++++++++++++++++++++++++++++
 12 files changed, 403 insertions(+), 13 deletions(-)
 create mode 100644 t/helper/test-default-branch-name.c
 create mode 100644 t/tests-that-need-master.txt

Comments

Jeff King Nov. 13, 2020, 7:14 p.m. UTC | #1
On Fri, Nov 13, 2020 at 05:13:20PM +0100, Ævar Arnfjörð Bjarmason wrote:

>  * A lot of tests (but a small minority of the total) have master
>    "master" hardcoded in some way. We now inventory them in
>    tests-that-need-master.txt, we can still remove the names from that
>    file and manually change the code later, but this accomplishes a
>    clean test run with a relatively easy-to-review diff.
> 
>    We ignore GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=<name> when it comes
>    to these files, unless
>    GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME_HARDER=true is set.

I'm confused how this is better. We could just be setting
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME at the top of those files, couldn't
we? (Likewise, I think annotating individual scripts is more
decentralized than a magic pattern in test-lib.sh, though it amounts to
the same thing).

And if I understand the current state of Dscho's patches, we don't
_have_ to convert any tests right now. We could just annotate those
scripts which are not yet converted to have them use the old name.

But I don't think we want to live in that state indefinitely. It's
slightly annoying to have inconsistent naming within the tests. I'd be
happy to switch individual tests at a leisurely pace over the next
couple of months or whatever. But since Dscho has bothered to write all
of the patches now, why not use them?

I'm much more concerned about the lack of documentation changes
associated with the final patch. We don't necessarily need to eradicate
every mention of "master" from the documentation, but I think we do need
to make sure that examples and instructions are consistent with how Git
will actually behave. And that does need to happen at the same time as
the user-visible flip of the default.

I'm on the fence whether there should be a deprecation period or major
version bump for the final patch, but making the tests flexible enough
to handle the before and after state seems like it can be done uncoupled
from the actual default-flip.

-Peff
Johannes Schindelin Nov. 13, 2020, 10 p.m. UTC | #2
Hi Peff and Ævar,

On Fri, 13 Nov 2020, Jeff King wrote:

> On Fri, Nov 13, 2020 at 05:13:20PM +0100, Ævar Arnfjörð Bjarmason wrote:
>
> >  * A lot of tests (but a small minority of the total) have master
> >    "master" hardcoded in some way. We now inventory them in
> >    tests-that-need-master.txt, we can still remove the names from that
> >    file and manually change the code later, but this accomplishes a
> >    clean test run with a relatively easy-to-review diff.
> >
> >    We ignore GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=<name> when it comes
> >    to these files, unless
> >    GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME_HARDER=true is set.
>
> I'm confused how this is better. We could just be setting
> GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME at the top of those files, couldn't
> we? (Likewise, I think annotating individual scripts is more
> decentralized than a magic pattern in test-lib.sh, though it amounts to
> the same thing).

I considered this alternative very briefly, and rejected it immediately
because it would have implied a drawn-out limbo where the test suite will
be inconsistent. That's not what I want.

> And if I understand the current state of Dscho's patches, we don't
> _have_ to convert any tests right now. We could just annotate those
> scripts which are not yet converted to have them use the old name.

And that's what I did in some cases, see e.g. 5d5f4ea30de (t5411: finish
preparing for `main` being the default branch name, 2020-10-31).

It's just quite a ton of work to do this for all the affected test
scripts, and I wanted to automate as much as possible of that process so
that it'll be easier to cope with all the other topics that are in flight.

Therefore, I opted to "annotate the scripts" via a `case` in
`test-lib.sh`. It should be quite a bit easier to understand, too, for the
occasional reader, as it shows you the complete range of scripts that have
been handled so far.

> But I don't think we want to live in that state indefinitely. It's
> slightly annoying to have inconsistent naming within the tests. I'd be
> happy to switch individual tests at a leisurely pace over the next
> couple of months or whatever. But since Dscho has bothered to write all
> of the patches now, why not use them?

Yep, I am a bit puzzled why we need to consider other approaches. I would
have thought that the more pressing issue is to verify that I

1) caught all the necessary conversions,

2) did not miss any non-trivial adjustments (such as `naster` and aligned
   comments).

At the same time, I am quite thankful for all the help Ævar provided;
mentioning that I missed `naster` in t1400 was definitely super helpful.

> I'm much more concerned about the lack of documentation changes
> associated with the final patch. We don't necessarily need to eradicate
> every mention of "master" from the documentation, but I think we do need
> to make sure that examples and instructions are consistent with how Git
> will actually behave. And that does need to happen at the same time as
> the user-visible flip of the default.

I am sorry. This is totally my fault. I should have described this much
better in the cover letter. This patch series deliberately omits all the
documentation changes.

I _did_ prepare them, they are pretty much ready-to-go, as part of the
`inclusive-naming` branch I track in
https://github.com/gitgitgadget/git/pull/655 (I use the branch name
`use-main-as-default-branch-name-docs` in the `inclusive-naming` branch
thicket to track the documentation changes).

The decision to separate them out into their own patch series was made
consciously, to avoid having one big, honking, totally unreviewably large
patch series.

Therefore, just like I fed the preparatory patch series in a slow cadence,
I planned on feeding the `-docs` patch series once the dust settles on
this patch series (i.e. once it hits `next`).

> I'm on the fence whether there should be a deprecation period or major
> version bump for the final patch, but making the tests flexible enough
> to handle the before and after state seems like it can be done uncoupled
> from the actual default-flip.

Hmm. On that matter, I wonder what the big fuss is all about. It's not
like Git is forcing anybody to change their default branch. That's not at
all what we're doing. To the contrary: _after_ many projects chose to
change their default branch names, and _after_ GitHub started to follow
that trend, Git added support for `init.defaultBranch` to accommodate that
use case better. So in a sense, we're actually pretty late changing the
fall-back of `init.defaultBranch`, at least from the perspective outside
of the Git project.

There have been plenty of articles about this in the meantime, too, and
I could imagine that most developers are at least aware that the shift
away from `master` is happening, in many quite visible projects.

So to me, this whole discussion about whether this should bump the major
version of Git seems a bit overblown. It's not like the median developer
is creating new repositories on a regular basis, and if they do, chances
are that they go with whatever branch name happens to be the initial one.

What is much more common is that developers clone existing projects. And
guess what, many of those projects already use a different default branch
name. And developers seem to accept that and just go on with their lives.

If it was up to me, I would reserve a major version increment to much
bigger changes.

Ciao,
Dscho
Johannes Schindelin Nov. 13, 2020, 10:39 p.m. UTC | #3
Hi Peff,

On Fri, 13 Nov 2020, Johannes Schindelin wrote:

> On Fri, 13 Nov 2020, Jeff King wrote:
>
> > I'm on the fence whether there should be a deprecation period or major
> > version bump for the final patch, but making the tests flexible enough
> > to handle the before and after state seems like it can be done uncoupled
> > from the actual default-flip.
>
> [...] It's not like the median developer is creating new repositories on
> a regular basis, and if they do, chances are that they go with whatever
> branch name happens to be the initial one.
>
> What is much more common is that developers clone existing projects. And
> guess what, many of those projects already use a different default branch
> name. And developers seem to accept that and just go on with their lives.

After sending off this mail, I felt a bit bad about not backing this up
with data.

Whatever telemetry I would be able to pull would not be representative,
and I would not be at liberty to share it anyway. So I asked Alex Mullans
of GitHub (who is in charge of the default branch name switch to `main`
there) whether he has any data I could share publicly and he said: "Across
GitHub, 1/4 of daily pushes (and growing) go to `main`."

Seeing as the branch name to be used in newly-created repositories on
GitHub changed only very recently (October 1st, i.e. some 6 weeks ago), I
highly suspect that this number means that _a lot_ of existing projects
have changed their primary branch name to `main`, and seem to be quite
happy with it.

All this is to say that I consider it unnecessary to have a long
deprecation period or major version bump for this patch series, based on
available public data. The name `main` is already in wide-spread use (and
growing) as primary branch name of Git projects.

Ciao,
Dscho
Ævar Arnfjörð Bjarmason Nov. 13, 2020, 11:49 p.m. UTC | #4
On Fri, Nov 13 2020, Johannes Schindelin wrote:

> Hi Peff and Ævar,
>
> On Fri, 13 Nov 2020, Jeff King wrote:
>
>> On Fri, Nov 13, 2020 at 05:13:20PM +0100, Ævar Arnfjörð Bjarmason wrote:
>>
>> >  * A lot of tests (but a small minority of the total) have master
>> >    "master" hardcoded in some way. We now inventory them in
>> >    tests-that-need-master.txt, we can still remove the names from that
>> >    file and manually change the code later, but this accomplishes a
>> >    clean test run with a relatively easy-to-review diff.
>> >
>> >    We ignore GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=<name> when it comes
>> >    to these files, unless
>> >    GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME_HARDER=true is set.
>>
>> I'm confused how this is better. We could just be setting
>> GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME at the top of those files, couldn't
>> we? (Likewise, I think annotating individual scripts is more
>> decentralized than a magic pattern in test-lib.sh, though it amounts to
>> the same thing).
>
> I considered this alternative very briefly, and rejected it immediately
> because it would have implied a drawn-out limbo where the test suite will
> be inconsistent. That's not what I want.
>
>> And if I understand the current state of Dscho's patches, we don't
>> _have_ to convert any tests right now. We could just annotate those
>> scripts which are not yet converted to have them use the old name.
>
> And that's what I did in some cases, see e.g. 5d5f4ea30de (t5411: finish
> preparing for `main` being the default branch name, 2020-10-31).
>
> It's just quite a ton of work to do this for all the affected test
> scripts, and I wanted to automate as much as possible of that process so
> that it'll be easier to cope with all the other topics that are in flight.
>
> Therefore, I opted to "annotate the scripts" via a `case` in
> `test-lib.sh`. It should be quite a bit easier to understand, too, for the
> occasional reader, as it shows you the complete range of scripts that have
> been handled so far.
>
>> But I don't think we want to live in that state indefinitely. It's
>> slightly annoying to have inconsistent naming within the tests. I'd be
>> happy to switch individual tests at a leisurely pace over the next
>> couple of months or whatever. But since Dscho has bothered to write all
>> of the patches now, why not use them?
>
> Yep, I am a bit puzzled why we need to consider other approaches. I would
> have thought that the more pressing issue is to verify that I
>
> 1) caught all the necessary conversions,
>
> 2) did not miss any non-trivial adjustments (such as `naster` and aligned
>    comments).
>
> At the same time, I am quite thankful for all the help Ævar provided;
> mentioning that I missed `naster` in t1400 was definitely super helpful.

Not being up-to-date on this whole s/master/main/g discussion, is the
context here that we've essentially pre-approved these patches & doc for
integration into the next release? If so I really don't mind doing it
this way.

I started poking at this because I noticed that on git.git's master
branch tests were being skipped due to PREPARE_FOR_MAIN_BRANCH, so it's
in some in-between state between patch serieses.

We're now in week 4/9 of a release cycle for 2.30 (or 3.00 or
whatever). I hope the one thing people for & against this master/main
change can agree on is that it would be bad to ship a git with an
incomplete migration to "main", e.g. the 28/28 patch here which changes
it but without any doc updates.

I may be reading this wrong, but it seems
pr-762/dscho/use-main-as-default-branch-name-v1...remotes/dscho/inclusive-naming
(which I'm assuming is what's left) is another ~30k line diff on top of
this ~25k one.

So yes I'm very late to the discussion, sorry about that. I'm just
chiming in to say that if we're doing this as part of our regular patch
review front-loading these massive search/replace changes seems to be
too much of a change for one cycle.

But if Junio's going to chime in to say he's applying it all I don't
care & don't have any concern about it.

>> I'm much more concerned about the lack of documentation changes
>> associated with the final patch. We don't necessarily need to eradicate
>> every mention of "master" from the documentation, but I think we do need
>> to make sure that examples and instructions are consistent with how Git
>> will actually behave. And that does need to happen at the same time as
>> the user-visible flip of the default.
>
> I am sorry. This is totally my fault. I should have described this much
> better in the cover letter. This patch series deliberately omits all the

Ditto in my hastily-written RFC commit message. A better summary is:

 * Yours: All tests depend on master changed to all tests depend on main
 * Mine (well, partway there): You can set $ANY_NAME for the branch, but
   we blacklist some as being hardcoded on <name> (which I just left at
   master).

   This means we can test e.g. non-ASCII default branch names. It seems
   better to me if we're going to s/master/something/g & review it to
   have that something be \$GIT_TEST_MAIN (or another variable). Then we
   can mark that test as "accepts any default branch name" and move on.

 * Yours: Requires not running some tests while we wait for this to land
 * Mine: Run all tests & mark them as we go along for
   master||$NEWNAME. Similar to the test protocol v2 refactoring

But yeah e.g. the t/tests-that-need-master.txt I added in my RFC is
better marked in the test itself, I should have stolen your 'case
"$TEST_NUMBER"' way of doing it.

In my defense I honestly managed to miss it in skimming the ginormous
diff, which I think makes part of my argument here :)

> I _did_ prepare them, they are pretty much ready-to-go, as part of the
> `inclusive-naming` branch I track in
> https://github.com/gitgitgadget/git/pull/655 (I use the branch name
> `use-main-as-default-branch-name-docs` in the `inclusive-naming` branch
> thicket to track the documentation changes).
>
> The decision to separate them out into their own patch series was made
> consciously, to avoid having one big, honking, totally unreviewably large
> patch series.
>
> Therefore, just like I fed the preparatory patch series in a slow cadence,
> I planned on feeding the `-docs` patch series once the dust settles on
> this patch series (i.e. once it hits `next`).

On the topic of deprecation etc.:

>> I'm on the fence whether there should be a deprecation period or major
>> version bump for the final patch, but making the tests flexible enough
>> to handle the before and after state seems like it can be done uncoupled
>> from the actual default-flip.
>
> Hmm. On that matter, I wonder what the big fuss is all about. It's not
> like Git is forcing anybody to change their default branch. That's not at
> all what we're doing. To the contrary: _after_ many projects chose to
> change their default branch names, and _after_ GitHub started to follow
> that trend, Git added support for `init.defaultBranch` to accommodate that
> use case better. So in a sense, we're actually pretty late changing the
> fall-back of `init.defaultBranch`, at least from the perspective outside
> of the Git project.
>
> There have been plenty of articles about this in the meantime, too, and
> I could imagine that most developers are at least aware that the shift
> away from `master` is happening, in many quite visible projects.
>
> So to me, this whole discussion about whether this should bump the major
> version of Git seems a bit overblown. It's not like the median developer
> is creating new repositories on a regular basis, and if they do, chances
> are that they go with whatever branch name happens to be the initial one.
>
> What is much more common is that developers clone existing projects. And
> guess what, many of those projects already use a different default branch
> name. And developers seem to accept that and just go on with their lives.
>
> If it was up to me, I would reserve a major version increment to much
> bigger changes.
>
[I'm continuing quoting you here from your downthread
<nycvar.QRO.7.76.6.2011132324070.18437@tvgsbejvaqbjf.bet>]

> Whatever telemetry I would be able to pull would not be representative,
> and I would not be at liberty to share it anyway. So I asked Alex Mullans
> of GitHub (who is in charge of the default branch name switch to `main`
> there) whether he has any data I could share publicly and he said: "Across
> GitHub, 1/4 of daily pushes (and growing) go to `main`."
> 
> Seeing as the branch name to be used in newly-created repositories on
> GitHub changed only very recently (October 1st, i.e. some 6 weeks ago), I
> highly suspect that this number means that _a lot_ of existing projects
> have changed their primary branch name to `main`, and seem to be quite
> happy with it.
> 
> All this is to say that I consider it unnecessary to have a long
> deprecation period or major version bump for this patch series, based on
> available public data. The name `main` is already in wide-spread use (and
> growing) as primary branch name of Git projects.

All of that's true, but I really don't see how it's relevant to the
change we're discussing making to refs.c in git.git, which from my
generous reading of some of the threads in objection to this is the main
point of contention.

(I'm generously not engaging with some of the more howler-monkey esque
replies we've had on-list from people who seemed to have no idea what
was actually being proposed in git.git)

*That* change is not whether we approve of people using "main", or
hosting sites like GitHub etc. making it the default.

I think it's fair to say that even in some alternate universe where the
particular reasons we're switching away from "master" didn't exist and
e.g. GitHub et al had just decided on this out of the blue based on an
aesthetic preference we'd just say "uh, sure, whatever, you configure it
how you want".

Rather, we're talking about what happens when you run "git init".

Most people who are using or creating git repositories are nowadays
never going to be impacted by what "git init" does. So I think the data
you're citing here doesn't support your argument at all, it does the
opposite.

The people using these repositories with "main" on GitHub did not do so
with a patch to "git init". They clicked a button in the UI, or
copy/pasted GitHub's "how to create a local repo" which nowadays will
manually set the branch to "main" before pushing.

Then who's using "git init" who's going to be impacted by this change?
It's everyone else, like probably tens of tens of thousands of one-off
cronjobs somewhere creating a daily report of some by "init && commit &&
git diff master..".

I'm on the fence about what we should do in that case, but I'm leaning
towards some deprecation period or at least some other approach than a
s/master/main/g change precisely because of the numbers you're citing.

Because they shows how irrelevant the default shipped with git.git is to
users who want this s/master/main/g change in repositories they
regularly use. So we're really mostly talking about an impact to scripts
& some advanced users, both of who have a pretty good argument for
"init"'s default being what's been explicitly documented for ages in its
manpage.

Even if we want to just change it I think it's uncharitable to those
people not to at least consider throwing them some bone. E.g. "init"
could use the old default when it's not connected to a terminal, we
could show an advice notice and sleep(5) saying we're using a new
default etc. etc.
Felipe Contreras Nov. 14, 2020, 12:25 a.m. UTC | #5
On Fri, Nov 13, 2020 at 4:05 PM Johannes Schindelin
<Johannes.Schindelin@gmx.de> wrote:
> On Fri, 13 Nov 2020, Jeff King wrote:

> > I'm on the fence whether there should be a deprecation period or major
> > version bump for the final patch, but making the tests flexible enough
> > to handle the before and after state seems like it can be done uncoupled
> > from the actual default-flip.
>
> Hmm. On that matter, I wonder what the big fuss is all about. It's not
> like Git is forcing anybody to change their default branch.

Except you are, and you will be doing it without the user consent, and
without warning. This is the opposite of what any software project
that cares about its users should do.

The consequences are predictable.

Exactly the same argument was used in 2008, and it was wrong for
exactly the same reasons.

Yes, people could add the exec-path to their PATH, so "nobody was
being forced" ultimately, but that's missing the point entirely,
because that happened *after* they were forced initially, and being
caught completely off guard.

> There have been plenty of articles about this in the meantime, too, and
> I could imagine that most developers are at least aware that the shift
> away from `master` is happening, in many quite visible projects.

I have used Git since 2005, contributed since 2009, follow the git
subreddit, and I was not aware of the change, and presumably neither
was Ævar.

What you imagine most developers know is irrelevant, what is relevant
is what they actually know.

This is the bias known as the curse of knowledge: since you have a lot
of specific knowledge you fail to see how other people could not see
the same thing you are seeing, but they don't, and the reason is that
they don't have the same knowledge as you.

But just because you can't see it happen, doesn't mean it can't.

It did in 2008, and people back then used the same argument you are using now.

Developers back then could not imagine how it was possible that users
were not aware of the upcoming change that had been cooking for years,
but alas they did not.

Do not assume what your users know. Deprecation periods exist for a
reason, and so do warnings.
Ævar Arnfjörð Bjarmason Nov. 18, 2020, 1:32 p.m. UTC | #6
On Mon, Nov 16 2020, Johannes Schindelin wrote:

> Hi Ævar,
>
> On Sat, 14 Nov 2020, Ævar Arnfjörð Bjarmason wrote:
>
>> On Fri, Nov 13 2020, Johannes Schindelin wrote:
>>
>> > Whatever telemetry I would be able to pull would not be representative,
>> > and I would not be at liberty to share it anyway. So I asked Alex Mullans
>> > of GitHub (who is in charge of the default branch name switch to `main`
>> > there) whether he has any data I could share publicly and he said: "Across
>> > GitHub, 1/4 of daily pushes (and growing) go to `main`."
>> >
>> > Seeing as the branch name to be used in newly-created repositories on
>> > GitHub changed only very recently (October 1st, i.e. some 6 weeks ago), I
>> > highly suspect that this number means that _a lot_ of existing projects
>> > have changed their primary branch name to `main`, and seem to be quite
>> > happy with it.
>> >
>> > All this is to say that I consider it unnecessary to have a long
>> > deprecation period or major version bump for this patch series, based on
>> > available public data. The name `main` is already in wide-spread use (and
>> > growing) as primary branch name of Git projects.
>>
>> [...]
>> I'm on the fence about what we should do in that case, but I'm leaning
>> towards some deprecation period or at least some other approach than a
>> s/master/main/g change precisely because of the numbers you're citing.
>>
>> Because they shows how irrelevant the default shipped with git.git is to
>> users who want this s/master/main/g change in repositories they
>> regularly use. So we're really mostly talking about an impact to scripts
>> & some advanced users, both of who have a pretty good argument for
>> "init"'s default being what's been explicitly documented for ages in its
>> manpage.
>
> I think you have a good point here. It really does not matter _all_ that
> much, yet I still would like to complete the switch to `main` at some
> stage. But as you point out, that point does not _have_ to be now.
>
> As a consequence, I reconsider my stance on "splitting off patch 28". I
> think I will send out a v2 tomorrow, including the fix you suggested for
> t1400 to also rename `naster` to `nain`, and dropping the patch that
> changes the fall-back for `init.defaultBranch` for now.
>
> I _do_ want to complete the transition to using
> `GIT_TEST_DEFAULT_INIT_BRANCH=main` to address the concern you raised
> elsewhere: a couple of test cases are skipped until that transition is
> complete.
>
> After I send out v2, I will work on that patch that imitates d18c950a69f
> (pull: warn if the user didn't say whether to rebase or to merge,
> 2020-03-09) to show some advice when `init.defaultBranch` is not set.
>
> My current thinking is that we could show this advice for about half a
> year and then make the switch to `main`, continuing to show the advice
> (now adjusted for `main`) for about another half year, and then turn the
> warning off.
>
> What do you think, does that sound too conservative of a plan?

The v2 looks good to me. I just had a suggestion in [1] to apply
something on top to restore the test coverage until while whatever comes
after it lands.

In case I didn't make it clear I have no objection entirely replacing
"master" with "main" in the tests. I just had a practical
concern/question about coverage while it was landing, and a suggestion
of whether perhaps there was an easier/faster way to do the "init"
change first by omitting some of the test churn.

But if you want to do all the legwork that's fine by me :)

I just thought that a sober estimation of how long it takes patches to
land would mean the v1 would be in some in-between state for the next
release.

FWIW I'm not necessarily for some warning. I mainly wanted to attempt to
mediate some of the discussion about the concern to something more
productive.

At the risk of repeating too much of my past overly long E-Mails, but if
I'm being difficult for you when you're submitting patches & causing
work for you I think I owe you an unambiguous explanation for why that
is:

I think some of the people advocating this change can rightly look at
some of the previous E-Mail traffic and see what are at best rants and
at worst some political grandstanding that's at best pretty irrelevant
to any proposed changes in git.git.

But that doesn't mean that there aren't some legitimate concerns. Those
are in my mind separate from the particular political motivations of the
s/master/main/ change, we'd have those with any change to the defaults
in the core tooling.

I think in general with such changes that replies like Theodore Ts'o
here [2] (not picking on him in particular, I just thought it was
representative) reflect a rather insular view of how we need to think
about these sorts of changes.

I.e. a *lot* of git users probably aren't aware that there's even a git
config (they use some 3rd party UI), and I'd say the vast majority are
likely to never find or read any sort of release notes about changes we
make.

Most people's relation to git is like my relation to netcat. It's some
tool I use 1-2 levels down in my stack, and I only bothered to find out
about it because "ssh" stopped working one day.

If at the end of the day we decide to keep something like your original
v1 28/28 patch + docs after some realistic look at the impact that would
be fine by me. Just as long as we understand who we're likely to break
stuff for, and whether it's worth the trade-off.

To Theodore's point about some people's motivations in [2], just to make
my stance/opinion on the end-state clear (so far in all these threads
I've been commenting on the "how" of the incremental transition):

I do 100% agree that the s/master/main/g change of the default should be
made in one form or another. In my mind that doesn't even require a
consideration of the political motivations at this point as far as
git.git is concerned, just:

 1. Major Git hosting providers already made the change

 2. Realistically a lot/majority of git's user base interact with that
    in a major way.

 3. A discrepancy in any default between /usr/bin/git and those
    providers is more confusing than not.

 4. #3 doesn't mean they say "jump" we say "how high" whatever the
    change is.

    But in this case the default is an entirely arbitrary default. Not
    e.g. that they decided to add some ill-thought out header to the
    object format or whatever.

P.S.: Shouldn't the pull patch in d18c950a69f be using the advice
     facility, not warning()?

1. https://public-inbox.org/git/20201118114834.11137-1-avarab@gmail.com/

2. https://public-inbox.org/git/20201115034649.GC3985404@mit.edu/
Felipe Contreras Nov. 18, 2020, 2:16 p.m. UTC | #7
On Wed, Nov 18, 2020 at 7:32 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:

> I do 100% agree that the s/master/main/g change of the default should be
> made in one form or another. In my mind that doesn't even require a
> consideration of the political motivations at this point as far as
> git.git is concerned, just:

Others disagree.

While the political motivation shouldn't be a central concern, I
suspect the vast majority of users have no idea this change is coming,
and when they see the warning they will likely complain... Strongly.
The fact that this change is extremely politically charged will become
a factor.

>  1. Major Git hosting providers already made the change

That's their decision. The Git project shouldn't be held hostage to
third party decisions.

>  2. Realistically a lot/majority of git's user base interact with that
>     in a major way.
>
>  3. A discrepancy in any default between /usr/bin/git and those
>     providers is more confusing than not.

That's a problem for GitHub et al. Fortunately they can tell their
users to set init.defaultbranch to whatever they want.

>  4. #3 doesn't mean they say "jump" we say "how high" whatever the
>     change is.
>
>     But in this case the default is an entirely arbitrary default. Not
>     e.g. that they decided to add some ill-thought out header to the
>     object format or whatever.

I don't agree it is arbitrary, otherwise you could set the default to
"loremipsum". Moreover, even if was arbitrary, it was arbitrary in
2005, not 2020 where "master" is already widely used in basically
*all* the documentation everywhere. Some people have been using this
name for 15 years, they won't give it up just like that.

People will complain, especially if they don't see a good reason for the change.
Junio C Hamano Nov. 18, 2020, 3:56 p.m. UTC | #8
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> ... In my mind that doesn't even require a
> consideration of the political motivations at this point as far as
> git.git is concerned, just:
>
>  1. Major Git hosting providers already made the change
>
>  2. Realistically a lot/majority of git's user base interact with that
>     in a major way.
>
>  3. A discrepancy in any default between /usr/bin/git and those
>     providers is more confusing than not.
>
>  4. #3 doesn't mean they say "jump" we say "how high" whatever the
>     change is.
>
>     But in this case the default is an entirely arbitrary default. Not
>     e.g. that they decided to add some ill-thought out header to the
>     object format or whatever.

Yes.

> P.S.: Shouldn't the pull patch in d18c950a69f be using the advice
>      facility, not warning()?

I think warning() is the right thing here, as it is self squelching.
Setting pull.rebase (even to 'false') is sufficient---there is no
need to set advise.setpullrebase to 'false' on top.
Johannes Schindelin Nov. 19, 2020, 9:32 a.m. UTC | #9
Hi Junio & Ævar,

On Wed, 18 Nov 2020, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
> > P.S.: Shouldn't the pull patch in d18c950a69f be using the advice
> >      facility, not warning()?
>
> I think warning() is the right thing here, as it is self squelching.
> Setting pull.rebase (even to 'false') is sufficient---there is no
> need to set advise.setpullrebase to 'false' on top.

Right. The only reason to use `advise()` would be to allow users to
squelch the warning by setting `advice.*`.

On the other hand, warnings are not colored, but advice messages are.

And now I realize that the same holds for `init.defaultBranch`: it is also
self-squelching. And it also might benefit from the coloring to make it
stand out a bit.

Thoughts?

Ciao,
Dscho
Johannes Schindelin Nov. 19, 2020, 10:46 a.m. UTC | #10
Hi Ævar,

I agree with pretty much all you said, just wanted to comment on a couple
things:

On Wed, 18 Nov 2020, Ævar Arnfjörð Bjarmason wrote:

> In case I didn't make it clear I have no objection entirely replacing
> "master" with "main" in the tests. I just had a practical
> concern/question about coverage while it was landing, and a suggestion
> of whether perhaps there was an easier/faster way to do the "init"
> change first by omitting some of the test churn.
>
> But if you want to do all the legwork that's fine by me :)

I started it, I finish it, I guess. Well, technically Don started it...

> I think some of the people advocating this change can rightly look at
> some of the previous E-Mail traffic and see what are at best rants and
> at worst some political grandstanding that's at best pretty irrelevant
> to any proposed changes in git.git.
>
> But that doesn't mean that there aren't some legitimate concerns.

And that's so sad to read. It is disheartening how eager certain people
were to drown out others' voices, then claiming that they had not heard
any views opposing their own. I mean, yeah, if you want to hear other
opinions, it sure helps to stop talking for a while, and to start
listening.

I consider myself lucky that I _did_ get the chance to listen. Related to
my work in GSoC and Outreachy, and through my day job, wonderful people
approached me with their stories and perspectives. I am really glad that I
had the opportunity to hear those.

As to legitimate concerns: yes, you are right. There are those. If your
documentation says that you should avoid committing directly to the
`master` branch, and then you clone a popular Open Source project and it
does not even _have_ a `master` branch, that might be a bit puzzling.

Note that I used a clone as an example, not `git init`, because it is a
much more common operation. Git is a tool for developers to communicate,
in a way, after all, even if it _can_ be used for working in isolation,
too. Hence clones outnumber inits. And that communication of ideas, of
code, and to combine efforts, to collaborate, that is what Git really
facilitates. That is why I find it so important to be inclusive, to be
inviting underrepresented developers. There is such a lot of untapped
potential there, and even if using a non-offensive default branch name is
but a _teeny_ tiny step to open the door a little, it is at least a step
in the right direction.

Now, since I mentioned `clone`: please note that the default branch name
used in a `clone` is squarely outside the Git project's control. It is
decided by the maintainer(s)/communities of the respective projects. And
that's exactly how it should be.

Therefore, as you said before, it does not really matter all that much
at what date we will change the fall-back for `init.defaultBranch`.

At the same time, I still think that it is valuable to transition the test
suite _now_, to be as independent on a specific default branch name as
possible, if only to ensure that above-mentioned projects can choose
freely what they want their primary branch to be called and Git works just
fine.

> I do 100% agree that the s/master/main/g change of the default should be
> made in one form or another. In my mind that doesn't even require a
> consideration of the political motivations at this point as far as
> git.git is concerned, just:
>
>  1. Major Git hosting providers already made the change
>
>  2. Realistically a lot/majority of git's user base interact with that
>     in a major way.
>
>  3. A discrepancy in any default between /usr/bin/git and those
>     providers is more confusing than not.

Right.

I originally thought that we should switch the default branch name in
v2.30 for that reason, but I now think that adding that advice is probably
a less disruptive, and almost equally supportive solution.

>  4. #3 doesn't mean they say "jump" we say "how high" whatever the
>     change is.
>
>     But in this case the default is an entirely arbitrary default. Not
>     e.g. that they decided to add some ill-thought out header to the
>     object format or whatever.
>
> P.S.: Shouldn't the pull patch in d18c950a69f be using the advice
>      facility, not warning()?

I submitted a patch for that, but unfortunately forgot to Cc: you:
https://lore.kernel.org/git/pull.795.git.1605781349528.gitgitgadget@gmail.com

Ciao,
Dscho
Junio C Hamano Nov. 19, 2020, 7:35 p.m. UTC | #11
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> Hi Junio & Ævar,
>
> On Wed, 18 Nov 2020, Junio C Hamano wrote:
>
>> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>>
>> > P.S.: Shouldn't the pull patch in d18c950a69f be using the advice
>> >      facility, not warning()?
>>
>> I think warning() is the right thing here, as it is self squelching.
>> Setting pull.rebase (even to 'false') is sufficient---there is no
>> need to set advise.setpullrebase to 'false' on top.
>
> Right. The only reason to use `advise()` would be to allow users to
> squelch the warning by setting `advice.*`.
>
> On the other hand, warnings are not colored, but advice messages are.
>
> And now I realize that the same holds for `init.defaultBranch`: it is also
> self-squelching. And it also might benefit from the coloring to make it
> stand out a bit.
>
> Thoughts?

I do not see colors well.  You'll always get "find some other way to
make it stand out more to those like us---if you canhdo so without
colors, that would be ideal" from me, so please don't ask me to vote
for more colors.
Ævar Arnfjörð Bjarmason Nov. 20, 2020, 11:36 a.m. UTC | #12
On Wed, Nov 18 2020, Felipe Contreras wrote:

> On Wed, Nov 18, 2020 at 7:32 AM Ævar Arnfjörð Bjarmason
> <avarab@gmail.com> wrote:
>
>> I do 100% agree that the s/master/main/g change of the default should be
>> made in one form or another. In my mind that doesn't even require a
>> consideration of the political motivations at this point as far as
>> git.git is concerned, just:
>
> Others disagree.

Sure, and I might end up disagreeing with myself once we have the
proposed patches & more people inevitably chime in with some useful data
about the trade-offs, edge cases we haven't considered etc.

> While the political motivation shouldn't be a central concern, I
> suspect the vast majority of users have no idea this change is coming,
> and when they see the warning they will likely complain... Strongly.
> The fact that this change is extremely politically charged will become
> a factor.
>
>>  1. Major Git hosting providers already made the change

[... addressed below ...]

> That's their decision. The Git project shouldn't be held hostage to
> third party decisions.
>
>>  2. Realistically a lot/majority of git's user base interact with that
>>     in a major way.
>>
>>  3. A discrepancy in any default between /usr/bin/git and those
>>     providers is more confusing than not.
>
> That's a problem for GitHub et al. Fortunately they can tell their
> users to set init.defaultbranch to whatever they want.

I think this and what you mention in another thread[1] about GitHub's
instructions for creating a repository takes a narrow view of our
responsibility for creating a sane UI for users.

For example, right after the instructions you note there GitHub's
current instructions are:

    git remote add origin $url
    git branch -M main
    git push -u origin main

Now, put yourself in the shoes of a novice user who's just been
introduced to this "git" thing for a job they started 2 days ago. We
don't take the s/master/main/g change in git.git, GitHub keeps
theirs.

You followed some tutorial or read the manpage to create a local
repository and made a few commits, then to upload it to GitHub or
another provider that uses "main" by default you copy/pasted the above
commands. Now the thing changing from "master" to "main" is one more
thing you're confused by.

That's my motivation for supporting this change. I think most git users
by number are (hopefully) in the future, yes, as you note we'll have
version transitions where that's more confusing than not, but the same
can be said about the dashed command transition.

Whatever mistakes we made in that transition and should learn from a
typical git user in 2020 has never used a dashed builtin, just like a
new user in 2030 probably won't know or have to care about their local
default being different than a $BIG_HOSTING_PROVIDER default.

That *is* our problem, not just a problem for GitHub et al. To claim
otherwise is to just bury our head in the sand.

Are we on balance going to not make the change because e.g. we don't
want various paper books and tutorials to be confusing? Maybe, maybe
not. But just dismissing those concerns by saying e.g. "that's
O'Reilly's problem" would be as nonsensical as us pretending that
perpetuating an (admittedly rather minor) UI difference in perpetuity by
our inaction is purely GitHub's responsibility.

>>  4. #3 doesn't mean they say "jump" we say "how high" whatever the
>>     change is.
>>
>>     But in this case the default is an entirely arbitrary default. Not
>>     e.g. that they decided to add some ill-thought out header to the
>>     object format or whatever.
>
> I don't agree it is arbitrary, otherwise you could set the default to
> "loremipsum". Moreover, even if was arbitrary, it was arbitrary in
> 2005, not 2020 where "master" is already widely used in basically
> *all* the documentation everywhere. Some people have been using this
> name for 15 years, they won't give it up just like that.

Yes, that was badly phrased and I take that back. I meant to say
something closer to "a common convention" or whatever. E.g. if GitHub et
al for whatever reason switched all use of "origin" as the default
remote to "source" I'd think that at some point we'd be improving things
overall if we made that switch as well.

> People will complain, especially if they don't see a good reason for
> the change.


1. https://lore.kernel.org/git/CAMP44s1515GOwTOYv-wz4qMC9Qb6d8cSVSb_CNVwun0+Yj3VxQ@mail.gmail.com/
Felipe Contreras Nov. 20, 2020, 4 p.m. UTC | #13
On Fri, Nov 20, 2020 at 5:36 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> On Wed, Nov 18 2020, Felipe Contreras wrote:

> > That's a problem for GitHub et al. Fortunately they can tell their
> > users to set init.defaultbranch to whatever they want.
>
> I think this and what you mention in another thread[1] about GitHub's
> instructions for creating a repository takes a narrow view of our
> responsibility for creating a sane UI for users.
>
> For example, right after the instructions you note there GitHub's
> current instructions are:
>
>     git remote add origin $url
>     git branch -M main
>     git push -u origin main
>
> Now, put yourself in the shoes of a novice user who's just been
> introduced to this "git" thing for a job they started 2 days ago. We
> don't take the s/master/main/g change in git.git, GitHub keeps
> theirs.

I am.

But that doesn't change the instructions. The "git branch -M main"
would still be there (for older versions of Git).

And the "git push -u origin main" would still be there, because you
need to specify the branch you want to push to. Although I would have
used HEAD instead of main, or even better @, which apparently doesn't
work, but should work. If GitHub cares so much about these
instructions, they could have fixed this so "git push -u origin @"
works, why haven't they? Because they don't care as much as they claim
to (see the obvious inconsistency below).

> You followed some tutorial or read the manpage to create a local
> repository and made a few commits, then to upload it to GitHub or
> another provider that uses "main" by default you copy/pasted the above
> commands. Now the thing changing from "master" to "main" is one more
> thing you're confused by.

What if the project uses "trunk"? Or "default"?

If a project uses a non-standard name, it's their responsibility to
teach their users how to interact with that project. If GitHub chose
"main", it's *their* responsibility to tell their users that this is a
discrepancy from most of the online documentation, including online
documentation specific to GitHub.

The best way the Git project can help is by not hard-coding any of
these names, so the documentation doesn't have to use "master", or
"main", but can use @, or @{upstream}.

But right now the documentation *has* to hard-code these names,
because of poor triangular workflow support from Git, something I
tried to fix many years ago with my @{publish} patches.

If we had proper @{upstream} and @{publish} support, and taught users
how to use them well, there would be no need for anyone to do "git
rebase -i master" ("git rebase -i" would do).

> That's my motivation for supporting this change. I think most git users
> by number are (hopefully) in the future, yes, as you note we'll have
> version transitions where that's more confusing than not, but the same
> can be said about the dashed command transition.

The number of Git users in the future directly depends on how we treat
Git users in the present. And the Git users of the present would not
appreciate that 99% of documentation out there uses "master", while
Git does not, especially if in their mind it's due to bad (political)
reasons.

What's wrong with *first* fixing the interface so we don't have to
type "master" so much (e.g. by properly supporting triangular
workflows), and *then* consider changing "master" later, *after* a lot
of online documentation has stopped using the name "master" directly
as well?

> Whatever mistakes we made in that transition and should learn from a
> typical git user in 2020 has never used a dashed builtin, just like a
> new user in 2030 probably won't know or have to care about their local
> default being different than a $BIG_HOSTING_PROVIDER default.

That's *if* the current project survives in its current form. Perhaps
in 2030 there will be a libgit with more than one user interface.
Nobody knows the future.

> That *is* our problem, not just a problem for GitHub et al. To claim
> otherwise is to just bury our head in the sand.

It is our problem to improve the interface so users don't have to type
"master" (or "main), so much.

It is not our problem that GitHub decided to get ahead of itself and
change their instructions without first considering other options,
like improving the interface.

> Are we on balance going to not make the change because e.g. we don't
> want various paper books and tutorials to be confusing? Maybe, maybe
> not. But just dismissing those concerns by saying e.g. "that's
> O'Reilly's problem" would be as nonsensical as us pretending that
> perpetuating an (admittedly rather minor) UI difference in perpetuity by
> our inaction is purely GitHub's responsibility.

GitHub can fix that UI difference *today* by retracting their
instructions and instead come here and discuss with us ways to improve
the interface first.

They chose that action *unilaterally* without discussing it with the
Git project. That's on them.

Yes, GitHub users are our users too, but we have many more users, we
shouldn't hurt them just because GitHub has no patience.

As an example of GitHub's impatience, look at GitHub's Hello World
[1], the text has been updated to "main", but all the images say
"master". It's their *first* guide, and it's already inconsistent.

https://guides.github.com/activities/hello-world/readme-edits.gif

Additionally, GitHub cannot say "implement X or we will hurt our
users". That would be manipulative tactics, and the Git project should
not succumb to those. Regardless of what GitHub does, the Git project
should implement X on its own terms, if and when it has determined
it's in the best interest of its users.

Moreover, you have not explained precisely how the issues will be
solved by changing the default name. All the documentation out there
would be inconsistent with "main". Even GitHub's own documentation is
inconsistent at this precise moment.

Take one of the first results you get when googling "github how to"
[2], it says to "git push -u origin master". By keeping the name
"master" we are helping those users that are not using a github.com
guide, and are using one of the hundreds (or thousands) of guides out
there that assume the name is master. In fact, the *only* thing that
is hurting GitHub users right now is those initial instructions they
chose, which you can ignore, and instead use an external guide.

It is very likely that by doing this change we would actually hurt
more GitHub users than not doing it.

Cheers.

[1] https://guides.github.com/activities/hello-world/
[2] https://opensource.com/article/18/1/step-step-guide-git
Johannes Schindelin Nov. 22, 2020, 7:07 p.m. UTC | #14
Hi Junio,

On Thu, 19 Nov 2020, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > On Wed, 18 Nov 2020, Junio C Hamano wrote:
> >
> >> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> >>
> >> > P.S.: Shouldn't the pull patch in d18c950a69f be using the advice
> >> >      facility, not warning()?
> >>
> >> I think warning() is the right thing here, as it is self squelching.
> >> Setting pull.rebase (even to 'false') is sufficient---there is no
> >> need to set advise.setpullrebase to 'false' on top.
> >
> > Right. The only reason to use `advise()` would be to allow users to
> > squelch the warning by setting `advice.*`.
> >
> > On the other hand, warnings are not colored, but advice messages are.
> >
> > And now I realize that the same holds for `init.defaultBranch`: it is also
> > self-squelching. And it also might benefit from the coloring to make it
> > stand out a bit.
> >
> > Thoughts?
>
> I do not see colors well.  You'll always get "find some other way to
> make it stand out more to those like us---if you canhdo so without
> colors, that would be ideal" from me, so please don't ask me to vote
> for more colors.

From a purely selfish point of view: colors _do_ serve me well. And from a
maintainer's point of view: I added my share of coloring based on users'
feedback, so I think that even if it does not benefit everybody equally
well, it is valuable to add coloring where helpful.

As to the aspect "find some other way to make it stand out", I believe
that `advise()` addresses that _also_, by virtue of prefixing the lines
with the uniform `hint:` prefix (which stands out visually, at least to
me, maybe it also does that for you?).

Ciao,
Dscho
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index 790a883932..fb94c836e2 100644
--- a/Makefile
+++ b/Makefile
@@ -696,6 +696,7 @@  TEST_BUILTINS_OBJS += test-chmtime.o
 TEST_BUILTINS_OBJS += test-config.o
 TEST_BUILTINS_OBJS += test-ctype.o
 TEST_BUILTINS_OBJS += test-date.o
+TEST_BUILTINS_OBJS += test-default-branch-name.o
 TEST_BUILTINS_OBJS += test-delta.o
 TEST_BUILTINS_OBJS += test-dir-iterator.o
 TEST_BUILTINS_OBJS += test-drop-caches.o
diff --git a/config.c b/config.c
index 2bdff4457b..0c12864b79 100644
--- a/config.c
+++ b/config.c
@@ -1706,6 +1706,16 @@  unsigned long git_env_ulong(const char *k, unsigned long val)
 	return val;
 }
 
+/*
+ * Parse environment variable 'k' as a char *; if missing, use the
+ * default value 'def'.
+ */
+const char* git_env_str(const char *k, const char *def)
+{
+	const char *v = getenv(k);
+	return v && strlen(v) ? v : def;
+}
+
 int git_config_system(void)
 {
 	return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
diff --git a/config.h b/config.h
index 91cdfbfb41..36a7284f8a 100644
--- a/config.h
+++ b/config.h
@@ -298,6 +298,7 @@  int git_config_copy_section_in_file(const char *, const char *, const char *);
 const char *git_etc_gitconfig(void);
 int git_env_bool(const char *, int);
 unsigned long git_env_ulong(const char *, unsigned long);
+const char* git_env_str(const char *, const char *);
 int git_config_system(void);
 int config_error_nonbool(const char *);
 #if defined(__GNUC__)
diff --git a/refs.c b/refs.c
index 392f0bbf68..ca8875e945 100644
--- a/refs.c
+++ b/refs.c
@@ -567,15 +567,12 @@  char *repo_default_branch_name(struct repository *r)
 	const char *config_key = "init.defaultbranch";
 	const char *config_display_key = "init.defaultBranch";
 	char *ret = NULL, *full_ref;
-	const char *env = getenv("GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME");
 
-	if (env && *env)
-		ret = xstrdup(env);
-	else if (repo_config_get_string(r, config_key, &ret) < 0)
+	if (repo_config_get_string(r, config_key, &ret) < 0)
 		die(_("could not retrieve `%s`"), config_display_key);
 
 	if (!ret)
-		ret = xstrdup("master");
+		ret = xstrdup(git_env_str("GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME", "master"));
 
 	full_ref = xstrfmt("refs/heads/%s", ret);
 	if (check_refname_format(full_ref, 0))
diff --git a/t/helper/test-default-branch-name.c b/t/helper/test-default-branch-name.c
new file mode 100644
index 0000000000..1a0c8502ee
--- /dev/null
+++ b/t/helper/test-default-branch-name.c
@@ -0,0 +1,16 @@ 
+#include "test-tool.h"
+#include "git-compat-util.h"
+#include "refs.h"
+
+/*
+ * usage:
+ * tool-test default-branch-name
+ */
+int cmd__default_branch_name(int argc, const char **argv)
+{
+	const char *name = git_default_branch_name();
+
+	puts(name);
+
+	return 0;
+}
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index a0d3966b29..ad4bd7274c 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -21,6 +21,7 @@  static struct test_cmd cmds[] = {
 	{ "ctype", cmd__ctype },
 	{ "date", cmd__date },
 	{ "delta", cmd__delta },
+	{ "default-branch-name", cmd__default_branch_name },
 	{ "dir-iterator", cmd__dir_iterator },
 	{ "drop-caches", cmd__drop_caches },
 	{ "dump-cache-tree", cmd__dump_cache_tree },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 07034d3f38..e0dda6bfd8 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -10,6 +10,7 @@  int cmd__chmtime(int argc, const char **argv);
 int cmd__config(int argc, const char **argv);
 int cmd__ctype(int argc, const char **argv);
 int cmd__date(int argc, const char **argv);
+int cmd__default_branch_name(int argc, const char **argv);
 int cmd__delta(int argc, const char **argv);
 int cmd__dir_iterator(int argc, const char **argv);
 int cmd__drop_caches(int argc, const char **argv);
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 69a320489f..68adb9a832 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -562,7 +562,7 @@  test_expect_success 'overridden default main branch name (env)' '
 	test_config_global init.defaultBranch nmb &&
 	GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=env git init main-branch-env &&
 	git -C main-branch-env symbolic-ref HEAD >actual &&
-	grep env actual
+	grep nmb actual
 '
 
 test_expect_success 'invalid default branch name' '
diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
index 70a9d2d8ab..939c8b2f83 100755
--- a/t/t5515-fetch-merge-logic.sh
+++ b/t/t5515-fetch-merge-logic.sh
@@ -11,6 +11,9 @@  test_description='Merge logic in fetch'
 GIT_TEST_PROTOCOL_VERSION=0
 export GIT_TEST_PROTOCOL_VERSION
 
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
 . ./test-lib.sh
 
 build_script () {
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index 9fafcf1945..27b31745ad 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -1,6 +1,10 @@ 
 #!/bin/sh
 
 test_description='test git-http-backend-noserver'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
 . ./test-lib.sh
 
 HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
diff --git a/t/test-lib.sh b/t/test-lib.sh
index fa347ed3e1..11ea009717 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1382,6 +1382,26 @@  HOME="$TRASH_DIRECTORY"
 GNUPGHOME="$HOME/gnupg-home-not-used"
 export HOME GNUPGHOME
 
+# Check if we're doing tests with the main branch != master, and if
+# we'd like to override that for known-broken tests.
+GIT_TEST_MAIN=$(test-tool default-branch-name)
+if test "$GIT_TEST_MAIN" = "master"
+then
+	test_set_prereq MAIN_BRANCH_IS_MASTER
+else
+	if test -z "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME_HARDER" &&
+	   grep -q $TEST_NAME "$TEST_DIRECTORY/tests-that-need-master.txt"
+	then
+		echo overriding
+		GIT_TEST_MAIN=master
+		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+		test_set_prereq MAIN_BRANCH_IS_MASTER
+	fi
+fi
+export GIT_TEST_MAIN
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+# Initialize the repository after we know the main branch name.
 if test -z "$TEST_NO_CREATE_REPO"
 then
 	test_create_repo "$TRASH_DIRECTORY"
@@ -1711,10 +1731,3 @@  test_lazy_prereq SHA1 '
 test_lazy_prereq REBASE_P '
 	test -z "$GIT_TEST_SKIP_REBASE_P"
 '
-# Special-purpose prereq for transitioning to a new default branch name:
-# Some tests need more than just a mindless (case-preserving) s/master/main/g
-# replacement. The non-trivial adjustments are guarded behind this
-# prerequisite, acting kind of as a feature flag
-test_lazy_prereq PREPARE_FOR_MAIN_BRANCH '
-	test "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" = main
-'
diff --git a/t/tests-that-need-master.txt b/t/tests-that-need-master.txt
new file mode 100644
index 0000000000..d7a693b19e
--- /dev/null
+++ b/t/tests-that-need-master.txt
@@ -0,0 +1,343 @@ 
+t0002-gitfile.sh
+t0020-crlf.sh
+t0021-conversion.sh
+t0027-auto-crlf.sh
+t0028-working-tree-encoding.sh
+t0041-usage.sh
+t0050-filesystem.sh
+t0060-path-utils.sh
+t0100-previous.sh
+t1004-read-tree-m-u-wf.sh
+t1008-read-tree-overlay.sh
+t1009-read-tree-new-index.sh
+t1011-read-tree-sparse-checkout.sh
+t1021-rerere-in-workdir.sh
+t1090-sparse-checkout-scope.sh
+t1091-sparse-checkout-builtin.sh
+t1300-config.sh
+t1301-shared-repo.sh
+t1305-config-include.sh
+t1309-early-config.sh
+t1400-update-ref.sh
+t1402-check-ref-format.sh
+t1403-show-ref.sh
+t1405-main-ref-store.sh
+t1406-submodule-ref-store.sh
+t1407-worktree-ref-store.sh
+t1408-packed-refs.sh
+t1410-reflog.sh
+t1411-reflog-show.sh
+t1413-reflog-detach.sh
+t1414-reflog-walk.sh
+t1416-ref-transaction-hooks.sh
+t1430-bad-ref-name.sh
+t1450-fsck.sh
+t1500-rev-parse.sh
+t1503-rev-parse-verify.sh
+t1505-rev-parse-last.sh
+t1506-rev-parse-diagnosis.sh
+t1507-rev-parse-upstream.sh
+t1508-at-combinations.sh
+t1511-rev-parse-caret.sh
+t1512-rev-parse-disambiguation.sh
+t1513-rev-parse-prefix.sh
+t1514-rev-parse-push.sh
+t1700-split-index.sh
+t2007-checkout-symlink.sh
+t2009-checkout-statinfo.sh
+t2010-checkout-ambiguous.sh
+t2011-checkout-invalid-head.sh
+t2012-checkout-last.sh
+t2015-checkout-unborn.sh
+t2017-checkout-orphan.sh
+t2020-checkout-detach.sh
+t2022-checkout-paths.sh
+t2023-checkout-m.sh
+t2024-checkout-dwim.sh
+t2027-checkout-track.sh
+t2030-unresolve-info.sh
+t2060-switch.sh
+t2070-restore.sh
+t2106-update-index-assume-unchanged.sh
+t2400-worktree-add.sh
+t2401-worktree-prune.sh
+t2402-worktree-list.sh
+t2405-worktree-submodule.sh
+t3040-subprojects-basic.sh
+t3200-branch.sh
+t3201-branch-contains.sh
+t3202-show-branch-octopus.sh
+t3203-branch-output.sh
+t3204-branch-name-interpretation.sh
+t3205-branch-color.sh
+t3206-range-diff.sh
+t3210-pack-refs.sh
+t3211-peel-ref.sh
+t3301-notes.sh
+t3302-notes-index-expensive.sh
+t3303-notes-subtrees.sh
+t3304-notes-mixed.sh
+t3308-notes-merge.sh
+t3320-notes-merge-worktrees.sh
+t3400-rebase.sh
+t3402-rebase-merge.sh
+t3403-rebase-skip.sh
+t3405-rebase-malformed.sh
+t3406-rebase-message.sh
+t3407-rebase-abort.sh
+t3408-rebase-multi-line.sh
+t3409-rebase-preserve-merges.sh
+t3412-rebase-root.sh
+t3413-rebase-hook.sh
+t3415-rebase-autosquash.sh
+t3416-rebase-onto-threedots.sh
+t3418-rebase-continue.sh
+t3419-rebase-patch-id.sh
+t3420-rebase-autostash.sh
+t3423-rebase-reword.sh
+t3427-rebase-subtree.sh
+t3430-rebase-merges.sh
+t3431-rebase-fork-point.sh
+t3432-rebase-fast-forward.sh
+t3434-rebase-i18n.sh
+t3435-rebase-gpg-sign.sh
+t3436-rebase-more-options.sh
+t3500-cherry.sh
+t3501-revert-cherry-pick.sh
+t3502-cherry-pick-merge.sh
+t3503-cherry-pick-root.sh
+t3504-cherry-pick-rerere.sh
+t3505-cherry-pick-empty.sh
+t3506-cherry-pick-ff.sh
+t3507-cherry-pick-conflict.sh
+t3508-cherry-pick-many-commits.sh
+t3509-cherry-pick-merge-df.sh
+t3512-cherry-pick-submodule.sh
+t3600-rm.sh
+t3701-add-interactive.sh
+t3901-i18n-patch.sh
+t3903-stash.sh
+t3910-mac-os-precompose.sh
+t4014-format-patch.sh
+t4015-diff-whitespace.sh
+t4017-diff-retval.sh
+t4038-diff-combined.sh
+t4041-diff-submodule-option.sh
+t4048-diff-combined-binary.sh
+t4052-stat-output.sh
+t4056-diff-order.sh
+t4057-diff-combined-paths.sh
+t4061-diff-indent.sh
+t4066-diff-emit-delay.sh
+t4068-diff-symmetric-merge-base.sh
+t4103-apply-binary.sh
+t4108-apply-threeway.sh
+t4121-apply-diffs.sh
+t4122-apply-symlink-inside.sh
+t4150-am.sh
+t4200-rerere.sh
+t4201-shortlog.sh
+t4202-log.sh
+t4203-mailmap.sh
+t4204-patch-id.sh
+t4207-log-decoration-colors.sh
+t4208-log-magic-pathspec.sh
+t4214-log-graph-octopus.sh
+t4216-log-bloom.sh
+t4253-am-keep-cr-dos.sh
+t4257-am-interactive.sh
+t5150-request-pull.sh
+t5304-prune.sh
+t5305-include-tag.sh
+t5312-prune-corruption.sh
+t5317-pack-objects-filter-objects.sh
+t5322-pack-objects-sparse.sh
+t5323-pack-redundant.sh
+t5400-send-pack.sh
+t5401-update-hooks.sh
+t5402-post-merge-hook.sh
+t5403-post-checkout-hook.sh
+t5404-tracking-branches.sh
+t5405-send-pack-rewind.sh
+t5407-post-rewrite-hook.sh
+t5410-receive-pack-alternates.sh
+t5500-fetch-pack.sh
+t5501-fetch-push-alternates.sh
+t5502-quickfetch.sh
+t5503-tagfollow.sh
+t5504-fetch-receive-strict.sh
+t5505-remote.sh
+t5506-remote-groups.sh
+t5509-fetch-push-namespaces.sh
+t5510-fetch.sh
+t5511-refspec.sh
+t5512-ls-remote.sh
+t5514-fetch-multiple.sh
+t5516-fetch-push.sh
+t5517-push-mirror.sh
+t5518-fetch-exit-status.sh
+t5519-push-alternates.sh
+t5520-pull.sh
+t5521-pull-options.sh
+t5523-push-upstream.sh
+t5526-fetch-submodules.sh
+t5527-fetch-odd-refs.sh
+t5528-push-default.sh
+t5529-push-errors.sh
+t5530-upload-pack-error.sh
+t5531-deep-submodule-push.sh
+t5533-push-cas.sh
+t5534-push-signed.sh
+t5537-fetch-shallow.sh
+t5538-push-shallow.sh
+t5539-fetch-http-shallow.sh
+t5540-http-push-webdav.sh
+t5541-http-push-smart.sh
+t5542-push-http-shallow.sh
+t5543-atomic-push.sh
+t5545-push-options.sh
+t5548-push-porcelain.sh
+t5550-http-fetch-dumb.sh
+t5551-http-fetch-smart.sh
+t5552-skipping-fetch-negotiator.sh
+t5553-set-upstream.sh
+t5561-http-backend.sh
+t5570-git-daemon.sh
+t5571-pre-push-hook.sh
+t5572-pull-submodule.sh
+t5580-unc-paths.sh
+t5581-http-curl-verbose.sh
+t5582-fetch-negative-refspec.sh
+t5601-clone.sh
+t5604-clone-reference.sh
+t5605-clone-local.sh
+t5606-clone-options.sh
+t5607-clone-bundle.sh
+t5608-clone-2gb.sh
+t5609-clone-branch.sh
+t5610-clone-detached.sh
+t5611-clone-config.sh
+t5612-clone-refspec.sh
+t5614-clone-submodules-shallow.sh
+t5616-partial-clone.sh
+t5617-clone-submodules-remote.sh
+t5700-protocol-v1.sh
+t5701-git-serve.sh
+t5702-protocol-v2.sh
+t5703-upload-pack-ref-in-want.sh
+t5801-remote-helpers.sh
+t6000-rev-list-misc.sh
+t6001-rev-list-graft.sh
+t6004-rev-list-path-optim.sh
+t6006-rev-list-format.sh
+t6007-rev-list-cherry-pick-file.sh
+t6008-rev-list-submodule.sh
+t6009-rev-list-parent.sh
+t6012-rev-list-simplify.sh
+t6013-rev-list-reverse-parents.sh
+t6016-rev-list-graph-simplify-history.sh
+t6017-rev-list-stdin.sh
+t6018-rev-list-glob.sh
+t6019-rev-list-ancestry-path.sh
+t6030-bisect-porcelain.sh
+t6040-tracking-info.sh
+t6050-replace.sh
+t6101-rev-parse-parents.sh
+t6110-rev-list-sparse.sh
+t6111-rev-list-treesame.sh
+t6112-rev-list-filters-objects.sh
+t6120-describe.sh
+t6200-fmt-merge-msg.sh
+t6302-for-each-ref-filter.sh
+t6400-merge-df.sh
+t6402-merge-rename.sh
+t6404-recursive-merge.sh
+t6405-merge-symlinks.sh
+t6406-merge-attr.sh
+t6407-merge-binary.sh
+t6409-merge-subtree.sh
+t6411-merge-filemode.sh
+t6412-merge-large-rename.sh
+t6413-merge-crlf.sh
+t6414-merge-rename-nocruft.sh
+t6415-merge-dir-to-symlink.sh
+t6416-recursive-corner-cases.sh
+t6417-merge-ours-theirs.sh
+t6418-merge-text-auto.sh
+t6419-merge-ignorecase.sh
+t6422-merge-rename-corner-cases.sh
+t6425-merge-rename-delete.sh
+t6427-diff3-conflict-markers.sh
+t6430-merge-recursive.sh
+t6432-merge-recursive-space-options.sh
+t6433-merge-toplevel.sh
+t6434-merge-recursive-rename-options.sh
+t6436-merge-overwrite.sh
+t6437-submodule-merge.sh
+t6439-merge-co-error-msgs.sh
+t6501-freshen-objects.sh
+t7003-filter-branch.sh
+t7004-tag.sh
+t7030-verify-tag.sh
+t7060-wtstatus.sh
+t7063-status-untracked-cache.sh
+t7102-reset.sh
+t7113-post-index-change-hook.sh
+t7201-co.sh
+t7400-submodule-basic.sh
+t7403-submodule-sync.sh
+t7406-submodule-update.sh
+t7407-submodule-foreach.sh
+t7409-submodule-detached-work-tree.sh
+t7417-submodule-path-url.sh
+t7501-commit-basic-functionality.sh
+t7502-commit-porcelain.sh
+t7503-pre-commit-and-pre-merge-commit-hooks.sh
+t7504-commit-msg-hook.sh
+t7505-prepare-commit-msg-hook.sh
+t7508-status.sh
+t7510-signed-commit.sh
+t7512-status-help.sh
+t7517-per-repo-email.sh
+t7600-merge.sh
+t7606-merge-custom.sh
+t7608-merge-messages.sh
+t7610-mergetool.sh
+t7611-merge-abort.sh
+t7612-merge-verify-signatures.sh
+t7614-merge-signoff.sh
+t7701-repack-unpack-unreachable.sh
+t7800-difftool.sh
+t7810-grep.sh
+t8001-annotate.sh
+t8003-blame-corner-cases.sh
+t8004-blame-with-conflicts.sh
+t9001-send-email.sh
+t9100-git-svn-basic.sh
+t9145-git-svn-master-branch.sh
+t9151-svn-mergeinfo.sh
+t9155-git-svn-fetch-deleted-tag.sh
+t9156-git-svn-fetch-deleted-tag-2.sh
+t9163-git-svn-reset-clears-caches.sh
+t9169-git-svn-dcommit-crlf.sh
+t9300-fast-import.sh
+t9301-fast-import-notes.sh
+t9302-fast-import-unpack-limit.sh
+t9350-fast-export.sh
+t9351-fast-export-anonymize.sh
+t9400-git-cvsserver-server.sh
+t9401-git-cvsserver-crlf.sh
+t9402-git-cvsserver-refs.sh
+t9500-gitweb-standalone-no-errors.sh
+t9501-gitweb-standalone-http-status.sh
+t9502-gitweb-standalone-parse-output.sh
+t9600-cvsimport.sh
+t9601-cvsimport-vendor-branch.sh
+t9602-cvsimport-branches-tags.sh
+t9603-cvsimport-patchsets.sh
+t9800-git-p4-basic.sh
+t9801-git-p4-branch.sh
+t9806-git-p4-options.sh
+t9807-git-p4-submit.sh
+t9811-git-p4-label-import.sh
+t9903-bash-prompt.sh