Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: Different git URLs for fetch and push #5611

Open
dconeybe opened this issue Feb 6, 2025 · 3 comments
Open

FR: Different git URLs for fetch and push #5611

dconeybe opened this issue Feb 6, 2025 · 3 comments
Labels
enhancement New feature or request

Comments

@dconeybe
Copy link

dconeybe commented Feb 6, 2025

Is your feature request related to a problem? Please describe.
I regularly use different URLs for fetching from and pushing to my git repositories. Specfically, I like to use the https URL for fetching and the ssh url for pushing. With this setup I can fetch from the remote even in a shell where ssh-agent is not set up (since fetching https urls for public github repos does not require authentication). But then when I want to push I must use the ssh url since the repos that I frequently use require pushes to be authenticated via ssh keys. Therefore, the extra burden of setting up ssh-agent is only needed when I actually want to push; simply fetching does not require ssh-agent setup.

For example, when using git, here is how I would clone a repo and configure the easier-to-use https url for fetching, but the more-difficult-to-use-but-required ssh url for pushing:

$ git clone https://github.com/firebase/firebase-js-sdk
Cloning into 'firebase-js-sdk'...
$ cd firebase-js-sdk
$ git remote set-url --push origin [email protected]:firebase/firebase-js-sdk.git
$ git remote -v
origin  https://github.com/firebase/firebase-js-sdk (fetch)
origin  [email protected]:firebase/firebase-js-sdk.git (push)

With this setup, running git fetch works just fine, even though ssh-agent isn't running, because it's using the https url, which doesn't require authentication:

$ git fetch
From https://github.com/firebase/firebase-js-sdk
 * [new branch]          foo        -> origin/foo

But running git push requests the ssh key's passphrase, as expected, because it's using the ssh url, which is required by the repo for pushes:

$ git push
Enter passphrase for key '/Users/foobar/.ssh/id_ed25519': 
...
To github.com:firebase/firebase-js-sdk.git
   5250e8006..7f6cbef22  foo -> foo

This means I only have to set up ssh-agent or enter my ssh key passphrase when it's strictly required; that is, when pushing to the repo.

Describe the solution you'd like
I'd like to see the jj command jj git remote set-url gain a --push flag to do the same thing as git remote set-url --push.

For example, I'd like to be able to run something like this (notice the --push flag, which I am proposing):

jj git remote set-url --push origin [email protected]:firebase/firebase-js-sdk.git

Additionally, the jj git remote list output should include both the push and the fetch URLs, especially if they are different. As of the latest version (0.26.0 at the time of writing) the output only includes the fetch URL, even if it is different from the push URL (see the workaround in next section an example of how the URLs can be different).

Describe alternatives you've considered
The workaround that I use is to run git directly on the git repo in the .jj directory to set the push url. This requires that I figure out or memorize the path to the git repo in the .jj directory. It works just fine, but it would be nice to just have this support built into the jj cli so I don't have to grok the .jj directory.

For example, here is how I use jj to work on the firebase-js-sdk github repository used above:

$ jj git clone https://github.com/firebase/firebase-js-sdk
Fetching into new repo in "/Users/dconeybe/tmp/firebase-js-sdk"
bookmark: main@origin                                                                                [new] untracked
Setting the revset alias `trunk()` to `main@origin`
Working copy now at: xwxwylqy 32a28fae (empty) (no description set)
Parent commit      : zqkuqqks 5250e800 main | ...
Added 2662 files, modified 0 files, removed 0 files

# Use git to set the push url on the repo in the .jj directory
$ cd firebase-js-sdk
$ git --git-dir .jj/repo/store/git remote set-url origin --push [email protected]:firebase/firebase-js-sdk.git
$ git --git-dir .jj/repo/store/git remote -v
origin  https://github.com/firebase/firebase-js-sdk (fetch)
origin  [email protected]:firebase/firebase-js-sdk.git (push)

# Fetching succeeds, as expected, because it uses the https url which does not require any authentication
$ jj git fetch
bookmark: foo@origin [new] untracked

