Proton 版本升级 Rebase 全流程指南:从上游 Wine 迁移补丁的工程实践
2026/9/19 13:01:25 网站建设 项目流程

Proton 版本升级 Rebase 全流程指南:从上游 Wine 迁移补丁的工程实践

【免费下载链接】ProtonCompatibility tool for Steam Play based on Wine and additional components项目地址: https://gitcode.com/gh_mirrors/pr/Proton

导读

Proton 是 Steam Play 的兼容工具,其核心思路是在 Wine 及其组件(如 DXVK、vkd3d-proton、dxvk-nvapi)之上叠加大量自定义补丁,以满足游戏兼容性需求。每当上游 Wine 发布新版本,Proton 维护者都需要执行一次Rebase:把散落在旧版本之上的补丁重新应用到新版本分支上,同时剔除已经被上游收录的补丁。本文基于 docs/REBASING_TIPS.md,系统讲解 Proton 的补丁管理纪律、批量迁移命令、冲突处理脚本与收尾的 prefix 版本号更新机制,并给出仓库源码级佐证。读完本文,你将掌握一套可复制的 Wine rebase 操作流程。

为什么 Proton 需要频繁 Rebase

Proton 并不是简单的 Wine 发行版,它在每个上游版本之上都维护着数量庞大的本地补丁(本仓库的wine/目录即内嵌了带补丁的 Wine 源码树,此外还有dxvk/vkd3d-proton/dxvk-nvapi/wineopenxr/等配套组件)。这些补丁来源有两类:

  1. 已上游化(upstreamed):已经合入官方 Wine 的补丁;
  2. 纯本地补丁:因兼容性、时机等原因只存在于 Proton 中的补丁。

Rebase 的核心矛盾在于:新版本 Wine 可能已经包含了部分 Proton 补丁的内容,直接照搬会冲突或冗余;同时纯本地补丁又必须原样保留。因此,维护一套能区分两类补丁、可批量迁移、可安全中断续跑的流程,是每次升级成败的关键。

铁律:cherry-pick 必须区分-x参数

文档首先强调了 Proton 维护者在 cherry-pick 时的纪律:

  • 从上游 Winecherry-pick 到 Proton时,必须-x参数,这样原始提交 ID 会保留在提交信息中,形成可追溯的"来自上游"标记;
  • 反之,对于没有上游化的补丁,绝不使用-x,避免留下误导性的上游关联标记。

这条纪律的意义在 rebase 时兑现:Proton 的提交历史中,凡是带有-x标记(提交信息中带有 "cherry picked from commit ..." 字样)的提交,说明其内容已经在上游存在,新版本 rebase 时可以安全丢弃;而没有该标记的,则是必须继续携带的本地补丁。提交信息本身因此成为 rebase 时的过滤依据。

第一步:列出需要迁移的补丁清单

文档给出了生成"待迁移补丁列表"的核心命令(在 Wine 仓库中执行):

wine$ git log --pretty=oneline --reverse --grep='cherry pick' --invert-grep wine-4.2..proton_4.2

逐段拆解这条命令的语义:

  • git log:遍历提交历史;
  • wine-4.2..proton_4.2:范围限定为从 Wine 基线标签wine-4.2之后、到 Proton 分支proton_4.2为止的提交;
  • --grep='cherry pick'+--invert-grep排除提交信息中含 "cherry pick" 字样的提交(即排除已上游化、带-x标记的补丁),只留下纯本地补丁;
  • --pretty=oneline --reverse:以一行一条的形式输出,且按时间正序排列,方便后续按顺序逐条应用。

执行后得到的列表即当前版本基线之上需要原样迁移的补丁集合。接下来要做的,就是把这个列表(不带-x)逐一 cherry-pick 到新的 Wine release 标签上,边应用边解决冲突。

第二步:用pick_commits脚本批量迁移补丁

文档提供了一段精心设计的 bash 脚本pick_commits,相比 git 内置的git rebase --onto等手段,它更直观、更易配合人工干预:

#!/bin/bash # Cherry-picks commits from an input file in --pretty=oneline format. # Lines that begin with '#' are ignored. # Aborts when a cherry-pick fails. # Outputs the same input file on stderr, but with '#' prefixed to lines that were successfully cherry-picked. #Usage: # $ pick_commits to_pick 2> ~/to_pick2 # On pick failure, fix conflicts and use "git cherry-pick --continue", or # otherwise fix up the repo as desired. # Edit ~/to_pick2 to comment-out the commit that you fixed. # Continue using the new file: # $ pick_commits to_pick2 2> ~/to_pick # Repeat, alternating between to_pick and to_pick2. broken=0 while read -r l; do f=$(echo -n "$l" | cut '-d ' -f1 -) if [ $broken == 0 -a ${f:0:1} != '#' ]; then echo "Picking $l" git cherry-pick $f 2>&1 if [ $? -ne 0 ]; then echo $l 1>&2 broken=1 else echo '#'$l 1>&2 fi else echo $l 1>&2 fi done < "$1"

