如何仅对暂存JS/TS文件中已变更代码行修复可修复的ESLint错误
如何仅对暂存JS/TS文件中已变更代码行修复可修复的ESLint错误
嘿,这个需求我之前在团队协作里刚好落地过,完全懂你想最小化修复范围、避免改动未修改代码的诉求。下面给你分享一套纯本地可实现的实操方案,核心思路就是先定位Git暂存区的目标文件和具体变更行,再让ESLint只针对这些行做修复,最后确保只保留变更行的修复结果并重新暂存:
一、基础准备
首先确保项目已经安装了eslint(这个肯定是必备的),我们会用到Node.js内置模块和Git原生命令,不需要额外安装第三方依赖,轻量又可靠。
二、编写核心Node.js脚本
在项目根目录新建scripts/fix-staged-lines.js文件,把下面的代码复制进去:
const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); // 筛选出暂存区中的JS/TS文件 const getStagedFiles = () => { try { const output = execSync( 'git diff --name-only --cached -- "*.js" "*.jsx" "*.ts" "*.tsx"', { encoding: 'utf-8' } ); return output.trim().split('\n').filter(file => file); } catch (err) { console.error('获取暂存文件失败:', err.message); return []; } }; // 解析单个文件的变更行范围(返回新文件中的行号数组) const getChangedLines = (filePath) => { try { // 用--unified=0参数只输出变更行的核心信息,减少解析复杂度 const diffOutput = execSync( `git diff --cached --unified=0 "${filePath}"`, { encoding: 'utf-8' } ); const changedLineNumbers = []; // 匹配diff中的行范围标记,比如@@ -123,0 +124,5 @@ 代表新文件中124-128行是变更内容 const rangeRegex = /@@ -\d+,\d+ \+(\d+),(\d+) @@/g; let matchResult; while ((matchResult = rangeRegex.exec(diffOutput)) !== null) { const startLine = parseInt(matchResult[1], 10); const lineCount = parseInt(matchResult[2], 10); // 把范围内的每一行号都存入数组 for (let i = startLine; i < startLine + lineCount; i++) { changedLineNumbers.push(i); } } return changedLineNumbers; } catch (err) { console.error(`解析${filePath}的变更行失败:`, err.message); return []; } }; // 仅对指定行执行ESLint自动修复 const fixTargetLines = (filePath, targetLines) => { if (targetLines.length === 0) return; // 1. 备份原文件内容,防止意外改动 const originalContent = fs.readFileSync(filePath, 'utf-8'); const originalLineList = originalContent.split('\n'); // 2. 创建临时文件,对整个文件执行ESLint修复(先拿到全量修复结果) const tempFile = path.join(path.dirname(filePath), `.temp-${path.basename(filePath)}`); fs.writeFileSync(tempFile, originalContent); try { // 忽略ESLint的非致命错误输出,只关注修复结果 execSync(`npx eslint --fix "${tempFile}"`, { stdio: 'ignore' }); } catch (err) { // 无法自动修复的规则会抛出错误,这里直接跳过不影响流程 } // 3. 读取修复后的临时文件内容 const fixedContent = fs.readFileSync(tempFile, 'utf-8'); const fixedLineList = fixedContent.split('\n'); // 4. 只保留变更行的修复结果,其他行还原成原内容 const finalLineList = [...originalLineList]; targetLines.forEach(lineNum => { // 注意:行号是从1开始计数,数组索引要减1 const lineIndex = lineNum - 1; if (fixedLineList[lineIndex] !== undefined && fixedLineList[lineIndex] !== originalLineList[lineIndex]) { finalLineList[lineIndex] = fixedLineList[lineIndex]; } }); // 5. 将筛选后的结果写回原文件 fs.writeFileSync(filePath, finalLineList.join('\n')); // 6. 清理临时文件 fs.unlinkSync(tempFile); }; // 主执行流程 const main = () => { const stagedFileList = getStagedFiles(); stagedFileList.forEach(file => { const absolutePath = path.resolve(file); const targetLineNumbers = getChangedLines(absolutePath); console.log(`处理文件: ${file},目标修复行: ${targetLineNumbers.join(', ')}`); fixTargetLines(absolutePath, targetLineNumbers); // 把修复后的文件重新暂存,确保提交的是修复后的版本 execSync(`git add "${absolutePath}"`); }); console.log('所有暂存文件的变更行修复完成!'); }; main();
三、配置自动触发(可选)
如果你想在每次提交代码前自动执行这个修复脚本,可以配置Git的pre-commit钩子:
- 到项目根目录的
.git/hooks文件夹下,新建pre-commit文件(不要加任何后缀),内容如下:
#!/bin/sh # 执行自定义的修复脚本 node scripts/fix-staged-lines.js # 继续执行后续的提交流程 exit 0
- 给这个钩子文件添加执行权限:
chmod +x .git/hooks/pre-commit
之后你每次运行git commit时,脚本都会自动处理暂存文件的变更行修复,不用手动触发。
一些小提醒
- 这个方案只处理ESLint标记为可自动修复的错误,对于无法自动修复的规则(比如部分
no-unused-vars场景),还是需要手动调整。 - 如果你的ESLint需要指定特殊配置文件(比如不在根目录的
tsconfig.json),可以在脚本的ESLint命令里加上--config参数指定路径。 - 首次使用建议先手动运行
node scripts/fix-staged-lines.js测试效果,确认符合预期后再配置自动钩子。
内容来源于stack exchange
相关产品推荐
相关产品推荐

