DEV Community

Cover image for Get GitHub PR from commit hash
Pavel Kutáč
Pavel Kutáč

Posted on

Get GitHub PR from commit hash

Have you ever needed to get GitHub PR details from the commit hash in the master branch? With the Merge commits strategy, number of PR will be in the commit message. But what about Rebase and merge or Squash and merge strategy?


🇨🇿 V češtině si lze článek přečíst na kutac.cz


Lately, I have modified GitHub Action, which sends Slack message with the author of the last PR that was merged. But how to get the PR number and the author of that PR when I only have a log history?

Merge commit strategy

As I wrote above, when using the Merge commit strategy, GitHub creates a merge commit with a message that looks like this:

Merge pull request #270 from author/branch-name

fix: here is your original commit message
Enter fullscreen mode Exit fullscreen mode

Here it is easy to extract the number. But before merging, the user can modify the message and the number of PR will be gone or different.

I have only commit hash

Browsing in git history with git log or similar, will not tell you much. But with GitHub API, you can ask which PR contains some commit hash.

And the best about that is, it works well in all scenarios! Including Rebase and merge and Squash and merge strategies, which create new commit. So the commit in the original PR and in the master branch have different hash.

The script below uses GitHub CLI which is pre-installed inside GitHub Actions, and by setting GH_TOKEN also authenticated.

jobs:
  your-action-name:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 10 # We are going to history a bit, so load little more to be sure

      - name: Get last PR author
        id: release-author
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          # Get last commit SHA
          last_commit_sha=$(git --no-pager log --format=%H --no-merges -n 1 --skip 1) || last_commit_sha=""
          author="unknown"

          if [ -n "$last_commit_sha" ]; then
            author=$(gh pr list --search $last_commit_sha --state merged --json author --jq '.[0].author.login') || author=""
          fi

          echo "author: $author"

Enter fullscreen mode Exit fullscreen mode

I need to explain script above

git --no-pager log --format=%H --no-merges -n 1 --skip 1

  • git log operates on top of the git history
  • --no-pager turns off pagination - not necessary
  • --format=%H prints only full commit hash
  • --no-merges will skip merge commits
  • -n 1 --skip 1 instruct to return only 1 commit (-n) and --skip last one. This is important for us, as the last commit is created by Release please action. Remove skipping if not needed for you.

gh pr list --search $last_commit_sha --state merged --json author --jq '.[0].author.login'

  • gh pr list is using GitHub CLI to list PRs, already pre-installed in GitHub action
  • --search $last_commit_sha is a general search query, so we are searching by our commit hash
  • --state merged include only merged PRs
  • --json author --jq '.[0].author.login' tells the CLI tool to return JSON with the author field, which is then filtered by jq expression to give us the login of the first author

Is this bulletproof?

No, it is not, because it is using a generic search query. So if someone adds commit directly to comments, this will fail.

In that case, you can improve a query a bit to exclude comments from search --search "{$last_commit_sha} \!in:comments".

Or you can select author together with commits of PR, and then using JQ filter it out. It is however more complex, but also more reliable not to give false positives.

gh pr list --search $last_commit_sha --state=merged \
  --json author,commits \
  --jq '.[] | select(.commits[]?.oid == "'"$last_commit_sha"'") | .author.login'
Enter fullscreen mode Exit fullscreen mode

If you spot another possible issue, share it with us in comments.

Top comments (1)

Collapse
 
albz profile image
Alberto Barrago

🤙🏻