javascriptgitcode-formattingpre-commit-hookprettier

How Do I Run Prettier Only on Files That I Want to Commit?


Using Husky, I've set up my package.json with a precommit hook so that my JavaScript code is formatted using Prettier before every commit:

{
  "name": "prettier-demo",
  "scripts": {
    "precommit": "prettier --write **/*.js && git add ."
  },
  "devDependencies": {
    "husky": "^0.14.3",
    "prettier": "^1.8.2"
  }
}

This works fine, but there are two drawbacks:

  1. If I have a large project with thousands of JavaScript files, I have to wait for Prettier to process all of them, even if only a few have changed; this can take very long and gets on my nerves quickly when it is done with every commit

  2. Sometimes I want to stage just a couple of files for committing, leaving other changes out of the commit; because I do a git add . after running Prettier, all my changes will always end up in the commit

How can I run Prettier before every commit only on the files that have been staged, ignoring unstaged or unchanged files?


Solution

  • You can do that using lint-staged:

    Linting makes more sense when running before committing your code. By doing that you can ensure no errors are going into repository and enforce code style. But running a lint process on a whole project is slow and linting results can be irrelevant. Ultimately you only want to lint files that will be committed.

    This project contains a script that will run arbitrary npm and shell tasks with a list of staged files as an argument, filtered by a specified glob pattern.

    Install lint-staged and husky, which is required for pre-commit hooks, with this command:

    npm install --save-dev lint-staged husky
    

    Change your package.json as follows:

    {
      "scripts": {
        "precommit": "lint-staged"
      },
      "lint-staged": {
        "*.js": [
          "prettier --write",
          "git add"
        ]
      }
    }