
为什么你不再需要git addlint-staged v10自动暂存变更与避免竞态条件的原理【免费下载链接】lint-staged — Run tasks like formatters and linters against staged git files项目地址: https://gitcode.com/gh_mirrors/li/lint-stagedlint-staged 是一款在 Git 提交前对暂存区staged文件运行格式化器、linter 等任务的命令行工具核心口号是别让屎进你的代码库。从v10版本开始lint-staged 内置了自动暂存auto-staging能力任务修改文件后它会统一执行git add把改动写回 Git 索引同时避免多个任务并发编辑同一文件时产生的竞态条件race condition。你只需要配置prettier --write这类命令再手动追加git add的做法已经成为历史。 旧式写法为什么危险手动 git add 的竞态隐患在 v10 之前典型的 lint-staged 配置长这样{ *.{js,ts}: [prettier --write, eslint --fix, git add] }每个任务链的最后都要手动加一步git add。这看似无害却在并行执行时埋下两大隐患并发写冲突lint-staged 默认并行运行任务见--concurrent选项。当两个任务都匹配到同一个文件时任务 A 可能还在写文件任务 B 就抢先执行了git add把写到一半的中间状态暂存进了索引。索引被半提交污染某个任务失败退出时另一个任务的git add可能已经执行导致索引和工作区不一致排查起来非常痛苦。官方在 v10.0.0 的发布说明中明确写道这一行为被整合进 lint-staged 本体就是为了防止多个任务编辑同一文件时的竞态条件并建议移除配置中的git add。详见 CHANGELOG.md 中 v10.0.0 的 BREAKING CHANGES 章节迁移说明也可参考 MIGRATION.md。⚙️ 自动暂存核心updateIndex 是如何工作的lint-staged v10 的整个 Git 生命周期由 lib/gitWorkflow.js 中的GitWorkflow类驱动其中负责自动git add的就是updateIndex方法lib/gitWorkflow.js它有几个关键设计只加匹配过的文件方法内部维护了一个matchedFiles集合在 lib/runAll.js 中收集即只把被任务 glob 匹配、且确实被任务修改过的暂存文件加回索引不会误伤其他文件。串行执行git add代码注释写着 Needs to be run serially because of locking Git operation——因为 Git 写索引时会加.lock锁所以git add必须逐个串行执行天然杜绝了并行写索引的竞争。处理长命令行通过 lib/getSpawnedTasks.js 中的chunkFilesForCommand把文件列表按平台命令行长度上限macOS 262144 / Windows 8191 / Linux 131072 字符二分切块避免参数过长。感知特殊索引场景如果检测到GIT_INDEX_FILE指向的是非默认 lock 文件例如git commit pathspec的用法它会额外再更新一次默认索引防止提交后留下残留 diff。空提交保护git add之后重新读取暂存文件列表如果任务把所有改动都格式化没了导致提交为空会抛出ApplyEmptyCommitError阻止空提交——除非你显式使用了--allow-empty选项。一句话总结所有任务跑完之后由 lint-staged 在唯一的、串行的时间点统一执行一次git add竞态条件自然消失。 完整工作流自动暂存发生在哪一步lib/runAll.js 串起了整个流程updateIndex恰好卡在任务执行之后、恢复现场之前步骤方法作用① 备份prepare()创建备份 stash保护原始状态② 隐藏未暂存改动hidePartiallyStagedChanges()让任务只看到本次要提交的内容③ 并行跑任务runTasks()执行 prettier / eslint 等④自动暂存updateIndex()统一git add任务产生的修改⑤ 恢复现场restoreUnstagedChanges()把第 ② 步隐藏的改动用 patch 贴回去⑥ 清理cleanup()删除备份 stash如果中间任何一步出错restoreOriginalState()会把工作区回滚到提交前的状态备份 stash 还能通过git stash list找回防止数据丢失。 如何迁移把 git add 从配置里删掉升级过程非常简单——打开你的配置比如项目根目录的 lint-staged.config.js把任务链里的git add删掉即可{ *.{js,ts,md}: prettier --write }如果忘了删也没关系lint-staged 会扫描每个任务的命令字符串一旦检测到包含git add就会在控制台打印黄色警告逻辑见 lib/runAll.js文案来自 lib/messages.js⚠ Some of your tasks usegit addcommand. Please remove it from the config since all modifications made by tasks will be automatically added to the git commit index.️ 相关选项速查控制自动暂存行为根据 README.md 的命令行参数文档有几个选项直接影响自动暂存的行为--fail-on-changes任务改动了文件时不自动暂存而是直接以退出码 1 失败。适合格式化必须干净通过的严格团队。--allow-empty任务把所有暂存改动都还原比如格式化回退了改动时允许继续创建空提交。--no-revert出错时不回滚原始状态方便你手动接管。--no-stash禁用备份 stash 机制适合 CI 等确定性环境。对应的自动化测试可参考 test/integration/allow-empty.test.js、test/integration/fail-on-changes.test.js 和 test/integration/no-revert.test.js。✅ 总结lint-staged v10 把git add从每个任务的末尾步骤提升为工作流中一次受控的串行操作省心配置里只写工具命令暂存交给工具链托管安全串行git add 索引锁感知彻底消除多任务并发写索引的竞态条件可靠备份 stash 自动回滚 空提交保护出错也不怕丢改动。下次写 pre-commit 钩子时就可以安心把git add从脑子里删掉了——lint-staged 已经替你把它做对了。【免费下载链接】lint-staged — Run tasks like formatters and linters against staged git files项目地址: https://gitcode.com/gh_mirrors/li/lint-staged创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考