You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was looking into this same issue and came across your repo from Google. I have since learned that we can resolve this issue without the deepen approach:
One of those is commits (expression: ${{ github.event.pull_request.commits }}), the number of commits for the PR.
Now you can fetch that amount +1 to get the common ancestor for the merge base 😀
Example
Original example (partially flawed)
- name: 'Checkout PR and all PR commits + 1'uses: actions/checkout@v3# Get the HEAD commit, not the merge commit GH generates for PR and fetches by default# I'm not sure why, but `git log` shows the number of commits as sufficient without the +1,# but otherwise seemed necessary when I tested locally without GH Actionswith:
ref: ${{ github.event.pull_request.head.ref }}fetch-depth: ${{ github.event.pull_request.commits }}
- name: 'Example: Show files added/modified by PR branch'# Referencing via ENV vars only for better readability compared to the context expressionsenv:
BRANCH_PR: ${{ github.event.pull_request.head.ref }}BRANCH_BASE: ${{ github.event.pull_request.base.ref }}run: | # Enabling echo for testing, so that you can see the output in workflow logs echo '::echo::on' # Get the base branch to derive the common ancestor commit (aka merge-base) # By default git fetch will try find a common commit in local history, else fetch all commits git fetch origin "${BRANCH_BASE}" # echo -e here is just to make the output visible to the logs echo -e "$(git diff-tree --no-commit-id --name-only --diff-filter 'AM' -r --merge-base origin/"${BRANCH_BASE}" "${BRANCH_PR}")"
I also used the following commands to test locally:
# Replace 42 with PR commits + 1, I am cloning the PR branch from my repo copy
git clone --depth 42 https://github.com/user/repo -b pr-branch-name .# Since the repo my PR is to merge to is not mine, I'm adding it as a remote
git remote add upstream-repo https://github.com/organization/repo
# Now fetching the master branch, normal git fetch should be able to resolve the common ancestor,# otherwise you can be more specific and further hint at which commit is the common ancestor to settle on (less data transferred?)# git rev-list command is retrieving the commit ID of the oldest commit in our original clone history depth:
git fetch --negotiation-tip $(git rev-list --max-parents=0 HEAD) upstream-repo master
# Now we have all the commits needed for the two branches to have a common merge-base and can get such a diff:
git diff-tree --no-commit-id --name-only --diff-filter 'AM' -r --merge-base upstream-repo/master pr-branch-name
Update
I have done a more thorough investigation, and since found that using branch refs isn't ideal if you're wanting reproducible workflow runs (re-run a job), as the github context used is cached, but if the PR has received new commits since, you fetch the latest history, but not enough commits (due to outdated context).
This approach will avoid that issue, and the --shallow-since option is useful if you want to ensure a merge-base, in-case some local history from the base branch exists already and fetch decides not to retrieve anymore base branch commits:
- name: 'Checkout the latest commit of the PR branch (at the time this event originally triggered)'uses: actions/checkout@v3with:
ref: ${{ github.event.pull_request.head.sha }}
- name: 'Example - Get a list of changed files to process (fetching full PR commit history)'env:
branch_base: origin/${{ github.event.pull_request.base.ref }}branch_pr: origin/${{ github.event.pull_request.head.ref }}refspec_base: +${{ github.event.pull_request.base.sha }}:remotes/origin/${{ github.event.pull_request.base.ref }}refspec_pr: +${{ github.event.pull_request.head.sha }}:remotes/origin/${{ github.event.pull_request.head.ref }}run: | # Fetch enough history to find a common ancestor commit (aka merge-base): git fetch origin ${{ env.refspec_pr }} --depth=$(( ${{ github.event.pull_request.commits }} + 1 )) \ --no-tags --prune --no-recurse-submodules # `actions/checkout` fetched a specific commit, not a branch (ref), so that commit was checked out in a # detached HEAD state. Depending on what you do, you may want to additionally switch to the branch # the refspec assigned the commit to in the prior fetch command: # git switch -c ${{ env.branch_pr }} # This should get the oldest commit in the local fetched history (which may not be the commit the PR branched from): COMMON_ANCESTOR=$( git rev-list --first-parent --max-parents=0 --max-count=1 ${{ env.branch_pr }} ) DATE=$( git log --date=iso8601 --format=%cd "${COMMON_ANCESTOR}" ) # Get all commits since that commit date from the base branch (eg: master or main): git fetch origin ${{ env.refspec_base }} --shallow-since="${DATE}" \ --no-tags --prune --no-recurse-submodules # Example - Show only files from the PR with content filtered by specific git status (Added or Modified): git diff-tree --name-only --diff-filter 'AM' -r \ --merge-base ${{ env.branch_base }} ${{ env.branch_pr }}
The text was updated successfully, but these errors were encountered:
I was looking into this same issue and came across your repo from Google. I have since learned that we can resolve this issue without the deepen approach:
fetch-through-merge-base/README.md
Lines 63 to 66 in 98594af
The GH Actions
pull_request
context has quite a bit of info you can query. The official docs last I checked don't make this obvious.., but you have full access to this payload response.One of those is
commits
(expression:${{ github.event.pull_request.commits }}
), the number of commits for the PR.Now you can fetch that amount +1 to get the common ancestor for the merge base 😀
Example
Original example (partially flawed)
I also used the following commands to test locally:
Update
I have done a more thorough investigation, and since found that using branch refs isn't ideal if you're wanting reproducible workflow runs (re-run a job), as the github context used is cached, but if the PR has received new commits since, you fetch the latest history, but not enough commits (due to outdated context).
This approach will avoid that issue, and the
--shallow-since
option is useful if you want to ensure a merge-base, in-case some local history from the base branch exists already andfetch
decides not to retrieve anymore base branch commits:The text was updated successfully, but these errors were encountered: