UNPKG

8.99 kBMarkdownView Raw
1<h1 align="center">Precise Commits</h1>
2
3<p align="center">
4 <a href="https://travis-ci.org/JamesHenry/precise-commits"><img src="https://img.shields.io/travis/JamesHenry/precise-commits.svg?style=flat-square" alt="Travis"/></a>
5 <a href="https://github.com/JamesHenry/precise-commits/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/precise-commits.svg?style=flat-square" alt="GitHub license" /></a>
6 <a href="https://www.npmjs.com/package/precise-commits"><img src="https://img.shields.io/npm/v/precise-commits.svg?style=flat-square" alt="NPM Version" /></a>
7 <a href="https://www.npmjs.com/package/precise-commits"><img src="https://img.shields.io/npm/dt/precise-commits.svg?style=flat-square" alt="NPM Downloads" /></a>
8 <a href="http://commitizen.github.io/cz-cli/"><img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly" /></a>
9 <a href="https://github.com/semantic-release/semantic-release"><img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square" alt="semantic-release" /></a>
10</p>
11
12<br>
13
14# Why `precise-commits`?
15
16🔎 It is simply **the most exact and least disruptive way** to add consistent code formatting (by [Prettier](https://prettier.io)) to an existing codebase.
17
18✨ You only **reformat the exact code you have modified anyway** as part of your normal development!
19
20| Tool | Staged files | Existing commits | PR Build | Arbitrary commands | Precision |
21| ------------------- | ------------ | ---------------- | -------- | ------------------ | ------------------------------- |
22| **precise-commits** | ✅ | ✅ | ✅ | ❌ | **Individual character ranges** |
23| lint-staged | ✅ | ❌ | ❌ | ✅ | Entire File |
24| pretty-quick | ✅ | ❌ | ❌ | ❌ | Entire File |
25
26<br>
27
28# Background
29
30Implementing a new code-style in an existing codebase can be really tricky.
31
32[Prettier](https://prettier.io) is an amazing automated code formatting tool, but that does not mean that introducing it into an existing codebase is trivial.
33
34Regardless of how consistent the existing code-style might be, introducing [Prettier](https://prettier.io) will result in larger diffs, which:
35
361. Increases the complexity and review time burden of PRs on senior team members.
372. Potentially increases the amount of time it takes to complete a PR in the first place.
383. Can block concurrent work on the same codebase and/or result in nasty merge conflicts with outstanding feature branches.
39
40Other tools, such as `lint-staged`, made an excellent first step towards mitigating the scope of the impact of the points above, by only running linters and formatters on files which have changed.
41
42This is great for small codebases, in which the authors do not mind much that they are polluting the git history of the files they are touching, but **it is not enough**.
43
44In large and enterprise codebases (particularly those organized as monorepos), the git history of each file is really important.
45
46> If I make a change on line 10 of a 4000 line file, I shouldn't be forced to reformat all 4000s lines (thus making me the last git user to update all of them) as part of my PR.
47>
48> I should just need to reformat line 10.
49
50This is where `precise-commits` comes in!
51
52<br>
53
54# Our ideal end-goal...
55
561. All developers on our team develop using consistent, automated formatting as they write their code.
57 e.g. Running an IDE-based plugin, such as "vscode-prettier" with "format on save" enabled.
58
592. Each time they commit, a precommit hook is triggered to _ensure_ that the staged code is formatted consistently.
60
613. Each time a Pull Request opened on our remote repo, a build is triggered on a CI server, during which the formatting
62 is checked to ensure that all the files touched for that PR were formatted consistently.
63
64<br>
65
66# How `precise-commits` helps us get there...
67
681. All developers on our team write their code as they always have.
69
702. Each time they commit, a precommit hook is triggered which will run `precise-commits` on the code and ensure that **the exact code they already modified** is formatted consistently. Any untouched existing code will not be mutated.
71
723. Each time a Pull Request opened on our remote repo, a build is triggered on a CI server, during which `precise-commits`
73 runs to ensure that all the **committed lines of code** for that PR was formatted consistently.
74
75<br>
76
77...and after enough time has passed, **our codebase will be formatted consistently, despite us never having to disrupt our feature-building momentum!**
78
79<br>
80
81# How it works
82
83Through analyzing your staged files (or any files modified between two given commit SHAs) `precise-commits` will work out exactly what lines and characters within those files have actually been changed or added.
84
85It then uses this information to run [Prettier](https://prettier.io) in a very focused way, allowing it to only reformat what is relevant for your current work, and allowing you to keep your PRs small and explicit!
86
87<br>
88
89# Installation
90
91`precise-commits` expects `prettier` to be available as a `peerDependency`, so you will need to install this yourself as a `devDependency` of your project.
92
93```sh
94npm install --save-dev prettier precise-commits
95```
96
97<br>
98
99# Usage
100
101It is intended that you will run `precise-commits` as a CLI, and it will automatically pick up on any of the standard [Prettier configuration files](https://prettier.io/docs/en/configuration) you may have in your project, including [`.prettierignore`](https://prettier.io/docs/en/ignore#ignoring-files) files.
102
103## 1. Running it manually
104
1051. Add an npm script to your package.json, such as:
106
107```js
108{
109 //...
110 "scripts": {
111 "precise-commits": "precise-commits"
112 }
113 //...
114}
115```
116
1172. Execute the npm script, e.g. for the one above run:
118
119```sh
120npm run precise-commits
121```
122
123## 2. "Precommit" Hook
124
125The recommended way to run `precise-commits` is as a "precommit" hook.
126
127A great tool for setting up the hook is [`husky`](https://github.com/typicode/husky). You can install and run it as follows:
128
129```sh
130npm install --save-dev husky
131```
132
133Update the `"scripts"` section of your `package.json`:
134
135```js
136{
137 //...
138 "scripts": {
139 "precise-commits": "precise-commits",
140 "precommit": "npm run precise-commits"
141 }
142 //...
143}
144```
145
146## 3. As part of a PR build
147
148When running a build for your PR, you can run `precise-commits` to ensure that the author's changes are all formatted consistently.
149
150The key things you need to configure are:
151
1521. The `--check-only` flag for `precise-commits` so that it will error out if it finds any inconsistent formatting
1532. The `--head` and `--base` flags so that `precise-commits` knows what commits it should consider when resolving modified files. Most CI servers will have environment variables you can use to resolve these.
154
155For example, if your PR is building on [Travis](https://travis-ci.com/), your config might look like this:
156
157**.travis.yml**
158
159```yaml
160# ... Other config options here ...
161install:
162 - yarn install
163script:
164 - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then precise-commits --whitelist="src/**/*.ts" --check-only --head=$TRAVIS_PULL_REQUEST_SHA --base=$(git merge-base HEAD $TRAVIS_BRANCH); fi'
165 - yarn test
166 - yarn e2e
167# ... Other config options here ...
168```
169
170<br>
171
172# CLI Configuration Options
173
174As was hinted at above, the `precise-commits` CLI supports a few different configuration options:
175
176* `--whitelist`: **[String, Default: `"*"`]**
177 * Whitelist is a glob pattern ([the glob syntax from the glob module is used](https://github.com/isaacs/node-glob/blob/master/README.md#glob-primer)).
178 * It is used to inform what files are considered when resolving modified files (by default all are considered).
179 * Don't forget the quotes around the globs! The quotes make sure that `precise-commits` expands the globs rather than your shell.
180
181<br>
182
183* `--formatter`: **[String, Default: `"prettier"`]**
184 * Currently only prettier is supported
185 * If you are interested in adding support for a different formatter, all you need to do is provide an object which [implements this interface](https://github.com/JamesHenry/precise-commits/blob/master/src/precise-formatter.ts).
186
187<br>
188
189* `--check-only`: **[Boolean, Default: `false`]**
190 * Only check the code formatting is consistent with the resolved config
191
192<br>
193
194* `--base`: **[String, NO DEFAULT]**
195 * Base commit SHA to be used in conjunction with the `--head` flag
196
197<br>
198
199* `--head`: **[String, CONDITIONAL DEFAULT]**
200 * Later commit SHA (e.g. the `HEAD` of a PR branch) to be used in conjunction with the `--base` flag
201 * NOTE on conditional default: If no value is provided for `--head`, but a value is given for `--base`, it will default to checking "HEAD"