threads / discuss / 61122

Name for initial branch is ignored when repository is cloned with SSH

Subject: Name for initial branch is ignored when repository is cloned with SSH

## tl;dr

3 messages between Mar 15, 2024 and Mar 15, 2024.

replies: 2people: 3as markdown or json

Yasuhiro Kimura· Mar 15, 2024, 01:49 UTC · lore
What did you do before the bug happened? (Steps to reproduce your issue)
1. git init --bare --initial-branch=main /somewhere/test.git
2. git clone ssh://hostname/somewhere/test.git
3. cd test
4. echo foo > foo.txt
5. git add foo.txt
6. git commit -m 'Add foo.txt'
7. git branch -v
What did you expect to happen? (Expected behavior)
% git branch -v
* main 1bd6499 [gone] Add foo.txt
%
What happened instead? (Actual behavior)
% git branch -v
* master 3f0b875 [gone] Add foo.txt
% 
What's different between what you expected and what actually happened?

I expect the change is committed to 'main' branch. But actually it is committed to 'master' branch.

Anything else you want to add:
If I change step 2 as following,
2'. git clone /somewhere/test.git
then I get expected behavior.

[System Info] git version: git version 2.44.0 cpu: x86_64 no commit associated with this build sizeof-long: 8 sizeof-size_t: 8 shell-path: /bin/sh uname: Linux 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 compiler info: gnuc: 12.2 libc info: glibc: 2.36 $SHELL (typically, interactive shell): /bin/zsh

[Enabled Hooks]
Jeff King· Mar 15, 2024, 05:49 UTC · re: Yasuhiro Kimura · lore

Re: Name for initial branch is ignored when repository is cloned with SSH

On Fri, Mar 15, 2024 at 10:49:39AM +0900, Yasuhiro Kimura wrote:
Show 10 quoted lines
> I expect the change is committed to 'main' branch. But actually it is
> committed to 'master' branch.
> 
> Anything else you want to add:
> 
> If I change step 2 as following,
> 
> 2'. git clone /somewhere/test.git
> 
> then I get expected behavior.
I suspect you are running afoul of two things:
  1. When cloning a totally empty repository, detecting the destination
     of the unborn HEAD requires a protocol extension. This extension
     was implemented only for Git's v2 protocol, not for v0.
  2. Git should automatically use v2 in most cases these days. But it
     does so by probing the server in a backwards-compatible way to see
     if it also supports v2. For ssh, that probe happens by passing a
     special environment variable. However, the default config for many
     ssh servers refuses unknown variables. For OpenSSH, you'd want to
     add:
       AcceptEnv GIT_PROTOCOL
     to your sshd_config.

You can verify the protocol in use by running your clone with GIT_TRACE_PACKET=1 in the environment. For v0, you'll see either a pair of empty flush packets (for older versions of the server):

  packet:        clone< 0000
  packet:        clone> 0000
or a single-line capabilities faux-ref like:
  packet:        clone< 00000... capabilities^{}\0multi_ack thin-pack side-band etc...

For v2, the server will respond with a multi-line capabilities list, starting with the version:

  packet:        clone< version 2

Assuming my guess is right, I think everything here is working as designed, though obviously it's not a great outcome (and changing the server-side config may not be an option for everyone).

Some possible things we could do to make it better:
  a. teach v0 the same "unborn" extension that v2 knows (or maybe even
     the existing symref extension would work on the capabilities line?)
     This probably wouldn't be too hard, but I think there are many
     other capabilities that v0 would still lack, so it's kind of a
     losing battle.
  b. as v0-only servers become more and more rare, it would be nice if
     the client could start assuming v2 by default, rather than probing.
     But I don't think this quite works, because it is the server who
     starts speaking v2 first (and it won't do so without seeing that
     probe). You could imagine the client invoking "git-upload-pack
     --version=2" on the server, but of course no server implements that
     option yet (and if you added it, you'd have to wait for the server
     side support to percolate).
  c. provide more ways to get the v2 probe information to the server.
     For ssh, one obvious thing is to invoke "GIT_PROTOCOL=version=2
     git-upload-pack" on the server, using the shell to set the
     environment variable rather than passing it over ssh. We didn't do
     that when we added v2 because there are backwards compatibility
     failure modes (e.g., servers where the shell is not regular 'sh' or
     where there might not be a shell at all, or restricted environments
     which allow "git-upload-pack" to run but nothing else).

But maybe taking (b) and (c) together, we could add an option to ask the client to pass the protocol variable via the shell. It doesn't have to work everywhere because you'd enable it manually for servers where you know it would work (and people configuring restricted servers probably already made the necessary ssh config changes).

Of course the biggest challenging is users realizing that they need to do something to enable v2 in the first place. For the most part v0 just works, and so it is easy to not realize you're still using it.

-Peff
Marc Branchaud· Mar 15, 2024, 13:49 UTC · re: Jeff King · lore

sshd support for Git protocol v2 (was: Re: Name for initial branch is ignored when repository is cloned with SSH)

On 2024-03-15 01:49, Jeff King wrote:
Show 29 quoted lines
> On Fri, Mar 15, 2024 at 10:49:39AM +0900, Yasuhiro Kimura wrote:
> 
>> I expect the change is committed to 'main' branch. But actually it is
>> committed to 'master' branch.
>>
>> Anything else you want to add:
>>
>> If I change step 2 as following,
>>
>> 2'. git clone /somewhere/test.git
>>
>> then I get expected behavior.
> 
> I suspect you are running afoul of two things:
> 
>    1. When cloning a totally empty repository, detecting the destination
>       of the unborn HEAD requires a protocol extension. This extension
>       was implemented only for Git's v2 protocol, not for v0.
> 
>    2. Git should automatically use v2 in most cases these days. But it
>       does so by probing the server in a backwards-compatible way to see
>       if it also supports v2. For ssh, that probe happens by passing a
>       special environment variable. However, the default config for many
>       ssh servers refuses unknown variables. For OpenSSH, you'd want to
>       add:
> 
>         AcceptEnv GIT_PROTOCOL
> 
>       to your sshd_config.

I've been the corporate Git Master here for over 15 years, and I was completely unaware of this until today. Thanks for pointing it out! Our internal Git host now finally supports v2!

		M.

← back to recent threads