Hub: Request: use merge button API

Created on 19 May 2017  Ā·  26Comments  Ā·  Source: github/hub

Github now allows the merge of PRs with their API just like if we had pressed the merge button. Using this with hub should be desirable to a lot of people, so opening the issue to keep track of progress/interest.

Relevant documentation: https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button

feature pull-request

Most helpful comment

How about

$ hub pr merge --strategy=[merge|squash|rebase] 212

Takes care of merging PR number 212 with the requested strategy without modifying the local repository.

All 26 comments

Wondering how this would be different from just doing a git merge.

A PR is just a branch (as far as git is concerned), and a git checkout master; git merge mybranch; git push origin will close the PR in GitHub, just as if you pressed the merge button.

And if hub had a command, what would it be? I envision the process would be something like git pull-request --merge; git checkout master; git pull origin.

It doesn't seem like much of an improvement.

The major difference is in how it looks in the interface. If you deal with a lot of git and Github newbies (which is the case with homebrew-cask), the difference between seeing your issue closed or merged means a lot. Itā€™s the difference between them understanding the contribution was accepted, or thinking it was rejected.

That is not a small difference.

Also (just noticed), if you directly commit something from a PR it appears to not take into account the ā€œCloses #0000ā€ messages in PRs, meaning it will not auto-close linked issues.

I see no significant difference in the UI. I am not sure what you mean.

https://github.com/pudge/mergetest/pull/1
https://github.com/pudge/mergetest/pull/2

In the latter, I simply did what I said in the comment: merged to master on the command line, then pushed. That's it!

(As to issues, I was able to similarly make it work just fine. I didn't even need a PR ... just said "closes ..." in my merge commit message.)

In the latter, I simply did what I said in the comment: merged to master on the command line, then pushed. That's it!

And in the process created merge commits. The merge button allows you to squash the commits. If you do that via the CLI, the issue shows as closed.

just said "closes ..." in my merge commit message.

The point is not us adding the message in the commit. Itā€™s about a user adding the message in their PR and us merging it.

Ah. I didn't know you meant squash. Of course that won't work as easily since you're technically not merging the commits in the branch (which is why I don't use squashing often).

And it doesn't have to be in the merge commit comment ... can be in any comment, as long as it gets in the merge. I think you're talking about a comment on the PR itself. And yeah that isn't being merged.

If you like to squash I can see it. I don't, so it's not highly useful for me.

I didn't know you meant squash.

Apologies; shouldā€™ve been more specific. But the merge button has three different options and I was thinking about all at once.

I should've thought of the other types of merges. No worries.

I too would like to see this. Merging is one of the few things I still have to navigate to the site in order to do.

Iā€™ll keep this open for others, but I no longer have a need for the feature. I ended up building my own solution (installable via brew install vitorgalvao/tiny-scripts/climergebutton).

A few more important differences between hub merge and the GitHub merge button/API:

  • hub merge works with the local copies of the head/base branches, which might be behind/ahead of the remote head/base branches. So we can't be certain hub merge will be equivalent to the GitHub merge button/API.
  • The GitHub PR has a preconfigured base, which unlike the GitHub merge button/API, hub merge will not consider.

I think these differences justify a use case for a hub command that works with the GitHub merge button/API.

@vitorgalvao Thanks for building climergebutton! I've only tried it once so far but it seems to work šŸ˜„

How about

$ hub pr merge --strategy=[merge|squash|rebase] 212

Takes care of merging PR number 212 with the requested strategy without modifying the local repository.

Perfect!

After some consideration, I have decided thatā€”for nowā€”this is best implemented in user scripts, rather than maintained in hub core. Now that there is a new hub api command, I will close this feature request and leave implementing this as an exercise to the reader. https://github.com/github/hub/releases/tag/v2.8.3 https://github.com/github/hub/pull/2016

For example:

hub api -XPUT repos/{owner}/{repo}/pulls/1483/merge \
  -f merge_method=squash -f commit_title='Yay squashed merge!'

Thank you for suggesting!

So now we have two options: climergebutton or hub api.

Both options require a full URL for the PR. It would be good to abstract this further so that only the PR ID/number was necessary. Here's a start:

function merge () {
    ID=$1
    # https://unix.stackexchange.com/questions/225943/except-the-1st-argument/225951#225951
    REST=${@:2}

    PR_PATH="repos/{owner}/{repo}/pulls/$ID"

    echo "Merging $ID"

    # https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button
    echo $REST | xargs hub api -XPUT $PR_PATH/merge
}

