【JavaScript】【Git】Git 管理下の変更されたファイルのみに対して任意のコマンドを実行する

 Git でコミットする前にコミット対象ファイルを整形したいことがあります。そして少々手間なことに、ファイルの種別によって実行環境やらなにやら個別に用意する必要があります。これをスクリプトによって適切に振り分けて解決したくなります。ざっくばらんに言えば lint-staged がやっていることをより自由度の高い形で実行したい、といった感じです。
okonet/lint-staged: 🚫💩 — Run linters on git staged files
 Git でコミットする予定の変更されたファイルにのみコマンドを実行するのは次のコードでできます。

  // gitのコマンドを実行
  const gitStatusStdOut = childProcess.execSync('git status -s').toString();
  // git status -sで次の様な文字列が標準出力されます
  // A addTest.txt
  // M app/Library/PDF/AppTcpdf.php
  // M database/seeders/EventOrderSeeder.php
  // M package.json
  // これらの内 A, M が今回変更されて色々処理すべきファイルです。これを正規表現で抜き出します
  const filePaths = gitStatusStdOut
    .split("\n")
    .map(line => line.match(/^\s*[AM] +(.*)$/)?.[1])
    .filter(v => !!v)
  ;
  // 対象のファイル一覧を表示。このファイルパスを元に色々できます。
  console.log(filePaths)

  // 以下は lint を docker 経由でかける例です。素の lint-staged では Windows の絶対パスが使われるので、docker に渡すのが手間です。

  // package.json の中からこのスクリプト用のデータセット app-lint-staged を抜き出す
  const p = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json')).toString())
  if (!p['app-lint-staged']) {
    return;
  }
  Object.keys(p['app-lint-staged']).forEach(regexStr => {
    // app-lint-staged中の設定に従ってファイルを振り分けて処理
    // ex.
    //     "app-lint-staged": {
    //         ".*\\.php": [
    //             "docker-compose run --rm app ./vendor/bin/php-cs-fixer fix -vvv --config ./.php-cs-fixer.php",
    //             "git add"
    //         ]
    //     },
    const regex = new RegExp(regexStr);
    filePaths.forEach(filePath => {
      if (!regex.test(filePath)) {
        return;
      }
      p['app-lint-staged'][regexStr].forEach(cmdStr => {
        console.log(`${cmdStr} "${filePath}"`)
        // package.json 内で定義されたコマンドの末尾にファイルパスを追記してコマンドを実行
        const res = childProcess.execSync(`${cmdStr} "${filePath}"`);
        console.log(res.toString())
      })
    })
  })

 こんな感じで特定のファイルにのみコマンドを実行できます。後は husky なり simple-git-hooks なりで適宜自動実行するようにすれば、自由で快適な Git フックが作れます。
typicode/husky: Modern native Git hooks made easy 🐶 woof!
toplenboren/simple-git-hooks: A simple git hooks manager for small projects

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG