lintstaged如何做到只lint-staged

45次阅读

共计 1589 个字符,预计需要花费 4 分钟才能阅读完成。

介绍

lint-staged 针对暂存的 git 文件运行 linters 并且不要让 ???? 进入你的代码库!

开始

去年的时候分享过一个主题——规范化工作流之约定式提交,主要内容是提交代码时对 暂存区 代码格式的校验和提交信息规范校验。当时就接触到了lint-staged,只知道这个工具能针对暂存区的文件处理,并未深入了解,那时候就有一些疑问埋在心里,最近得空,特来解疑。

疑问点:

git 分为暂存区和工作区,如果一个文件同时存在在两个区(某文件 git add 后又再次修改,如下图 test2.js),此时本地的文件内容实际上是等同未暂存区的,根据介绍 lint-staged 会 lint 暂存区的那个版本,那么这是怎么做到的呢?

先猜测:

使用 SourceTree 提交代码偶尔会比较卡,稍微窥得点儿(未暂存文件消失再重现),因此猜测可能是用了什么方法先清除未暂存文件然后再恢复。

猜测归猜测,还是要验证一下。

结论

经过分析,lint-staged在执行检查前会对保存当前文件状态,然后清除掉修改,再执行 lint 任务,执行完毕再恢复。

重点就是:如何保存?如何恢复?

我总结出 lint-staged 的流程大致如下

这样就很清晰了,由图可知,上述疑问点为 红色流程 部分,下面我们来分析一下流程中的具体实现。

分析

流程大致分为四部分:

  • Stashing changes
  • Running linters
  • Updating stash
  • Restoring local changes

我们来分别看一下每一步做了什么

保留案发现场并清除干扰(Stashing changes…)

git write-tree // 得到 indexTree
git add .
git write-tree // 得到 workingCopyTree
git read-tree $indexTree
git checkout-index -af // 清除文件修改(未暂存的 test2.js 被清除)

根据以上操作步骤得知,lint-staged通过 tree 对象 来保存暂存区目录和工作区目录,并清除掉工作区修改文件,操作完成后,可以看到,被修改的 test2.js 已经被清除(如下图)。

执行代码检查任务(Running linters…)

按照配置的命令走,比如配置了 "*.js": "eslint"

eslint test2.js test.js

更新(Updating stash…)

上一步(Running linters)如果有检查到错误,直接跳过走下一步(Restoring local changes)

git write-tree // 得到 formattedIndexTree  

这里需要特别声明一下,

如果上一步(Running linters)未检测到错误,那么这里得到的 formattedIndexTree 会和第一步的indexTree 一样,如果检测到错误并将修复后文件添加到暂存区,如配置命令是 eslint --fix , git add 的话,那么代码被修复过,formattedIndexTreeindexTree 不同

恢复案发现场(Restoring local changes…)

git read-tree $workingCopyTree // 首先恢复工作区内容,对应第一步的 git add .
git checkout-index -af // 清除工作区修改
git read-tree $formattedIndexTree // 恢复暂存区内容 
git apply $patch // 如果修复了代码,也应用到工作区

总结

归根结底,都是 git 对象的操作。

  • git-read-tree – Reads tree information into the index
  • git-write-tree – Create a tree object from the current index
  • git-checkout-index – Copy files from the index to the working tree

正文完
 0