Hub: Allow specifying the git remote name for a command

Created on 19 Dec 2018  路  9Comments  路  Source: github/hub

pull-request

When raising PRs, by default I want to raise a PR from the branch my current HEAD is tracking (which is on the fork remote) to the HEAD branch on the upstream repo (i.e. the default branch for the up remote, refs/remotes/up/HEAD).

This is the current command I have to run to do this:

hub pull-request \
  -b $(git remote get-url up | 
       sed -E 's|^.*github.<company>.com[:/]([^/]+)/.*$|\1|'):$(git symbolic-ref refs/remotes/up/HEAD | 
       sed 's|^refs/remotes/up/||'
  )
  -o

This resolves to something like:

hub pull-request -b upstream_org:dev -o

I would like to be able to specify the remote name instead, so I could just do:

hub pull-request -b up/dev -o

I'm thinking hub could work out that this is a remote-tracking branch name, and resolve up/dev to upstream_org:dev.


remote create

I have the same problem with hub release create, except that here AFAICT there is no way to specify a remote name or an org name, given two remotes, neither called origin, hub just picks one at random.

hub release does take a --commitish flag, but that flag is passed directly to the GitHub API without being resolved.

This makes hub release create unusable for us, as where the tag gets created is not clear.

config feature

Most helpful comment

This makes hub release create unusable for us, as where the tag gets created is not clear.

I'm sorry this has been difficult for you! If you named your upstream git remote one of "upstream", "github", or "origin", then the commands such as hub release create should work without a hitch.

I think the default should be "origin" not "upstream". It would be nice to have a --remote flag in order to specify which remote to use when pushing the tag.

% git remote -v
james   https://github.com/JamesGlover/limber.git (fetch)
james   https://github.com/JamesGlover/limber.git (push)
origin  https://github.com/radome/limber.git (fetch)
origin  https://github.com/radome/limber.git (push)
upstream    https://github.com/sanger/limber.git (fetch)
upstream    https://github.com/sanger/limber.git (push)

% hub release create release-0.2.1-os3
https://github.com/sanger/limber/releases/tag/release-0.2.1-os3

All 9 comments

I think allowing remote/branch in at least these two places (hub pull-request --base and hub release create --commitish) and then resolving it like:

git remote get-url up | sed -E 's|.*/(\w+/\w+)|\1|' # returns org/repo

Would work. Then the target_commitish could just be the branch without the remote/ prefix:

https://github.com/github/hub/blob/ca320f401eda7881fe0cb438dd6fac5382faf286/commands/release.go#L494

For anyone else hitting this issue, I'm working around it by using:

    curl \
      -H "Authorization: token $(awk '$1 == "oauth_token:" { print $2; exit }' ~/.config/hub)" \
      -d "{\"tag_name\":\"$tag\",\"name\":\"$tag\",\"body\":\"$(bin/changelog | awk '{printf "%s\\n", $0}')\",\"draft\":true}" \
      https://api.github.<company>.com/repos/<org>/<repo>/releases

in our release notes.

Thank you for raising this issue and explaining your use-case and workarounds!

except that here AFAICT there is no way to specify a remote name or an org name, given two remotes, neither called origin, hub just picks one at random.

Yes, hub's behavior when none of the remotes is named "origin", "github", or "upstream" is not well documented (it just picks the first remote from git remote -v).

When raising PRs, by default I want to raise a PR from the branch my current HEAD is tracking (which is on the fork remote) to the HEAD branch on the upstream repo

This should, roughly, already be the default behavior of hub pull-request. The default head branch is the upstream branch where the current branch is pushed to (provided that you had used git push -u fork HEAD when initially pushing if your git config push.default is either "upstream" or "tracking"), and the default base remote is the first one found by searching for one named "upstream", "github", or "origin".

I recommend you name your fork's remote "origin" and your upstream remote (one pointing to the canonical version of the project) "upstream".

The idea for a --remote flag for various hub commands has existed for a while, and a PR was already in the works but got stalled around defining an CLI API for this (personally I would prefer to make it a global flag rather than implementing it separately for every individual command).

This makes hub release create unusable for us, as where the tag gets created is not clear.

I'm sorry this has been difficult for you! If you named your upstream git remote one of "upstream", "github", or "origin", then the commands such as hub release create should work without a hitch. I would prefer to keep the --commitish flag functionality unchanged since it already accurately reflects what the API would do: if it's a raw SHA, use that verbatim, and if it's a branch name, then look up the SHA at the tip of that branch.

I recommend you name your fork's remote "origin" and your upstream remote (one pointing to the canonical version of the project) "upstream".

Yeah, I can see that hub is currently designed around this use-case. I'd prefer not to use origin, as I find it confusing in more complex scenarios, but it's a good workaround in the meantime.

