You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitHub Actions中Linux与Windows运行器git worktree行为差异问题

问题现象

编写GitHub Action工作流时,通过创建git worktree的方式将文件推送到与Action当前运行分支不同的目标分支,执行环境差异导致结果不一致:

  • 使用ubuntu-latest运行器时逻辑运行正常,可正确推送至目标ghpages分支
  • 使用windows-2019运行器时逻辑执行失败,git push未推送到worktree绑定的ghpages分支,反而尝试推送当前受保护的main分支,触发分支保护报错

Ubuntu环境正常运行代码

git worktree add -B ghpages html_build origin/ghpages
cp -a docs/. html_build/

cd html_build

git add . 
git commit -m "ghpages"
git push 

Windows环境异常代码

git worktree add -B ghpages html_build origin/ghpages
robocopy .\docs\ .\html_build\ /MIR

cd html_build

git add . 
git commit -m "ghpages"
git push 

Windows环境报错日志

remote: error: GH006: Protected branch update failed for refs/heads/main.        
remote: error: At least 1 approving review is required by reviewers with write access.        
To https://github.com/XXX/XX
 ! [remote rejected]   main -> main (protected branch hook declined)
error: failed to push some refs to 'https://github.com/XXX/XX'

临时移除main分支保护规则后验证,提交内容确实被错误推送到main分支,而非预期的ghpages分支。

根本原因

不存在git worktree在Linux、Windows运行器上的原生行为差异,问题来自两个Windows环境特有的执行逻辑坑:

  • 核心原因是robocopy /MIR的镜像同步逻辑:该参数会强制目标目录内容和源目录完全一致,所有源目录不存在的文件、文件夹都会被直接删除。执行上述robocopy命令时,源目录docs内没有worktree自动生成的.git引用文件(worktree目录下的.git不是文件夹,是指向主工作区git配置的文本引用文件),同步时这个文件会被直接删除。.git文件丢失后,html_build目录就不再是绑定ghpages分支的独立工作树,git向上递归查找仓库根目录时,会直接命中上层主工作区(也就是Action默认checkout的main分支仓库),后续所有git操作实际都是在main分支上执行的。
    而Linux下的cp -a docs/. html_build/只会把docs目录下的内容复制到目标目录,不会删除目标目录已有的文件,自然不会破坏worktree的.git引用,所以逻辑正常。
  • 次要原因是PowerShell的目录切换上下文和bash存在差异:如果git操作拆分在不同的run步骤中执行,cd切换目录后的上下文不会自动继承,git可能仍然读取主工作区的配置,不过该问题在同一段run脚本内执行时影响极小。
解决方案

针对Windows环境调整执行逻辑,避开上述问题即可,两种常用方案任选:

  • 方案1(推荐,双保险不会推错分支):给robocopy加排除.git的参数避免破坏worktree结构,同时显式指定推送的目标分支,不依赖git默认的上下文识别,修改后代码如下:
git worktree add -B ghpages html_build origin/ghpages
# 加/XD .git参数,排除.git文件,避免被robocopy误删
robocopy .\docs\ .\html_build\ /MIR /XD .git

cd html_build
git add . 
git commit -m "ghpages"
# 显式指定将当前HEAD推送到远程ghpages分支,完全避免分支识别错误
git push origin HEAD:ghpages
  • 方案2:如果希望和Linux环境写法保持一致,可以使用PowerShell原生的目录栈命令强制切换执行上下文,同样需要给robocopy加排除.git参数:
git worktree add -B ghpages html_build origin/ghpages
robocopy .\docs\ .\html_build\ /MIR /XD .git

Push-Location html_build
git add . 
git commit -m "ghpages"
git push
Pop-Location

注意:无论用哪种方案,都必须给robocopy加/XD .git参数,这是该场景下90%以上异常的触发原因。

内容的提问来源于stack exchange,提问作者001001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 22:18:22