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

Patrick Hund picture Patrick Hund · Dec 2, 2017 · Viewed 9.6k times · Source

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?

Answer

str picture str · Dec 2, 2017

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"
    ]
  }
}