news 2026/8/30 16:26:17

GitHub Actions中actions/checkout完全指南:原理、参数与常见问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GitHub Actions中actions/checkout完全指南:原理、参数与常见问题

actions/checkout是 GitHub Actions 中最常用的 Action 之一,几乎所有 CI 工作流的第一步都是从它开始的。但对于刚接触 GitHub Actions 的开发者来说,checkout 到底做了什么、有哪些参数需要关注、为什么有时候拉下来的代码不完整、子模块要怎么处理,这些问题往往散落在各个 issue 和博客里,不成体系。本文会从核心概念讲起,结合完整示例、参数说明和常见报错,带你彻底搞懂 GitHub Actions 中 checkout 的用法和原理,并与 Git 本地的git checkout命令做区分,避免混淆。

1. 背景与核心概念

1.1 什么是 actions/checkout

actions/checkout是 GitHub 官方提供的一个 Action,它的作用是在 GitHub Actions 的运行环境中拉取当前仓库的代码,让后续的 CI 步骤能够基于这份代码执行构建、测试、打包等操作。

可以这样理解:GitHub Actions 的工作流运行在一个独立的虚拟机上,这个环境一开始是空白的、和我们本地开发环境无关的。即使工作流是因为某个仓库的 push 事件触发的,运行环境本身也不会自动携带仓库代码。我们需要显式地执行 checkout 动作,才能把代码“取”到 runner 中。

因此,几乎每个 GitHub Actions 工作流的第一段都是:

steps: - name: 拉取代码 uses: actions/checkout@v4

这段配置的含义是:让当前 job 使用actions/checkout@v4这个 Action,把仓库代码检出到 runner 的工作目录中。

1.2 checkout 解决了什么问题

GitHub Actions 的定位是自动化任务执行平台。它需要的是可重复、可控、干净的执行环境。如果系统默认把仓库代码自动挂载到每个环境里,反而会带来几个问题:

  • 不是所有工作流都需要仓库代码,自动检出会浪费时间和存储。
  • 不同工作流可能需要在不同分支、不同 commit 上执行,自动检出无法灵活指定。
  • runner 环境的镜像需要保持通用性,内置所有仓库代码不现实。

actions/checkout把“是否拉取代码”“拉取哪个分支”“拉取多深的历史”这些选择权交给了工作流编写者。这种显式声明的方式更符合 CI/CD 的工程化思路,也让工作流的行为更可预测。

1.3 checkout 和 git clone 的区别

很多人会问:checkout 不就是 git clone 吗?两者确实都是拉取代码,但存在几个明显差异:

对比项git cloneactions/checkout
操作主体在本地终端手动执行在 GitHub Actions runner 中自动执行
身份认证依赖本地 SSH key 或凭据自动使用 GitHub 提供的 GITHUB_TOKEN
参数能力需要自己组合多个参数提供封装好的 Action 参数
分支切换clone 后需要手动 checkout可直接指定要检出的 ref
历史深度默认为完整历史可通过 fetch-depth 控制
子模块处理需要手动执行相关命令可通过 submodules 参数自动处理

actions/checkout本质上是在 runner 中执行类似 git clone 的操作,但它针对 CI 场景做了很多封装,比如自动处理认证、优化检出效率、支持稀疏检出、支持 GitHub 托管 runner 的特殊环境变量等。

1.4 常见使用场景

actions/checkout在以下场景中使用频率较高:

  • 每次 push 代码后自动执行测试。
  • Pull Request 创建或同步时运行静态检查。
  • 发布版本时拉取指定 tag 的代码进行构建。
  • 多仓库协作时,在主仓库工作流中拉取其他仓库代码。
  • 需要同时拉取多个子模块的文档站或 monorepo 项目。

2. 环境准备与版本说明

2.1 GitHub Actions 基础环境

在使用actions/checkout之前,需要确保你已经具备以下条件:

  • 一个 GitHub 账号和仓库。
  • 仓库中已启用 GitHub Actions(默认开启)。
  • 本地有 Git 基础使用经验。
  • 了解 YAML 的基本语法。

