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

Stack是否仅构建时运行hpack?切Git分支时.cabal为何被自动修改

成因说明

Stack 没有常驻后台的守护进程监听文件变更来重生成 .cabal,你遇到的瞬时修改问题,触发源基本都来自 shell 环境的自动执行逻辑:

  • 只要执行任意需要读取项目配置的 Stack 子命令(不止 build,包括查询 GHC 版本、读取路径、补全信息加载这类非构建操作),Stack 默认都会先校验 package.yaml 和现有 .cabal 文件的一致性,判定不匹配就会自动调用 hpack 重写 .cabal。仅在构建前重生成的逻辑确实能满足构建需求,但 Stack 目前没有做这个场景的区分,所有读配置的命令都会触发 hpack 检查。
  • 你观察到的时间差完全匹配 shell 提示符插件的执行时机:执行完 git restore *.cabal 命令返回交互 shell 时,侧边栏显示 GHC 版本的插件会自动调用 Stack 命令读取当前项目环境,这个过程触发了 .cabal 重写,等你再执行 git switch 时,文件已经产生未提交变更,自然会报错。把两个命令用 && 合并成同一条执行时,中间不会回到 shell 交互态,没有触发插件执行的窗口,所以可以正常切换。
  • 不同分支下生成的 .cabal 中 Paths_Package 内容存在差异是正常现象:hpack 生成该段内容时会读取当前本地环境状态、包版本配置,哪怕两个分支的 package.yaml 完全一致,切换分支过程中的文件临时状态、本地 Stack 环境参数变化,都可能导致生成内容出现 diff。
  • stack --bash-completion-script 本身不会触发重写,但 Zsh 补全逻辑如果在预加载项目补全信息时调用了其他需要读配置的 Stack 子命令,同样会触发 .cabal 重写。
可参考的解决方法
  • 最优方案:不要将自动生成的 .cabal 文件纳入 Git 版本管理,在 .gitignore 中添加 *.cabal 规则,所有协作者统一通过 package.yaml 管理配置,从根源上避免自动生成文件带来的冲突。如果项目需要兼容不使用 hpack 的场景、必须提交 .cabal 文件,可以参考下面的方案。
  • 临时规避:执行 Git 分支切换等操作时,添加环境变量禁用 Stack 的自动 hpack 逻辑,例如使用 STACK_AUTO_HPACK=false git switch <目标分支名>,需要构建时再手动执行 stack build 触发一次 .cabal 生成即可。
  • 调整 shell 配置:修改终端侧边栏显示 GHC 版本的插件逻辑,调用 Stack 命令时统一加上 --no-hpack 参数,避免非构建场景下触发文件改写。
  • 配置 Git 钩子:在仓库的 post-checkout 钩子中添加 git restore *.cabal 逻辑,分支切换完成后自动复位 .cabal 文件状态,省去手动操作的步骤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.13 16:15:54