[PATCH 0/3] Add support for per-remote and per-namespace SSH options
- From
Wesley Schwengle <wesleys@opperschaap.net>
- Date
- Mar 26, 2026, 23:37 UTC
- Message-ID
- <20260326233739.2911354-1-wesleys@opperschaap.net>
With this changeset applied git is now aware of `sshIdentityFiles' and `sshOpts'. This allows users to have multiple accounts on the same forges. A common problem within the developer community. This problem is often solved by hacking in one's `.ssh/config' and changing hostname URIs to ensure the correct key is being used.
For years I had zsh wrapper script that was used as the `core.sshCommand' and is a reference implementation of this change.
In order of importance:
Configuration on the remotes itself. This is easy, straight forward and should allow people to get it to work quickly:
* `remote.*.sshIdentityFile' and `remote.*.sshOpts'
Configuration set on owner/path style. This is to support `includeIf` configuration management. For example, a git-forge that host both employer/client repo's. Eg, `git@gitlab.com/waterkip/git.git' and `git@gitlab.com/corp/git.git' would have something configured as:
* `core.sshIdentityFile.*', eg
[core "sshIdentityFile"]
waterkip = ~/.ssh/id_ed25519_me
corp = ~/.ssh/id_ed25519_corporateAnd finally, a global override for everything:
* `core.sshIdentityFile' and `core.sshOpts'
I stayed within the `core' namespace, mainly because `core.sshCommand'. I'm happy to move it to `ssh' or something similar. It would perhaps make `ssh.*.sshIdentifyFile' more structured, because now that's split between two core subsections.
The following assumptions have been made to make it safe and sound for users. When an `sshIdentityFile' is used and no `sshOpts' are configured git will inject `-F /dev/null' to prevent cycling over all sshIdentityFiles a user has in their `.ssh/config'. When a user configures `sshOpts', these take precedence and a user itself is responsible for setting `-F /dev/null'.
Separate push/pull URIs are not supported by the feature. The biggest problem with this is that I don't know how to properly configure them with the namespace constraints. `remote.*.xyz' is as deep as git can go and a push/pull would require additional configuration. I filed it under edge-case.
There are two new structs introduced: `ssh_options' and `cnx_context'. They are there to limit the amount of argument passing down the wire. And this is especially true for `ssh_options' because it keeps `push_ssh_options' dumb.
Wesley Schwengle (3): connect: Rename name to command in connect_git() connect: Add transport->remote->name to git_connect() connect: Add support for per-remote and per-namespace SSH options
Documentation/config/core.adoc | 22 ++++ Documentation/config/remote.adoc | 9 ++ builtin/fetch-pack.c | 2 +- builtin/send-pack.c | 2 +- connect.c | 144 ++++++++++++++++++++-- connect.h | 2 +- t/t57xx-ssh-options-config.sh | 198 +++++++++++++++++++++++++++++++ transport.c | 9 +- 8 files changed, 375 insertions(+), 13 deletions(-) create mode 100755 t/t57xx-ssh-options-config.sh
-- 2.53.0.722.g8e572876c5