GitHub 提供了两类 runner:

  • GitHub 托管的 runner,例如ubuntu-latestwindows-latestmacos-latest
  • 自托管 runner,即自己搭建的运行环境。

actions/checkout在这两类 runner 上都可以使用,但配置细节略有差异。本文示例以 GitHub 托管的ubuntu-latest为例,这部分配置对大多数项目都适用。

2.2 actions/checkout 版本说明

actions/checkout目前已经历了多个大版本,使用最广的版本是@v3@v4

版本主要变化
v2基于 Node.js 运行,成为主流版本
v3适配 Node 16,继续兼容大部分项目
v4适配 Node 20,参数模型更清晰,安全性和性能有改进

在实际项目中,建议使用@v4或保持与项目约定一致的 tag。这里的 tag 是大版本号,GitHub Actions 会自动解析到该大版本的最新 release,不需要锁死小版本。

如果团队对可复现性要求较高,也可以锁定为具体的 release tag,例如类似actions/checkout@v4.1.1的写法。但需要特别注意的是,Actions 的 release 版本会持续更新,锁定小版本后应及时关注官方更新,避免错过安全修复。

2.3 示例项目结构

本文后续的实战案例会基于一个简单的 Node.js 项目,目录结构如下:

github-actions-checkout-demo/ ├── .github │ └── workflows │ └── ci.yml ├── package.json ├── index.js └── README.md

其中ci.yml是关键,它定义了整个 GitHub Actions 工作流。其他文件是一个最小可运行的 Node.js 项目,方便我们验证 checkout 的效果。

3. checkout 操作原理拆解

3.1 checkout 的核心逻辑

actions/checkout在 runner 中做了以下几件核心事情:

  1. 根据repository参数确定要拉取的仓库地址。
  2. 根据ref参数确定要检出的分支、tag 或 commit SHA。
  3. 配置 Git 凭据,使用GITHUB_TOKEN或自定义 token 完成身份认证。
  4. 克隆代码到path参数指定的目录。
  5. 根据需要处理子模块、LFS 文件、稀疏检出等扩展选项。
  6. 切换到目标 ref,确保当前工作区与指定提交一致。

从底层看,checkout 的过程和我们在终端手动执行的 Git 命令很相似,但它在 runner 环境中自动完成了认证和环境准备。

3.2 默认参数说明

actions/checkout提供了大量参数。下面我们先看几个最重要的:

3.2.1 repository

指定要拉取的仓库,默认值是当前仓库。

- uses: actions/checkout@v4 with: repository: your-github-name/repo-name

当工作流在仓库 A 中,却需要拉取仓库 B 的代码时,可以通过这个参数切换。

3.2.2 ref

指定要检出的分支、tag 或 commit SHA。默认情况下,GitHub Actions 会根据触发事件自动判断。例如 push 事件会检出对应分支的最新提交,pull_request 事件会检出 PR 的合并结果。

也可以手动指定:

- uses: actions/checkout@v4 with: ref: main

或:

- uses: actions/checkout@v4 with: ref: v1.2.0
3.2.3 fetch-depth

控制 Git 历史的获取深度。默认值是 1,也就是只拉取最新的一个提交。这在大多数 CI 场景中已经够用,能显著加快 checkout 速度。

如果需要完整历史,可以设置为0

- uses: actions/checkout@v4 with: fetch-depth: 0

如果需要最近几个提交,比如做代码扫描或版本计算,可以设置为具体数字,例如fetch-depth: 10

3.2.4 path

指定代码检出到 runner 的哪个目录,默认是当前工作目录$GITHUB_WORKSPACE

- uses: actions/checkout@v4 with: path: my-code

设置后,后续步骤需要进入my-code目录才能操作代码。

3.2.5 token

指定用于认证的 GitHub token,默认是${{ github.token }},也就是 GITHUB_TOKEN。这个 token 由 GitHub Actions 自动生成,权限由工作流的permissions配置决定。