# Pushing, however, fails, as expected, because it uses the ssh url, which requires authentication
$ jj bookmark track foo@origin
Started tracking 1 remote bookmarks.
$ jj new foo
Working copy now at: ooxmnykk c77cdb25 (empty) (no description set)
Parent commit      : zqkuqqks 5250e800 foo main | ...
$ jj bookmark move foo --to @
Moved 1 bookmarks to ooxmnykk c77cdb25 foo* | (empty) (no description set)
$  jj git push --allow-new --allow-empty-description
Changes to push to origin:
  Move forward bookmark foo from 5250e80066e0 to d0ddeb03976a
Error: failed to authenticate SSH session: Unable to extract public key from private key file: Wrong passphrase or invalid/unrecognized private key file format; class=Ssh (23)
Hint: Jujutsu uses libssh2, which doesn't respect ~/.ssh/config. Does `ssh -F /dev/null` to the host work?

# After setting up ssh-agent, the push now succeeds (as expected)
$ ssh-add
Enter passphrase for /Users/foobar/.ssh/id_ed25519: 
Identity added: /Users/foobar/.ssh/id_ed25519 (foobar@foobar-linux)
$ jj git push --allow-new --allow-empty-description
Changes to push to origin:
  Move forward bookmark foo from 5250e80066e0 to d0ddeb03976a
...

Note how jj git fetch succeeded. This is because fetch used the https url, which does not require any sort of authentication. Also note how the jj git push command initially failed (as expected) because it used the ssh url. After running ssh-add the push command succeeded (as expected). This is the workflow that I like because it makes it easy to fetch and I only have to set up ssh-agent when I actually want to push something up to the remote repository.

Another workaround suggested in #5611 (comment) is to use an alternate remote for pushing. This also works just fine. The only drawback is that it forces me to come up with a name for the 2nd remote ("origin_ssh" in this case), and that is a notoriously hard problem in computer science (source).

Here's what it looks like though. It's exactly the same as the bash shell snippet above, except that the raw git --git-dir=... commands above are replaced by:

$ jj git remote add origin_ssh [email protected]:firebase/firebase-js-sdk.git
$ jj config set --repo git.push origin_ssh

Additional context
Since there is a workaround (i.e. running git --git-dir .jj/repo/store/git remote set-url origin --push <url>) this isn't super-high priority or blocking or anything. But for me it's a nice-to-have.

@dconeybe dconeybe added the enhancement New feature or request label Feb 6, 2025
@PhilipMetzger
Copy link
Contributor

I think this is achievable today with https://jj-vcs.github.io/jj/latest/config/#default-remotes-for-jj-git-fetch-and-jj-git-push, but I'm not sure.

@dconeybe
Copy link
Author

dconeybe commented Feb 6, 2025

I think this is achievable today with https://jj-vcs.github.io/jj/latest/config/#default-remotes-for-jj-git-fetch-and-jj-git-push, but I'm not sure.

Ahh yes that does indeed work. I've update the OP of this issue to mention it as another workaround. I'd still like to leave this issue opened, though, since this workaround is still slightly sub-optimal IMO.

Here is the paragraph I added to the OP:

Another workaround suggested in #5611 (comment) is to use an alternate remote for pushing. This also works just fine. The only drawback is that it forces me to come up with a name for the 2nd remote ("origin_ssh" in this case), and that is a notoriously hard problem in computer science (source).

Here's what it looks like though. It's exactly the same as the bash shell snippet above, except that the raw git --git-dir=... commands above are replaced by:

$ jj git remote add origin_ssh [email protected]:firebase/firebase-js-sdk.git
$ jj config set --repo git.push origin_ssh

@PhilipMetzger
Copy link
Contributor

I think this FR can be summarized as: Add support for fetch and push URLs in jj git remote add, which will allow you to use different protocols.

Here is the paragraph I added to the OP:

Another workaround suggested in #5611 (comment) is to use an alternate remote for pushing. This also works just fine. The only drawback is that it forces me to come up with a name for the 2nd remote ("origin_ssh" in this case), and that is a notoriously hard problem in computer science (source).

Here's what it looks like though. It's exactly the same as the bash shell snippet above, except that the raw git --git-dir=... commands above are replaced by:

I think the simplest solution for you until this is implemented, is to use the above mechanism and a jj git push alias to which calls the correctly configured remote for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants