Subject: Re: [PATCH] revisions: add @{default} shorthand for default branch

From: Junio C Hamano <[email-masked]>
Date: Sat, 31 Jan 2026 11:16:11 -0800

Junio C Hamano <[email-masked]> writes:

> For those who follow the naming the upstream decided to use in
> cloned repositories, init.defaultBranch is probably the last thing
> you want to take as a hint, as these people decided to _ignore_ the
> preference of their own and instead to follow what upstream uses.
> For that, refs/remotes/origin/HEAD would be a lot more stronger
> hint.  If they call their primary branch 'trunk', these people would
> want to call theirs 'trunk'.  And for that, these people would not
> do anything with init.defaultBranch.
>
>>     git checkout $(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')
>>
>> That's uneccessary overhead, that could now be replaced with:
>>
>>     git checkout @{default}
>
> That mirrors what I wrote in the previous paragraph.  Those who
> follow the naming the upstream uses, refs/remotes/$remote/HEAD
> (here, "origin" may not be the default remote) would be a better
> hint than init.defaultBranch so calling it @{default} is misleading.

Thinking about this more, while I can see how using the
remote-tracking branch that is pointed by refs/remotes/origin/HEAD
may make sense, I see no sensible reason why mapping that to a local
branch name by simply stripping refs/remotes/origin/ makes sense.

Stepping back a bit, the workflow that may be helped by being able
to learn the value of "refs/remotes/origin/HEAD", in addition to
@{upstream} and @{push} would be laid out like the following:

 * The project uses 'main' as its primary integration branch.  After
   you clone it, refs/remotes/origin/HEAD points at their 'main'
   (i.e., you have refs/remotes/origin/main keeping track of it),
   "git fetch" updates refs/remotes/origin/HEAD when they change
   their naming if you are using a recent enough version of Git.

 * The project uses topic based workflow.  The idea is each topic
   gets its own topic branch, e.g., 'feature', and participants join
   forces to bring it to perfection, after which 'main' merges the
   completed 'feature'.

 * You, as a participant of this project, fork your own 'feature'
   local branch from the remote-tracking branch 'origin/feature'.
   You publish the result into a separate repository of your own,
   different from where you cloned from.  If you fetch from there, a
   remote-tracking branch 'refs/remotes/publish/feature' may be
   created in your local clone as well (assuming your publishing
   repository is called 'publish').

Now, you have @{upstream} that is their 'feature' (that is kept
track of with refs/remotes/origin/feature remote-tracking branch
in your local clone), @{push} that is refs/remotes/publish/feature.
Comparing your local progress against these two are useful to see
where you are, how far you came, and how much others you see in
@{upstream} may have diverged.

In addition, the overall "progress" of the project is how far
@{upstream} has come relative to refs/remotes/origin/main, which is
the ultimate target that you and your fellow project participants
want to see @{upstream} gets merged, is a useful thing to keep track
of.

So in that sense, I do understand why somebody may find it useful if
there is a handy short-hand for refs/remotes/origin/main (or
whichever branch is pointed at by refs/remotes/origin/HEAD) in the
above picture.  And refs/remotes/origin/HEAD already does have a
handy short-hand, which is 'origin' ;-).

But step back and notice that there is no mention of local 'main' in
the above layout?

As Kristoffer said in another message [*1*], I would too expect that
people would not work on their 'main' (or have their 'main' track
the upstream's 'main').  So the utility of the piping to sed we saw
above is dubious, unless we are talking about quite different
workflow, but I do not think of what that other workflow would look
like that makes a neutral synonym for 'main' useful.

So, enough about refs/remotes/origin/HEAD.  Back to your original
idea of using init.defaultBranch.

In one of your other messages [*2*], you reported that you were
having trouble with repositories without init.defaultBranch
configuration variable cofigured.

Doesn't repo_default_branch_name() do the right thing without being
noisy at all even in a repository without that configured, as the
function will fall back to the built-in default?  While I do not
think of a workflow in which a handy access to the value the
function gives would be so useful that it deserves a short-hand, it
would be a reasonable candidate of what to be called "@{default}",
if it proves useful, I would think.

> I am not good at naming things, so instead of calling it @{primary}
> let's call it @{dumbo}.  With the realization that what branch
> refs/remotes/$remote/HEAD points at is a good source of hint, I
> actually think $branch@{dumbo} does make sense, and @{dumbo} should
> be a short-hand for $branch@{dumbo} where the name of the current
> branch is substituted for $branch (i.e. similar to @{push}, I
> suppose).  As you may be interacting with two sets of branches that
> go to two different remotes.
>
> In any case, it is very different from what you implemented as the
> @{default} in your patch.

[References]

*1* https://lore.kernel.org/git/[email-masked]/

*2* https://lore.kernel.org/git/[email-masked]/