The idea for a --remote flag for various hub commands has existed for a while, and a PR was already in the works but got stalled around defining an CLI API for this (personally I would prefer to make it a global flag rather than implementing it separately for every individual command).

Yeah a hub --remote|-R <remote> pull-request flag, and maybe a ~/.config/hub option to configure would be ideal (allowing the defaults to be set per-user).

If I get round to it maybe I'll try taking a look at the hub cli and working out how one would add support global flags.

Thanks for being so responsive!

This makes hub release create unusable for us, as where the tag gets created is not clear.

I'm sorry this has been difficult for you! If you named your upstream git remote one of "upstream", "github", or "origin", then the commands such as hub release create should work without a hitch.

I think the default should be "origin" not "upstream". It would be nice to have a --remote flag in order to specify which remote to use when pushing the tag.

% git remote -v
james   https://github.com/JamesGlover/limber.git (fetch)
james   https://github.com/JamesGlover/limber.git (push)
origin  https://github.com/radome/limber.git (fetch)
origin  https://github.com/radome/limber.git (push)
upstream    https://github.com/sanger/limber.git (fetch)
upstream    https://github.com/sanger/limber.git (push)

% hub release create release-0.2.1-os3
https://github.com/sanger/limber/releases/tag/release-0.2.1-os3

Totally agree, the default should be origin, with an optional --remote parameter in the (rare) case you would _not_ want to create the release on origin.

-r, --remote <REMOTE>
:   Create the release in the repo <REMOTE> (default: origin).

Without explicit configuration, no assumptions should be made regarding remote names other than the canonical origin name, which is the Git standard and default for any cloned repository. @gibfahn for example seems to call the remote for the authoritative repo up, others may call it upstream, or may have other personal preferences (see below "About remote naming").

Examples for the release command

To create a release on origin:

$ hub release create v1.0.0

To create a release on a different remote (for example my fb fork):

$ hub release create -r fb v1.0.0
  - or -
$ hub release create --remote fb v1.0.0

Overriding the default

If someone prefers to deviate from the conventions and does _not_ want to use origin as the default remote, something similar to the concept of remote tracking branches is conceivable:

.git/config might contain:

[hub]
        defaultremote = fork

When this is set, hub commands by default would interact with the repo that fork points to.

This is similar to how different local branches can track branches on different remotes:

[branch "xyz"]
        remote = fork
        merge = refs/heads/xyz

About remote naming

It can be _confusing_ when people do not use the Git _default_ origin remote name to point to the main and authoritative repository. If that happens, you can no longer talk about the term "origin" in a group, because it would mean something different for each person. In the distributed world of Git, my fork of a repo is not any more or less special than someone else's fork - the _only_ designated "special" repo is the authoritative one that everyone uses to collaborate and fork from.

_Uniquely_ naming remotes _based on the fork they're pointing to_ (which is the behavior for several hub commands already) may be better, for example:

$ git remote -v
james   https://github.com/JamesGlover/limber.git (fetch)
james   https://github.com/JamesGlover/limber.git (push)
origin  https://github.com/sanger/limber.git (fetch)
origin  https://github.com/sanger/limber.git (push)
radome  https://github.com/radome/limber.git (fetch)
radome  https://github.com/radome/limber.git (push)

Since I rarely have more than 10 remotes in one repo, unique two character remote names (for example based on the initials of the person who forked the repo) are usually good enough for me. In any repo, I can reach my personal fork (if one exists) using the fb remote name. Of course this last part is a personal preference, but I think few people would disagree with the concept of unambiguous remote names.

Thoughts @gibfahn @mislav @radome?

I like the idea of defaultremote

@friederbluemle I like the idea of something like defaultremote configuration. When the feature described in #225 ships (long overdue; I know), I imagine it would generate default configuration for each authenticated GitHub host:

github.com:
  defaultremote: upstream, github, origin

If it's a list of names, they would be looked up in order of preference and the first one that exists would be selected. Any user of hub could change this list to what they prefer.

Finally, a remote could be explicitly set per-command with the --remote <REMOTE> flag, in which case defaultremote configuration wouldn't be consulted.

I'd really like this since currently, in our studio, I've written a series of scripts to automate some of our git workflows using hub and when a developer sets up a remote called upstream, all of a sudden, commands may stop working as intended. PRs get sent to the wrong repo, etc.

What I'd like to see is either a way to explicitly select which remote is used for API calls or be able to customize the priority that hub uses, either in config or on the CLI (or environment variable?).

What's worse is that the verbose output doesn't include this information; it just includes specifics about the API call(s) being used, but not what remote it's using to hit, so troubleshooting issues becomes a headache.

Was this page helpful?
0 / 5 - 0 ratings