脚本工作机制解读

  • 输入:一个--pretty=oneline格式的补丁列表文件(即第一步命令的输出);
  • 注释行跳过:以#开头的行被忽略,用于标记"已处理/已放弃"的提交;
  • 顺序执行:逐行取出提交哈希(cut '-d ' -f1取第一个以空格分隔的字段),执行git cherry-pick
  • 失败即停:一旦某个 cherry-pick 失败($? -ne 0),把该行原样输出到 stderr 并置broken=1,终止后续操作,避免冲突雪崩;
  • 成功即标记:成功 picked 的提交,向 stderr 输出时前缀一个#,实现"处理进度即清单更新"。

标准用法与冲突处理循环

脚本设计成两文件交替的工作流,配合 stderr 重定向实现进度持久化:

$ pick_commits to_pick 2> ~/to_pick2 # 若中途失败: # 1. 手动解决冲突后执行 git cherry-pick --continue,或以其他方式修复仓库状态 # 2. 编辑 ~/to_pick2,把刚才失败的那条提交行加 '#' 注释掉 # 3. 用新文件继续: $ pick_commits to_pick2 2> ~/to_pick # 如此往复,在 to_pick 与 to_pick2 之间交替,直到清单全部处理完毕
  • 成功被 pick 的提交会以#开头写回新文件,下次运行时自动跳过;
  • 失败提交被手动注释后,其余未处理提交可以继续执行,做到任意断点续跑
  • 由于脚本输出"处理后的清单"到 stderr、原始日志到 stdout,重定向互不干扰,文件内容始终是"剩余任务 + 已完成标记"的完整快照。

第三步:Rebase 完成后更新 prefix 版本号

文档明确指出收尾动作:Wine rebase 完成后,更新 proton Python 脚本中的 prefix 版本号,并把 minor 版本重置回 1

这一要求在仓库源码中得到了完整印证。在 proton 脚本第 44 行:

CURRENT_PREFIX_VERSION="11.0-100"

prefix 版本号采用主版本.次版本-前缀号的结构,例如11.0-100。其作用体现在两个关键机制上:

  1. prefix 版本持久化setup_prefix()在 proton 中读取pfx/version文件获得旧版本号;初始化完成后在 proton 将CURRENT_PREFIX_VERSION写入该文件;
  2. 升级判定upgrade_pfx()在 proton 中,若旧版本号与CURRENT_PREFIX_VERSION不一致,即触发 prefix 升级逻辑,并打印Upgrading prefix from <旧版本> to <新版本>日志。

正因为每次启动都会比对版本号,每次 rebase 到新 Wine 后都必须提升该版本号,否则旧的 prefix 不会得到重新初始化,新的 Wine/DLL 行为也不会生效。而"重置 minor 版本"指的是:当主版本发生跨越(例如从4.11升到5.0)时,把-之后的子版本号从累加值重新置为1(如4.11-25.0-1),从而形成清晰的"大版本归零、小版本递增"的节奏。

源码中还能看到版本号比较的实际逻辑(proton):脚本会将旧版本.旧前缀号新版本.新前缀号逐一按主版本、次版本比较,若发现当前运行的 Proton 版本低于 prefix 记录版本,会判定为"降级场景",输出Removing newer prefix并清理由旧版本创建的 tracked files 后重建 prefix——这意味着不正确地回退 prefix 版本号会导致 prefix 被重建,用户数据迁移成本很高,进一步说明版本号管理必须谨慎。

与 Rebase 密切相关的仓库资产

执行 rebase 时,以下仓库资产值得配合使用:

  • wine/:内嵌的 Wine 源码树,rebase 的主战场;
  • dxvk/、vkd3d-proton/、dxvk-nvapi/、wineopenxr/:配套图形与接口组件,其版本往往与 Wine 版本联动,rebase 时通常需要同步升级;
  • proton:启动与 prefix 管理入口,CURRENT_PREFIX_VERSION的所在地;
  • proton_3.7_tracked_files:历史版本遗留的 tracked files 清单,供旧 prefix 升级路径使用(见 proton 中对 3.7 旧 prefix 的特殊处理);
  • Makefile.in 与 Makefile:构建入口,确认 rebase 后各组件版本一致性;
  • docs/REBASING_TIPS.md:本文所依据的官方操作文档,建议直接对照阅读。

此外,Proton 的构建和打包依赖 Docker 多阶段镜像(见 docker/proton.Dockerfile.in),其中 Wine 与 LLVM、Mingw 工具链的版本组合也需要在 rebase 时一并核对,必要时参考 docker/README.md 调整镜像构建参数。

总结

一次完整的 Proton Rebase 可以归纳为四个步骤:

  1. 区分补丁来源:cherry-pick 上游补丁一律加-x,本地补丁一律不加,让提交信息自带"可丢弃"标记;
  2. 生成迁移清单:用git log --grep='cherry pick' --invert-grep反向筛选出必须携带的本地补丁;
  3. 批量应用:借助pick_commits脚本按清单逐条 cherry-pick,冲突时修复后交替使用两份清单文件续跑;
  4. 更新版本号:在 proton 中提升CURRENT_PREFIX_VERSION并将 minor 重置为 1,触发 prefix 升级,使新 Wine 行为生效。

这套流程的核心价值在于:用统一的提交标记纪律 + 可断点续跑的工具脚本 + 自动触发的 prefix 升级机制,把"升级上游版本"这件高频、高风险的事,变成可控、可复现的工程操作。

【免费下载链接】ProtonCompatibility tool for Steam Play based on Wine and additional components项目地址: https://gitcode.com/gh_mirrors/pr/Proton

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询