ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SWE-agent 格式化冲突解决实战:ruff-format 与 pre-commit 引入后的 Git 分支同步与 Rebase 指南

2026/9/13 18:45:59 拓冰建站 浏览量
SWE-agent 格式化冲突解决实战:ruff-format 与 pre-commit 引入后的 Git 分支同步与 Rebase 指南 SWE-agent 格式化冲突解决实战ruff-format 与 pre-commit 引入后的 Git 分支同步与 Rebase 指南【免费下载链接】SWE-agentSWE-agent takes a GitHub issue and tries to automatically fix it, using your LM of choice. It can also be employed for offensive cybersecurity or competitive coding challenges. [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/sw/SWE-agent本文是 SWE-agent 项目开发者文档docs/dev/formatting_conflicts.md的深度解读与实战扩展。SWE-agent 在 2024 年 5 月 28 日起为代码库引入了ruff-format自动化格式化和pre-commit钩子这一变更几乎改写了仓库内所有文件。如果你在此变更之前 fork 或创建了分支如今试图将你的 fork/branch 与SWE-agent/SWE-agent:main同步时会遭遇大量合并冲突。本文将完整复现官方解决方案并结合仓库内的 .pre-commit-config.yaml、pyproject.toml 与 开发贡献指南 的源码级细节帮助你一次性、自动化地化解这些格式化冲突并保持功能提交的完整可追溯性。一、冲突从何而来一次全仓格式化变更的背景在 SWE-agent 的版本历史中0.5.0 版本的发布说明明确记录了这次变更见 changelogWe have reformatted our codebase. If you create a PR based on a previous commit, make sure you install ourpre-commithook to avoid merge-conflicts because of formatting.也就是说格式化变更属于破坏性变更breaking change任何基于旧提交创建的分支或 fork在与最新main同步时git 会把格式化重排的代码与你的功能改动混在同一批 diff 中从而在几乎每个文件上都产生冲突。其根源在于格式化工具会重排空白、引号风格、行长度与 import 顺序而这类纯格式改动与内容改动在合并时无法被 git 自动区分。要彻底解决官方给出的思路非常清晰让你的分支也应用同一套格式化规则再通过带-Xtheirs与--exec的特殊 rebase把每个提交都重放为先恢复功能改动、再套用格式化、最后重新提交的标准形态。二、冲突解决前置准备格式化工具的配置文件真相在执行官方 rebase 方案之前先理解这条命令为什么能生效——因为它依赖两份关键配置文件它们定义了格式化之后的代码应该长什么样2.1.pre-commit-config.yaml五类钩子的职责仓库根目录的 .pre-commit-config.yaml 定义了完整的提交前检查链共注册了 5 个仓库钩子来源版本职责pre-commit/pre-commit-hooksv6.0.0通用检查大文件、大小写冲突、合并冲突标记、符号链接、行尾、私钥、AST 语法、尾随空白crate-ci/typosv1针对.py/.md/.rst/.yaml/.toml的拼写检查astral-sh/ruff-pre-commitv0.15.20①ruff静态检查带--fix自动修复②ruff-format代码格式化pre-commit/mirrors-prettierv4.0.0-alpha.8对javascript、css文件格式化其中与格式化冲突直接相关的是ruff与ruff-format两个钩子。配置还通过exclude排除了tests/test_data/与tools/目录下带路径的 Python 文件因此在手动执行格式化时这些目录内的文件不会被改动。2.2pyproject.toml中[tool.ruff]的格式化规则格式化长什么样由 pyproject.toml 中的[tool.ruff]表决定核心规则如下line-length 120行宽上限为 120 字符超出会被折行indent-width 4缩进宽度 4 空格target-version py310目标语法版本为 Python 3.10[tool.ruff.format]quote-style double统一双引号、indent-style space空格缩进、skip-magic-trailing-comma false尊重魔法尾逗号、line-ending auto自动检测行尾[tool.ruff.lint]启用了大量规则PyflakesF、pycodestyleE、pyupgradeUP、bugbearB、flake8-errmsgEM、pytestPT、flake8-use-pathlibPTH等并允许--fix修复全部可修复规则fixable [ALL]。也就是说官方 rebase 命令中的pre-commit run与pipx run ruff check --fix --unsafe-fixes实际执行的就是上面这份规则集。你的分支只有应用了同一套规则git 才能在后继合并中把格式化差异消化掉。2.3 快速自检你的格式化环境是否就绪在开始 rebase 前建议先确认本地环境具备pre-commit与pipx。若尚未安装可参考 开发环境搭建说明# 从源码安装开发依赖包含 pre-commit、pytest 等 pip install -e .[dev]pre-commit会在每次提交前自动运行钩子若首次运行因修复失败导致git commit报错通常再执行一次即可多数问题会被自动修复。三、完整实操四步化解全仓格式化冲突下面完整复现官方方案并对每一步给出补充说明。步骤 1添加官方远程并拉取最新代码git remote add upstream https://github.com/SWE-agent/SWE-agent.git git fetch upstream如果upstream已存在git remote add会报错此时忽略该警告即可说明之前已添加。步骤 2从main取回最新格式化配置文件git checkout upstream/main -- .pre-commit-config.yaml pyproject.toml git commit -m Update formatting instructions --no-verify这条命令把两份配置从upstream/main检出到你的分支并提交。--no-verify用于跳过 pre-commit 钩子此时钩子可能尚未安装或配置刚更新直接提交更稳妥。步骤 3创建分支副本保留原分支不动export FEATURE_BRANCHmain # 如果你的改动在 main 上则如此设置 git branch ${FEATURE_BRANCH}_REBASED ${FEATURE_BRANCH}这里把功能分支名存入环境变量FEATURE_BRANCH然后基于它创建副本${FEATURE_BRANCH}_REBASED。副本的存在保证原分支不被修改方便失败后回退。步骤 4执行带格式化修复的 rebase核心步骤git rebase upstream/main ${FEATURE_BRANCH}_REBASED \ -Xtheirs \ --exec git reset --soft HEAD^; pre-commit run; pipx run ruff check --fix --unsafe-fixes; git add -u; git commit -C HEAD{1} --no-verify这条命令是整套方案的关键下面逐段拆解片段作用git rebase upstream/main ${FEATURE_BRANCH}_REBASED将${FEATURE_BRANCH}_REBASED上的每一个提交依次重放到upstream/main之上-Xtheirs遇到合并冲突时始终采用**你这一侧theirs即被重放的提交**的改动而非上游的格式化改动--exec ...在每个提交重放完成后执行指定的 shell 命令git reset --soft HEAD^撤销刚才的git commit动作soft 模式保留变更处于已暂存状态pre-commit run运行全部 pre-commit 钩子包含ruff与ruff-format自动修复格式pipx run ruff check --fix --unsafe-fixes额外启用 ruff 的不安全自动修复处理pre-commit默认不处理的修复项git add -u将格式化后的变更加入暂存区git commit -C HEAD{1} --no-verify沿用原提交的 message 重新提交格式化后的内容--no-verify再次跳过钩子提示HEAD{1}引用的是reset之前那个提交即原提交-C表示复用其提交信息因此格式化前后提交信息保持一致历史可读性不受影响。四、仍然遇到冲突怎么办非格式化冲突的排查官方文档明确指出-Xtheirs只会处理与格式化相关的冲突。如果 rebase 过程中仍有无法自动解决的冲突说明这些冲突与格式化无关例如双方都修改了同一段逻辑代码。此时git rebase会在无法解决冲突的提交处自动停下像平时一样手工编辑冲突文件、解决冲突将解决结果提交继续执行git rebase --continuerebase 会继续处理后续提交直到全部完成。五、收尾合并回主干或发起 PRrebase 完成后你的历史已被完整重写每个提交都应用了最新的格式化规则每个提交都保留了原有的提交信息与功能改动与upstream/main之间不再存在因格式化产生的大量冲突。此时你有两个选择# 从副本分支发起 PR git push -u origin ${FEATURE_BRANCH}_REBASED或者将副本提升为新的默认分支合并回原分支后推送git checkout ${FEATURE_BRANCH} git merge ${FEATURE_BRANCH}_REBASED需要说明的是rebase 会重写提交历史如果该分支此前已推送到远程并被他人使用建议仅对尚未共享的分支执行此操作避免影响协作者。六、预防胜于修复如何避免未来再次遇到格式化冲突从项目视角看格式化冲突是可以从源头避免的。SWE-agent 的 开发贡献指南 给出了两条实用建议6.1 提交前先跑一遍全仓格式化# 在仓库根目录执行 pre-commit run --all-files在提交或发起 PR 之前手动执行一次全仓检查可以确保所有文件而不仅是本次改动文件都满足格式化要求。6.2 提交时让 pre-commit 自动把关# cd 到仓库根目录后执行一次即可 pre-commit install安装后每次git commit都会自动触发钩子。多数问题包括格式会被自动修复若首次提交因自动修复失败直接再提交一次即可。6.3 需要更多自动修复时启用 ruff 不安全修复pipx run ruff check --fix --unsafe-fixes--unsafe-fixes会启用规则集中标记为不安全的自动修复覆盖面比 pre-commit 默认执行更广这正是官方 rebase 命令也调用它的原因。七、测试验证格式化后代码仍应通过测试格式化只改变代码外观不应改变行为。重写历史后建议运行仓库测试确认一切正常。项目在 pyproject.toml 中配置了 pytesttestpaths [tests]慢测试用slowmarker 标记因此可以直接运行# 快速运行排除慢测试 pytest -m not slow # 或全部测试 pytest总结SWE-agent 的全仓格式化变更虽然给旧分支的同步带来了阵痛但官方给出的更新配置 → 分支副本 →-Xtheirs--exec重放四步方案可以自动化地把格式化差异从历史中洗掉让每个提交同时具备完整的功能改动、统一的格式化风格、保留的提交信息以及与上游干净可合并的历史。配合本文补充的 .pre-commit-config.yaml 钩子清单、pyproject.toml 的 ruff 规则详解与预防性配置你可以把这套方法论直接迁移到任何遭遇全仓格式化变更的开源协作场景中。更多相关内容可参阅 开发贡献指南、SWE-agent 变更记录 与 开发者文档首页。【免费下载链接】SWE-agentSWE-agent takes a GitHub issue and tries to automatically fix it, using your LM of choice. It can also be employed for offensive cybersecurity or competitive coding challenges. [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/sw/SWE-agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考