Also, I'm keen to build shell completions for this, since it relies on PR IDs which are hard to memorizeā€”I usually work in terms of branch names. My thinking is that the completion list should appear similar to hub pr list, and when an item is selected, the PR ID/number would be inserted. I made a start on Zsh completions:

image

#compdef git-merge-pr

_git-merge-pr () {
    # Note: requires jq to be installed

    # https://developer.github.com/v3/pulls/#list-pull-requests
    # hub api /repos/{owner}/{repo}/pulls
    PRS=$(
        hub api /repos/{owner}/{repo}/pulls \
            | jq 'map({title, number, head})'
    )

    # Alternatively, use `hub pr` instead
    # PRS=$(hub pr list -f '{ "number": %I, "title": "%t" }%n')

    PRS_DETAIL_STRING=$(
        echo $PRS \
            | jq --raw-output 'map((.number | tostring) + ": " + .head.ref + ", " + .title) | .[]'
    )

    # https://unix.stackexchange.com/questions/29724/how-to-properly-collect-an-array-of-lines-in-zsh
    # TODO: avoid leaking IFS?
    IFS=$'\n' PRS_DETAIL=($(echo "$PRS_DETAIL_STRING"))

    PRS_NUMBER=($(echo $PRS | jq --raw-output 'map(.number) | .[]'))

    compadd -l -d PRS_DETAIL -a -- PRS_NUMBER
}

https://gist.github.com/OliverJAsh/06ac17b9dacff7a15f5c084c11cfd57d

I'm keen to hear other people's thoughts on this. I'd be happy to collaborate on this and get something published for others to use.

@OliverJAsh This looks awesome! I was thinking to start a separate repository that collects relatively short scripts like these to demonstrate building one's own scripts on top of hub (mostly to demonstrate the new hub api command, but other hub commands can be used of course). This would be a perfect fit for such a collection šŸ˜

Both options require a full URL for the PR. It would be good to abstract this further so that only the PR ID/number was necessary.

Iā€™m willing to add that feature. There are also other things I want to add, but Iā€™m more willing to if I know other people use the script.

How would you suggest that work, exactly? Iā€™m imagining that if you give only a number as an argument, it would:

  1. Check if inside a git repo. If not, abort; if yes, continue.
  2. Get the origin remote.
  3. Act on that one.

Is that what you were thinking?

@mislav Nice! I polished it a bit and shared a script here: https://gist.github.com/OliverJAsh/06ac17b9dacff7a15f5c084c11cfd57d

I would also like to add further wrappers to delete local/remote head branches and update (pull) the local base branch, however this is specific to my workflow, so they would probably be added as options, e.g.:

  1. Delete local/remote head branches: --delete-head-branches
  2. Update (pull) local base branch: --update-local-base-branch
  3. 1 + 2 = --sync-branches

@vitorgalvao

There are also other things I want to add, but Iā€™m more willing to if I know other people use the script.

What were you thinking?

Is that what you were thinking?

Yes! Although we get step 1/2 for free by using hub api, since it automatically replaces {owner} and {repo}.

Also I realised my completion script can be re-used for the hub merge CLI.

What were you thinking?

Currently I ask for an API token. I can make it so the script asks for (and saves) a token for itself, wich will streamline use.

Yes! Although we get step 1/2 for free by using hub api

But thatā€™s the easy part. Since I already did the hard work in climergebutton, thereā€™s no point in adding a dependency on hub. I also wonā€™t depend on jq; Iā€™d rather rewrite the script in ruby and get JSON support for free.

@OliverJAsh , amazing work, thank you!
I have a question about how to run git-merge-pr script after a branch has been selected?
I get this error:
git: 'merge-pr' is not a git command. See 'git --help'.
Thanks

Nevermind. Just added to the PATH. Thanks again

@mislav

I was thinking to start a separate repository that collects relatively short scripts

Let me know if you do do this!

@OliverJAsh (and others): the repo is now live and accepting your contributions! https://github.com/mislav/hub-api-utils/blob/master/bin/hub-pr-merge

@mislav script works great!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stsewd picture stsewd  Ā·  4Comments

kentcdodds picture kentcdodds  Ā·  4Comments

Kristinita picture Kristinita  Ā·  4Comments

xxmyjk picture xxmyjk  Ā·  4Comments

nicksergeant picture nicksergeant  Ā·  3Comments