Luïs
Luïs

Reputation: 2853

Github Actions: Git diff master...HEAD fatal: no merge base

Some context

Long story short: I am trying to run jest --changedSince=master when I open up a new Pull Request. The jest changedSince flag runs git diff master...HEAD in the background. This results in an error which I can't seem to get my head around.

Current situation

To debug this I have a Github Action which has a step which closely resembles the following:

runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - run: |
        git fetch --no-tags --depth=1 origin master
        git checkout -t origin/master
        git checkout pull/1/merge
        git diff master...HEAD

This results in the following error (Which is the same error returned by Jest):

fatal: refs/remotes/origin/master...HEAD: no merge base

What I have tried

The problem does not occur when I run this locally (imagine that). I do realise that the biggest issue here is most likely the fact that the actions/checkout@2 action does not fetch the entire repository. That's why I added the git fetch & git checkout -t origin/master and pull/1/merge command.

I did attempt to run git branch -a to debug if this worked as expected, these were the results:

* (HEAD detached at pull/1/merge)
  master
  remotes/origin/master
  remotes/pull/1/merge

All the refs which are required to run git diff master...HEAD seem to be available in the action.

I have also tried to check if the actual ref is returned correctly: I ran git show-ref master inside the action which returns:

<commit-sha> refs/heads/master
<commit-sha> refs/remotes/origin/master

I am out of ideas on what could cause this issue, any ideas are appreciated greatly!

Upvotes: 17

Views: 15982

Answers (3)

James Hall
James Hall

Reputation: 380

Expanding on LeGEC's answer, you can calculate the depth of the clone before cloning.

steps:
  - name: Get base depth
    id: base-depth
    run: echo "base-depth=$(expr ${{ github.event.pull_request.commits }} + 1)" >> $GITHUB_OUTPUT

  - name: Checkout repository
    uses: actions/checkout@v4
    with:
      ref: ${{ github.event.pull_request.head.sha }}
      fetch-depth: ${{ steps.base-depth.outputs.base-depth }}

This ensures the clone includes all commits from the branch, as well as the merge base commit.

Upvotes: 5

Carl G
Carl G

Reputation: 18280

I'm using the following in a Github action to use a single GH API call to determine the commits needed to have a merge base:

          comparison=$(gh api\
            repos/Howdju/howdju/compare/${{ github.event.pull_request.base.sha }}...${{github.event.pull_request.head.sha }})
          behind_by=$(echo -E $comparison | jq -r '.behind_by')
          ahead_by=$(echo -E $comparison | jq -r '.ahead_by')
          echo "ahead_by: $ahead_by; behind by: $behind_by"
          # +1 because fetch depth=1 is the commit itself.
          if [[ $behind_by -gt 0 ]]; then
            base_depth=$((behind_by+1))
            echo Fetching base to depth $base_depth
            git -c protocol.version=2 fetch --no-tags --no-recurse-submodules\
              --depth=$base_depth origin ${{github.event.pull_request.base.sha }}
          fi
          if [[ $ahead_by -gt 0 ]]; then
            head_depth=$((ahead_by+1))
            echo Fetching head to depth $head_depth
            git -c protocol.version=2 fetch --no-tags --no-recurse-submodules\
              --depth=$head_depth origin ${{github.event.pull_request.head.sha }}
          fi

Upvotes: 1

LeGEC
LeGEC

Reputation: 52081

If you want to explore the history of master and HEAD (as in : find the merge base for these two commits), you can't limit your clone/fetch actions to a shallow clone -- not with depth=1 at least.

Try setting fetch-depth: 0 (or perhaps fetch-depth: 1000 # a high enough number) in the config of your action/checkout@v2 (as described in the project's Readme), and drop the --depth=1 (or set it to a higher value) when you run git fetch origin master.


Another way could be to get this kind of info through the GitHub API, instead of querying the local clone.

Upvotes: 20

Related Questions