如果需要拉取私有仓库或在当前仓库中 push 代码,可能需要自定义 token:

- uses: actions/checkout@v4 with: token: ${{ secrets.MY_PAT }}
3.2.6 submodules

控制子模块的拉取方式。默认值为false,即不拉取子模块。如果项目使用了 submodule,需要设置为truerecursive

- uses: actions/checkout@v4 with: submodules: recursive

recursive会递归拉取所有嵌套子模块。

3.2.7 lfs

控制是否拉取 Git LFS 大文件。默认是false

- uses: actions/checkout@v4 with: lfs: true
3.2.8 sparse-checkout

用于稀疏检出,只在需要部分目录时使用。这个参数在大型 monorepo 项目中很实用。

- uses: actions/checkout@v4 with: sparse-checkout: | src tests

3.3 常见误区

3.3.1 误认为 checkout 会自动切换分支

actions/checkout会切换到目标 ref,但它不受本地git checkout命令一样的“分支切换”语义影响。在 Actions 环境中,检出的是某个具体的提交状态,后续步骤中直接运行git branch可能看到的是 detached HEAD 状态。这通常是正常的,因为 CI 只需要代码内容,并不关心你当前在哪个分支上工作。

3.3.2 忽略 fetch-depth 对版本号计算的影响

很多项目在 CI 中根据 Git tag 计算版本号。此时如果fetch-depth为 1,可能无法取得最近的 tag,导致版本号错误。这种情况下需要将fetch-depth设置为0

3.3.3 把 actions/checkout 和 git checkout 混为一谈

这个点非常常见。Git 命令git checkout用于本地分支切换或文件恢复,而actions/checkout是 GitHub Actions 的一个 Action,两者解决的问题完全不同。在写工作流时,使用的是 GitHub Actions 的语法;在写 shell 命令时,才会用到git checkout。理解这个区别对排查问题很有帮助。

4. 完整实战案例

下面我们从头开始构建一个 GitHub Actions 工作流,逐步演示actions/checkout的使用方法。

4.1 创建项目结构

先在 GitHub 上创建一个新仓库,然后在本地把项目克隆下来。仓库名称可以命名为github-actions-checkout-demo

在本地创建以下文件:

package.json

{ "name": "github-actions-checkout-demo", "version": "1.0.0", "description": "A simple demo for actions/checkout", "main": "index.js", "scripts": { "test": "node index.js" } }

index.js

console.log('Hello from GitHub Actions checkout demo!');

README.md:写入简单的项目说明。

4.2 编写第一个工作流

在项目根目录创建.github/workflows/ci.yml,内容如下:

name: CI on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - name: 拉取代码 uses: actions/checkout@v4 - name: 查看检出后的文件 run: | pwd ls -la - name: 运行测试 run: npm test

将这个文件提交并推送到 GitHub 后,打开仓库的 Actions 页面,可以看到工作流开始执行。

4.3 运行与验证

工作流执行时,你会看到拉取代码这一步使用了actions/checkout@v4。这一步完成后,后续步骤就能访问到仓库中的代码。

查看检出后的文件步骤会输出当前工作目录和文件列表,结果类似:

/home/runner/work/github-actions-checkout-demo/github-actions-checkout-demo total 16 drwxr-xr-x 3 runner docker 4096 ... drwxr-xr-x 3 runner docker 4096 ... -rw-r--r-- 1 runner docker 76 ... README.md drwxr-xr-x 2 runner docker 4096 ... index.js drwxr-xr-x 2 runner docker 4096 ... package.json

这说明 checkout 成功地把仓库代码放到了 runner 的工作目录中。

4.4 使用参数控制检出行为

下面我们扩展工作流,加入更丰富的 checkout 参数。

4.4.1 拉取指定分支
steps: - name: 拉取 main 分支 uses: actions/checkout@v4 with: ref: main

这种方式适合手动触发的 workflow_dispatch 场景,或者需要固定分支的发布流程。

4.4.2 拉取完整历史
steps: - name: 拉取完整 Git 历史 uses: actions/checkout@v4 with: fetch-depth: 0

在需要根据 Git tag 生成版本号、统计提交数量、执行某些需要历史信息的扫描工具时,需要这样配置。

4.4.3 检出到指定目录
steps: - name: 拉取代码到 build 目录 uses: actions/checkout@v4 with: path: build - name: 进入目录查看文件 run: ls -la build

当工作流需要同时检出多个仓库代码时,这个参数特别有用。例如:

steps: - name: 拉取主仓库代码 uses: actions/checkout@v4 with: path: main-repo - name: 拉取工具仓库代码 uses: actions/checkout@v4 with: repository: your-name/tool-repo path: tool-repo
4.4.4 处理子模块

如果项目使用 submodule,需要在 checkout 时指定:

steps: - name: 拉取代码并初始化子模块 uses: actions/checkout@v4 with: submodules: recursive

配置了submodules: recursive后,checkout 会自动运行git submodule sync --recursivegit submodule update --init --recursive,不需要再手动执行额外的 shell 命令。

4.5 完整的多场景工作流参考

下面是一个相对完整的示例,展示了多个参数的组合使用:

name: Full Checkout Demo on: workflow_dispatch: jobs: demo: runs-on: ubuntu-latest steps: - name: 检出主仓库代码(完整历史) uses: actions/checkout@v4 with: repository: your-name/github-actions-checkout-demo ref: main fetch-depth: 0 path: app - name: 显示检出目录 run: ls -la app - name: 显示当前 Git 提交信息 run: git -C app log --oneline -5

这个工作流可以通过仓库 Actions 页面的Run workflow按钮手动触发。它演示了如何指定仓库、分支、获取完整历史,以及将代码检出到自定义目录。

5. 常见问题与排查思路

5.1 常见报错一览

问题现象常见原因解决思路
Repository not foundtoken 没有权限访问仓库确认使用正确的 token,检查仓库名称和权限
fatal: unable to access ...网络问题或认证失败检查网络,确认 token 有效,自托管 runner 检查代理配置
检出后模块找不到子模块未初始化设置submodules: recursive
Git tag 无法获取fetch-depth 为 1设置fetch-depth: 0
代码不在期望目录path 参数设置影响检查 path 参数,后续步骤切换到对应目录
Permission deniedGITHUB_TOKEN 权限不足调整工作流 permissions 或使用自定义 token
checkout 卡住或超时仓库过大或网络慢使用稀疏检出、设置更大的 timeout,或检查 runner 网络

5.2 拉取私有仓库失败

如果当前工作流需要拉取另一个私有仓库的代码,甚至还需要在当前仓库中使用私有 Action,那 checkout 时依赖的默认 GITHUB_TOKEN 可能权限不够。

常见做法是创建一个 Personal Access Token,在仓库的 Secrets 中保存,然后在 checkout 时引用:

- uses: actions/checkout@v4 with: repository: your-name/private-repo token: ${{ secrets.MY_PAT }}

需要特别注意的是,个人访问令牌的权限比较大,建议使用 GitHub App 的 token 或GITHUB_TOKEN配合精细化的permissions配置,避免长期使用权限较大的个人令牌。

5.3 checkout 的 ref 参数并非总是生效

ref参数在大多数情况下都能正确指定分支、tag 或 commit,但如果你同时指定了repository参数,并且repository指向的是当前仓库,行为与默认一致。如果指向其他仓库,需要确认目标仓库中确实存在这个 ref。

另外在pull_request事件中,默认 checkout 的是 PR 合并后的提交,而不是 PR 源分支的最新提交。这是 Actions 的设计行为,目的是模拟合并后的状态。如果你需要 checkout 源分支,可以依赖github上下文中的参数自行指定:

- uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }}

但要注意,这种情况下需要确认 token 有权限访问源分支所在的仓库。

5.4 子模块拉取失败

