GitHub Actions拉取请求中git diff返回无修改文件的问题
GitHub Actions PR场景下git diff返回空的问题修复
问题背景
我在GitHub上为一个批量项目搭建CI/CD流水线,项目目录结构如下:
batch_project/ ├── alpha/ │ ├── program_1.txt │ ├── program_2.txt │ └── program_3.txt ├── beta/ │ ├── program_1.txt │ ├── program_2.txt │ └── program_3.txt ├── gamma/ │ ├── program_1.txt │ ├── program_2.txt │ └── program_3.txt └── .github/ └── workflows/ └── ci-cd.yml
触发规则:当alpha、beta或gamma模块下的任意文件发生代码推送时,流水线自动触发对应模块的构建与部署。
异常场景:从feature/*或release/*分支向main分支发起拉取请求(PR)时,用于列出修改文件的流水线步骤返回空值,但PR中确实存在变更。出问题的代码片段:
MODIFIED_FILES=$(git diff --name-only origin/$BASE_BRANCH..${{ github.sha }})
问题原因
- 默认checkout深度限制:GitHub Actions的
actions/checkout默认只拉取最近1个提交(fetch-depth:1),本地没有目标分支的完整历史,导致git diff无法对比两个分支的差异。 - BASE_BRANCH变量取值错误:PR触发的流水线中,若
BASE_BRANCH未正确设置为PR的目标分支(比如main),会导致对比的分支不存在或不正确。 - SHA对比逻辑问题:PR场景下,
github.sha是临时的合并提交SHA,直接用它和origin/$BASE_BRANCH对比,因本地历史不全无法识别差异。
修复方案
方案1:拉取完整仓库历史
修改checkout步骤,设置fetch-depth: 0拉取所有分支和历史:
- name: 拉取代码 uses: actions/checkout@v4 with: fetch-depth: 0 # 拉取完整仓库历史,支持分支对比
方案2:直接使用PR事件中的SHA对比
PR触发时,可通过GitHub上下文直接获取基准分支和头部分支的SHA,跳过本地分支引用的依赖:
# PR场景下直接用事件中的SHA对比差异 MODIFIED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }})
方案3:动态设置BASE_BRANCH变量
根据触发场景自动设置目标分支,配合完整checkout执行diff:
- name: 设置基准分支 run: | if [ "${{ github.event_name }}" = "pull_request" ]; then echo "BASE_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV else echo "BASE_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV fi - name: 获取修改文件列表 run: | MODIFIED_FILES=$(git diff --name-only origin/$BASE_BRANCH..HEAD) echo "MODIFIED_FILES=$MODIFIED_FILES" >> $GITHUB_ENV
完整流水线示例片段
jobs: 构建部署: runs-on: ubuntu-latest steps: - name: 拉取代码 uses: actions/checkout@v4 with: fetch-depth: 0 - name: 设置基准分支 run: | if [ "${{ github.event_name }}" = "pull_request" ]; then echo "BASE_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV else echo "BASE_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV fi - name: 获取修改文件 run: | if [ "${{ github.event_name }}" = "pull_request" ]; then MODIFIED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}) else MODIFIED_FILES=$(git diff --name-only origin/$BASE_BRANCH..HEAD) fi echo "MODIFIED_FILES=$MODIFIED_FILES" >> $GITHUB_ENV - name: 处理alpha模块 if: contains(env.MODIFIED_FILES, 'alpha/') run: | echo "开始构建部署alpha模块..." # 此处添加alpha模块的构建部署命令 - name: 处理beta模块 if: contains(env.MODIFIED_FILES, 'beta/') run: | echo "开始构建部署beta模块..." # 此处添加beta模块的构建部署命令 - name: 处理gamma模块 if: contains(env.MODIFIED_FILES, 'gamma/') run: | echo "开始构建部署gamma模块..." # 此处添加gamma模块的构建部署命令
内容的提问来源于stack exchange,提问作者Uday Kiran
相关产品推荐
相关产品推荐

