How do I get the git diff compared to main?

I want the same git diff blob I get from adding .diff to a PR in Github.
Tried this:

on:
  pull_request:
    branches:
      - main

jobs:
  tests:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Debug github.sha
        run: |
          git diff --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }}

This has worked in a different repo but now I’m getting:


Run git diff --diff-filter=ACMRT 056dd907dec16280916ee9779a1416c8b618f53e 0605ea0f43db356598fbea3469b8ce381f084900
  git diff --diff-filter=ACMRT 056dd907dec16280916ee9779a1416c8b618f53e 0605ea0f43db356598fbea3469b8ce381f084900
  shell: /usr/bin/bash -e {0}
fatal: bad object 056dd907dec16280916ee9779a1416c8b618f53e
Error: Process completed with exit code 128.

I don’t think I understand how actions/checkout but I think 0605ea0f43db356598fbea3469b8ce381f084900 isn’t a commit I’d find anywhere else. It’s a merge commit made by actions/checkout or something. I honestly don’t understand that stuff but it seems to be what’s going on from skimming various issues and discourse and stackoverflow posts.

All I need is: what’s the diff?

For example, here’s a PR and here’s the diff which is simply add .diff to the URL. How do I get that into my bash inside the GitHub Action?

By default actions/checkout fetches only the commit github.ref points at. If you want to compare other points in history, you’ll need to retrieve more of the history, possibly all. See:

1 Like

What’s so confusing is that it’s not necessary to do that on this workflow:

That one uses just:

      - uses: actions/checkout@v2

And then further down, it does

git diff --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} > build/DIFF

and that works.

I see that workflow calls some actions and scripts that are specifically for dealing with diffs, as far as their names and comments in the workflow say. Maybe one of those fetches additional history?

1 Like

Yeah, that’s very likely the explanation. Under the hood it does a git pull or something that unbreaks things further down.

I think this trick might actually solve it. But I’m now not entirely certain what that means. Will it potentially be a different code that gets CI run? I.e. different from what would be merged.

That changes what gets checked out, not whether history is available. So comparing it with other commits will still fail.

Your code above looks like you want to compare two specific commits. That is possible regardless of what you check out, as long as you have the history available. To make the full history available with actions/checkout you need to use fetch-depth: 0.

Won’t fetch-depth include EVERYTHING? That could be huge. All I need is the commit from which the PR branch was started and nothing older than that.

Yes. The options actions/checkout offers for shallow clones are somewhat limited. For the comparison between two commits you naturally need both commits, and the full clone is the only reliable way to get both.

Alternatively you could look at rolling your own repository setup using Git commands, maybe using partial clone (which can get missing objects when needed). I can’t judge if it’d be worth the effort in your use case. If it sounds interesting, here’s an introduction:

1 Like