子模块拉取失败的常见原因有两个:

  • 子模块是私有仓库,checkout 时使用的 token 没有权限。
  • 子模块内容较大,默认的 fetch 策略超时。

解决方案是在 checkout 时传入有权限的 token:

- uses: actions/checkout@v4 with: submodules: recursive token: ${{ secrets.MY_PAT }}

如果子模块中还嵌套了子模块,需要使用recursive而不是true

5.5 LFS 文件未拉取

如果仓库使用了 Git LFS,并且 CI 构建需要这些大文件,需要在 checkout 时开启 LFS:

- uses: actions/checkout@v4 with: lfs: true

注意,开启 LFS 会拉取大量数据,可能增加整体构建时间。如果构建不需要 LFS 文件,保持默认关闭即可,这样可以加快 checkout 速度。

5.6 自托管 runner 的注意事项

在自托管 runner 上使用actions/checkout时,需要确保 runner 环境中已经安装 Git,并且 Git 版本足够新。部分旧版 Git 可能无法正确处理某些 GitHub 的新特性。

如果 runner 所在环境需要代理访问外部网络,还需要检查代理配置是否会影响 checkout 过程中的 HTTPS 请求。

6. 最佳实践与工程建议

6.1 尽量使用默认参数

对于大多数项目,默认的actions/checkout@v4就能满足需求。默认fetch-depth: 1能显著减少 checkout 耗时,而且大多数构建和测试命令并不需要完整历史。不要一开始就把fetch-depth设置为0,等确实需要完整历史时再调整。

6.2 重视 token 权限最小化

actions/checkout默认使用GITHUB_TOKEN,而这个 token 的权限范围由工作流顶部的permissions决定。建议在工作流中显式声明权限,而不是依赖仓库全局设置。例如:

permissions: contents: read

如果 checkout 后还需要在当前仓库中提交代码,例如自动生成文档并推送,则需要声明contents: write。此时要格外小心,避免工作流在每次 push 时再次触发自身,形成循环。

6.3 在需要时使用稀疏检出

如果你的仓库很大,而 CI 只需要其中部分目录,可以考虑使用sparse-checkout。这个功能在 monorepo 架构下能大幅减少检出耗时。

- uses: actions/checkout@v4 with: sparse-checkout: | packages/app packages/shared

需要注意的是,稀疏检出后git statusgit diff等操作可能只反映已检出的文件,某些工具可能因此表现异常。

6.4 根据事件类型合理选择 ref

在写工作流时,默认 checkout 逻辑已经能覆盖绝大多数场景。但如果你的工作流需要更复杂的引用关系,建议先理解github上下文中的几个关键字段:

字段含义
github.sha触发工作流的 commit SHA
github.ref触发工作流的分支或 tag
github.event.pull_request.head.shaPR 源分支的最新 commit
github.event.pull_request.base.shaPR 目标分支的最新 commit

合理使用这些字段,可以让 checkout 更精确地定位到需要分析的提交。

6.5 避免在 checkout 后修改 Git 配置导致问题

有些项目会在工作流中手动执行git config user.namegit config user.email。这些操作在本地没有问题,但在 CI runner 中,如果后续有自动提交需求,需要正确设置这些值。建议通过环境变量或专门的步骤来管理,不要在 checkout 之前强行修改全局 Git 配置,以免影响其他步骤。

6.6 缓存与 checkout 的顺序

在 GitHub Actions 中,缓存恢复和 checkout 的顺序会影响效率。如果用了actions/cache恢复依赖缓存,并且缓存内容不依赖代码内容,通常可以先恢复缓存再 checkout。如果缓存 key 中包含 commit SHA,那么必须先 checkout,才能知道当前的 SHA,然后构造缓存 key。

这里给出一个常见的组合示例:

steps: - name: 拉取代码 uses: actions/checkout@v4 - name: 恢复 npm 缓存 uses: actions/cache@v4 with: path: ~/.npm key: npm-${{ hashFiles('package-lock.json') }}

6.7 关注 checkout 和 git checkout 的语义区别

