Rebase and merge only triggers "push" event for the latest commit on the merged branch

Hey,
I have a job that is triggered to run at a push to master:

on:
  push: 
    branches:
      - master
    paths:
      - 'services/**'

I have recently noticed that when merging to master using the “rebase and merge” method that my job will only run on the latest commit in the merge rather then on each commit separately. whereas if I “squash and merge” the job will include all the commits in the merge. Is there a way to get the job to run on each commit in a “rebase and merge”?

@mfaur,

Is there a way to get the job to run on each commit in a “rebase and merge”?

Currently, we seem do not have any way to do this.

There are few points you need to understand:

  1. Normally, when you push multiple commits at once to a branch, the triggered workflow run only considers the latest commit as the commit ref (github.sha). A workflow run only has one corresponding commit ref.

  2. About pull request merge methods (more details, you also can see “About pull request merges”):

    • Merge pull request - - All the new commits on the head branch (source branch, github.head_ref) of the PR will be add to the PR merge branch (refs/pull/:prNumber/merge) to generate new PR merge commit, and the latest PR merge commit will be directly pushed to the base branch (target branch, github.base_ref) of the PR when the PR is merged. On the base branch will only generate one commit.

    • Squash and merge - - All the new commits on the head branch will be combined into a commit, and this commit will be directly pushed to the base branch. On the base branch will only generate one commit.

    • Rebase and merge - - All the new commits on the head branch will be added to the base branch. On the base branch will generate a commit for each new commit from the head branch, but the commit SHA for each one will be different between the base branch and the head branch.

No matter what merge method you use, after merged, the workflow triggered by push event will only reference the latest one commit on the base branch.

1 Like

Hey,
Thanks for the quick response!
So I did some more digging and saw that as you said, when multiple commits are pushed at once they only trigger one “push” action job for the latest commit sha. However the “push” trigger paths include all the paths of all of the recent commits.

e.g:

  push:
    branches:
       - master
    paths:
      - 'services/test/**'
      - '.github/workflows/test.yaml'
      - 'packages/**'

If I have a job with the above push trigger and the latest commit didn’t contain any of those paths but one of the older commits that were rebased and merged along with it did contain one of those paths then the job will run. However if I enter the commit sha that the job is running from it will only show the changes of the most recent commit which can be confusing and lead to mistaking that the job ran even though it shouldn’t have. Is this the correct behaviour?

@mfaur,

If I have a job with the above push trigger and the latest commit didn’t contain any of those paths but one of the older commits that were rebased and merged along with it did contain one of those paths then the job will run. However if I enter the commit sha that the job is running from it will only show the changes of the most recent commit which can be confusing and lead to mistaking that the job ran even though it shouldn’t have. Is this the correct behaviour?

Sure, it is the correct behavior.

There are few points you need to understand:

  1. A push can contain either one commit or multiple commits at once.

  2. When the push event occurs on a branch, GitHub will use the latest commit in the current push to compare with the latest commit in the last push. So, it is obvious that all the changed files between the two pushes will be listed to compare with the path filters you set on the push event in the workflow file.

  3. The path filters on the pull_request event are the similar logic. Every time you push new commits to a PR, GitHub will use all the commits (include older and new) on the PR to compare with the path filters.

1 Like

Thanks for the explanation. Is there a git command or api call that can list all the changed files between the most recent push and the last push before it? or a command that will retrieve the latest commit of the last push?

I doubt that git tracks pushes. It’s not a real git action. It’s a combination of fetch and depending on settings and branch heads a merge, rebase or fast forward.

You should be able to get a list of commits in the current push from the commits attribute of the push event. Note that if you want to look at commit details you’ll either have to make the checkout non-shallow (actions/checkout does a shallow clone by default), or retrieve them over the API.

They should show up in git reflog, but that doesn’t help here because the actions runner will get a fresh clone.

1 Like

@airtower-luna Just checked, pushes don’t create reflog entries at all. Pulls do. Not sure if Git servers consider incoming pushes like pulls? Do they even have a reflog?

Pushes do create reflog entries if the push leads to a checkout, like with receive.denyCurrentBranch set to updateInstead. A bare repository not having a reflog makes sense because there’s no meaningful HEAD.

1 Like

Makes sense that it creates a reflog entry if a checkout occurs. Didn’t know this option. Doesn’t help with the problem at hand though :sweat_smile:

1 Like

Agreed, that’s why I mentioned the event object and API. :slightly_smiling_face:

1 Like