Get pull request associated with a commit

I was wondering if it’s possible to get a pull request associated with a commit. With a merge-commit or squash-merging I can infer the associated pull request from the commit message, but in the case of rebase-merging the commits are directly appended to the master branch which makes this impossible. 

It seems like GitHub has a way of associating commits that have been merged using rebase-merging as can be seen in the following screenshot (all appended commits show this):

pr-number.png

I’ve been digging through the V4 and V3 API but I couldn’t find a way to associate commits with a PR. Is this somehow possible?

For more context: I’m currently working on supporting rebase-merging in Release Drafter (https://github.com/toolmantim/release-drafter/issues/106).

1 Like

Hey @timonvs, Thanks for being here! This is a great question,  you can do this using the search UI but I don’t think there is a way to do it programmatically via the API. I’ll dig a little dipper and post any updates here. Hopefully another user might have more insight into this question.

Thanks @andreagriffiths11. It’s indeed possible with the search API (https://help.github.com/articles/searching-issues-and-pull-requests/#search-by-commit-sha). For my use case however that would not work very well because I need be able to identify PRs from a bunch of commits. Doing a request for every commit would be very ineffecient and I’d quickly hit the API limits.

Ideally I’d be able to do the following GraphQL query:

  

{
  repository(owner: "awkward", name: "sketch-frontend") {
    ref(qualifiedName: "master") {
      target {
        ... on Commit {
          id
          associatedPullRequest {
            title
            number
          }
        }
      }
    }
  }
}
2 Likes

@timonvs thanks for clarifying, I believe that schema is not supported yet, but has been requested. 

I figured out how to do this using github3.py. It assumes you have cloned the repo locally.

import github3
import subprocess
import os

os.chdir('C:\\yourRepo')

github_repo_owner = '15five'
github_repo_name = 'yourRepo'
sha = '1425ca3' # replace with desired sha

# thanks to https://stackoverflow.com/questions/17818167
out = subprocess.check_output(['git', 'describe', '--all', '--contains', sha])
text = out.decode('utf-8')
branch = text.replace('remotes/origin/','').split('~')[0]

gh = github3.GitHub(token='CENSORED') # replace token
repo = gh.repository(github_repo_owner, github_repo_name)
pulls = repo.pull_requests(state='closed', sort='updated', head=github_repo_owner+':'+branch, number=1)
your_pr = next(pulls)
print(your_pr.title)

I was just randomly looking at the GraphQL API changelog and I saw that the associatedPullRequests field has recently been added (https://developer.github.com/v4/changelog/2019-03-08-schema-changes/) which resolves this issue. Thanks a lot @andreagriffiths11 :pray:

2 Likes

Here’s an example query which demonstrates how to fetch associated pull requests of the five latest commits on the master branch:

{
  repository(name: "react", owner: "facebook") {
    ref(qualifiedName: "master") {
      target {
        ... on Commit {
          id
          history(first: 5) {
            nodes {
              id
              associatedPullRequests(first: 10) {
                edges {
                  node {
                    title
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
4 Likes

Here is another example graphql query that takes a specific sha and outputs the associated PR’s:

query associatedPRs($sha: String, $repo: String!, $owner: String!){
  repository(name: $repo, owner: $owner) {
    commit: object(expression: $sha) {
      ... on Commit {
        associatedPullRequests(first:5){
          edges{
            node{
              title
              number
              body
            }
          }
        }
      }
    }
  }
}

{
                    "sha": 14242132153asfe33453,
                    "repo": "repo name",
                    "owner": "repo owner"
}
4 Likes

Thanks! precisely what I was looking for.

So commits are abstracted behind GitObjects 🤭