回到文章开始时提到的混淆点,actions/checkout解决的是“在 CI 环境中检出代码”的问题,git checkout解决的是“在本地仓库中切换分支或恢复文件”的问题。如果在一个 workflow 的run步骤里写 shell 命令,需要操作 Git 时,依然可以使用git checkout,但在uses关键字下,我们使用的是 GitHub Actions 的 Action 语法。

这种区分在排查问题时非常重要。例如在 CI 日志中看到Run actions/checkout@v4,这是 Action 的输出;看到git checkout main,才是 shell 命令的输出。理解了这一层,就不会因为报错信息来自不同的层而困惑。

6.8 定期关注 Action 版本更新

GitHub 官方会不定期发布actions/checkout的新版本,修复安全漏洞或兼容性问题。建议在 CI 中定期检查使用的版本,尤其是在 GitHub 官方通知 Node.js 版本不再受支持时,及时升级到新的大版本。

升级时可以先在一个不关键的工作流中试用,确认无误后再推广到所有仓库。不要同时调整大量配置,避免问题出现时难以定位。

7. 总结与学习路线

本文从 GitHub Actions 中的actions/checkout入手,介绍了它的核心概念、与git clone的区别、常用参数、完整实战案例以及典型报错的排查方法。同时,我们重点区分了actions/checkout和 Git 本地命令git checkout的语义差异,这个区分在实际排查中非常关键。

如果你刚开始接触 GitHub Actions,建议按以下顺序继续深入:

  1. 先掌握on事件触发、jobssteps的基础写法。
  2. 理解github上下文中的常用字段。
  3. 尝试在一个简单项目中加入测试、构建步骤。
  4. 掌握actions/upload-artifactactions/download-artifact,了解如何传递构建产物。
  5. 深入学习actions/cache,优化依赖安装速度。
  6. 最后再研究仓库权限、环境变量、自托管 runner 等高阶内容。

actions/checkout虽然只是 CI 流程中的第一步,但很多构建问题其实都出在这一步。把它的参数和原理搞清楚,后续的 CI 优化会顺利很多。建议你在自己的项目中多写几个小实验,分别试试不同的reffetch-depthpathsubmodules组合,观察实际行为,这样才能真正掌握它。如果本文对你有帮助,可以收藏备用,后面用到时候直接翻出来照做。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 16:24:34

省赛第三的遗憾:机器学习竞赛中,流程管理比调参更关键

比赛成绩在大屏上刷出来的那一刻,我们三个人都没有说话。排名第三,全省第三。旁边有两支队伍在拥抱,他们的名字排在我们前面。再往后,还有一些队伍在庆祝,因为他们拿到的成绩已经超出预期。我们队的气压明显不对&#…

作者头像 李华
网站建设 2026/8/30 16:22:48

AI编程时代,如何用批判性思维守住代码质量底线?

不知道你有没有遇到过这种情况:让 AI 写了一段代码,本地一跑居然通过了,但上线之后却出了事故;或者 AI 给了一个看起来很专业的修复方案,照着改完却发现另一个功能挂了。问题并不一定出在 AI 本身,而在于我…

作者头像 李华
网站建设 2026/8/30 16:22:00

CapyToolkit:浏览器原生硬件诊断工具,一条链接搞定开发调试

把一个开发板插到新电脑上,通常意味着重新经历一遍硬件调试的“仪式”:装驱动、找串口号、配权限、打开串口工具、设置波特率,如果换一台电脑、换一个系统,这套流程还得从头再来。CapyToolkit 属于“Show HN”项目里比较有意思的一…

作者头像 李华
网站建设 2026/8/30 16:19:40

逆变器板烧毁后ST-LINK V2无法识别?SWD接口故障排查与保护方案

1. 故障现象:逆变器板子烧了之后,ST-LINK V2跟着“不认设备”了先说结论:ST-LINK V2不是真的坏了,极大概率是调试接口周围的电路被逆变器板上的高压串扰击穿,导致SWD接口的电平异常,主机识别不到调试器。我…

作者头像 李华