1 | # pre-git
|
2 |
|
3 | > Important git hooks implemented using Nodejs for your project.
|
4 |
|
5 | [![NPM][pre-git-icon]][pre-git-url]
|
6 |
|
7 | [![Build status][pre-git-ci-image]][pre-git-ci-url]
|
8 | [![Build Status][snapci-image]][snapci-url]
|
9 | [![dependencies][pre-git-dependencies-image]][pre-git-dependencies-url]
|
10 | [![devdependencies][pre-git-devdependencies-image]][pre-git-devdependencies-url]
|
11 | [![semantic-release][semantic-image] ][semantic-url]
|
12 | [![manpm](https://img.shields.io/badge/manpm-%E2%9C%93-3399ff.svg)](https://github.com/bahmutov/manpm)
|
13 |
|
14 | [semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
|
15 | [semantic-url]: https://github.com/semantic-release/semantic-release
|
16 |
|
17 | ## Why?
|
18 |
|
19 | You can easily run the `pre-commit` and `pre-push` Git hooks to
|
20 | [avoid breaking the local master branch](http://glebbahmutov.com/blog/never-break-master-by-accident/)
|
21 | or the [remote master](http://glebbahmutov.com/blog/never-break-remote-master-again/).
|
22 |
|
23 | ### Installation
|
24 |
|
25 | It's advised to install this module as `devDependency` in your `package.json`
|
26 | file so it doesn't get installed on production servers. Run:
|
27 |
|
28 | ```
|
29 | npm install pre-git --save-dev
|
30 | ```
|
31 |
|
32 | ### Configuration
|
33 |
|
34 | Specify commands to run on *commit* and on *push* in your package.json under `config > pre-git`
|
35 | object.
|
36 |
|
37 | ```json
|
38 | "scripts": {
|
39 | "test": "node-qunit *.js"
|
40 | },
|
41 | "config": {
|
42 | "pre-git": {
|
43 | "enabled": true,
|
44 | "msg-pattern": "^(US|DE)\\d+ - .+",
|
45 | "commit-msg": "simple",
|
46 | "pre-commit": [
|
47 | "grunt jshint"
|
48 | ],
|
49 | "post-commit": "git status",
|
50 | "pre-push": [
|
51 | "rm -rf node_modules",
|
52 | "npm install",
|
53 | "grunt build",
|
54 | "grunt test"
|
55 | ],
|
56 | "post-checkout": "npm install",
|
57 | "post-merge": "npm install"
|
58 | }
|
59 | }
|
60 | ```
|
61 |
|
62 | If there are older settings like `pre-commit`, etc, you will have to move
|
63 | them to the `config > pre-git` object manually.
|
64 |
|
65 | Related project: [post-merge-make](https://github.com/bahmutov/post-merge-make)
|
66 | runs `make post-merge` after pull or merge.
|
67 |
|
68 | ## Windows
|
69 |
|
70 | Thanks to [ybiquitous](https://github.com/ybiquitous) for
|
71 | [adding support](https://github.com/bahmutov/pre-git/pull/72) for Windows.
|
72 |
|
73 | * Git Bash (Git for Windows): work fine!
|
74 | * Command prompt: work if sh.exe in PATH (e.g. `set PATH=C:\Program Files\Git\bin;%PATH%`)
|
75 |
|
76 | ## Untracked files
|
77 |
|
78 | Before the commit, we check if there are any untracked files. A commit does
|
79 | not continue if there are any. Please `git ignore` or delete unnecessary
|
80 | files before running the `git commit` command to ensure clean tests.
|
81 | In every case where I forgot to add files to the repo, this was by accident
|
82 | and caused breaking tests.
|
83 |
|
84 | This can be disabled by setting the `allow-untracked-files` option to true
|
85 |
|
86 | ```json
|
87 | {
|
88 | "config": {
|
89 | "pre-git": {
|
90 | "allow-untracked-files": true
|
91 | }
|
92 | }
|
93 | ```
|
94 |
|
95 | ## Details
|
96 |
|
97 | You can disable all `pre-git` hooks by setting the configuration option to
|
98 | false
|
99 |
|
100 | ```json
|
101 | {
|
102 | "config": {
|
103 | "pre-git": {
|
104 | "enabled": false
|
105 | }
|
106 | }
|
107 | ```
|
108 |
|
109 | If the 'config.pre-git' object has the option 'enabled' missing, it is
|
110 | assumed to be "true" and the hooks are executed.
|
111 |
|
112 | You can always skip pre-commit hook (but not pre-push hook!) by using `-n` option
|
113 |
|
114 | git commit -m "done, don't check me" -n
|
115 |
|
116 | You can skip the pre-push hook using `--no-verify` option
|
117 |
|
118 | To run just the hook (for example to test what it does), execute
|
119 |
|
120 | ```bash
|
121 | .git/hooks/pre-commit
|
122 | .git/hooks/pre-push
|
123 | ```
|
124 |
|
125 | Since there might be no changes to push, you can force the `pre-commit` hook to execute
|
126 | using `-f` or `--force` argument
|
127 |
|
128 | ```bash
|
129 | .git/hooks/pre-commit -f
|
130 | ```
|
131 |
|
132 | ## Validating commit message
|
133 |
|
134 | By default, this package will install both the message validator
|
135 | and the message format helper. You can disable the validation
|
136 | by removing the below command.
|
137 |
|
138 | ```json
|
139 | "config": {
|
140 | "pre-git": {
|
141 | "commit-msg": "conventional"
|
142 | }
|
143 | }
|
144 | ```
|
145 |
|
146 | When you run `git commit -m "message ..."` the hook will enforce the default style
|
147 | `type(scope): message ...`. To better form the message, there is a CLI wizard
|
148 | installed based on [commitizen](https://www.npmjs.com/package/commitizen) project,
|
149 | very well shown in the tutorial
|
150 | [video](https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-writing-conventional-commits-with-commitizen). The commit wizard is available under "node_modules/.bin/commit-wizard" link
|
151 | and can be started from command line
|
152 |
|
153 | node --harmony node_modules/.bin/commit-wizard
|
154 |
|
155 | or via a script
|
156 |
|
157 | ```json
|
158 | "scripts": {
|
159 | "commit": "commit-wizard"
|
160 | }
|
161 | ```
|
162 |
|
163 | Then run
|
164 |
|
165 | npm run commit
|
166 |
|
167 | The wizard will look something like this
|
168 |
|
169 | ```
|
170 | ? Select the type of change that you're committing:
|
171 | feat: A new feature
|
172 | ❯ fix: A bug fix
|
173 | chore: Changes to the build process or auxiliary tools
|
174 | and libraries such as documentation generation
|
175 | ```
|
176 |
|
177 | There are 2 plugins included with `pre-git`:
|
178 |
|
179 | * "conventional" follows AngularJS log convention,
|
180 | see [conventional-commit-message](https://github.com/bahmutov/conventional-commit-message)
|
181 | * "simple" only allows "feat", "fix" and "chore" commit types,
|
182 | see [simple-commit-message](https://github.com/bahmutov/simple-commit-message)
|
183 |
|
184 |
|
185 | I recommend sticking with "simple" unless you need more release types.
|
186 |
|
187 | ## Development
|
188 |
|
189 | In order to locally test this package, from another git repo execute the install script
|
190 | using `-f` or `--force` argument. For example
|
191 |
|
192 | ```
|
193 | $ node ../pre-git/src/install.js -f
|
194 | pre-git 0.7.2 in /Users/kensho/git/test-git-hooks
|
195 | /Users/kensho/git/test-git-hooks
|
196 | read target package from /Users/kensho/git/test-git-hooks/package.json
|
197 | added empty command list for hook commit-msg
|
198 | added empty command list for hook pre-commit
|
199 | added empty command list for hook pre-push
|
200 | added empty command list for hook post-commit
|
201 | added empty command list for hook post-merge
|
202 | saving updated files /Users/kensho/git/test-git-hooks/package.json
|
203 | ```
|
204 |
|
205 | ```json
|
206 | "config": {
|
207 | "pre-git": {
|
208 | "msg-pattern": "whatever-regex-without-delimiters"
|
209 | }
|
210 | }
|
211 | ```
|
212 |
|
213 | When using msg-pattern, the pre-git will match the commit message against the given pattern,
|
214 | if the test fails, then it will stop the execution and will exit the commit,
|
215 | this feature is optional and can be used along with any of the commit wizards, however
|
216 | those can be omitted using only the pattern, this is a useful manner of checking
|
217 | a custom message, as some commit may require custom codes as user story prefixes and so on.
|
218 |
|
219 | It is also possible to customize your own msg-pattern-error along with msg-pattern to be more descriptive
|
220 | as to why the pattern fails.
|
221 |
|
222 | ```json
|
223 | "config": {
|
224 | "pre-git": {
|
225 | "msg-pattern": "whatever-regex-without-delimiters",
|
226 | "msg-pattern-error": "whatever error message that will be thrown when the pattern fails"
|
227 | }
|
228 | }
|
229 | ```
|
230 |
|
231 | I am using a small project [test-pre-git](https://github.com/bahmutov/test-pre-git)
|
232 | as a test playground for these hooks.
|
233 |
|
234 | ### End to end testing
|
235 |
|
236 | To create a sample project and test the hooks, just run the included script
|
237 | `npm run e2e` which should finish with status zero.
|
238 |
|
239 | To see how `pre-git` stops a commit when a hook fails, run
|
240 | `npm run test-no-commit-on-test-fail` command, which should exit with status 1.
|
241 |
|
242 | You can verify the git hooks are not running when the `pre-git` is disabled
|
243 | via a config option by running `npm run e2e-pre-git-disabled` which allows
|
244 | the commit to go through.
|
245 |
|
246 | To see how `allow-untracked-files` option lets the commit go through,
|
247 | run `npm run test-allow-untracked-files`
|
248 |
|
249 | ## Debugging
|
250 |
|
251 | If a hook does not behave as expected, you can see verbose log messages by setting
|
252 | the environment variable `DEBUG=pre-git` when running a git command. For example, to
|
253 | see the messages when committing
|
254 |
|
255 | DEBUG=pre-git git commit -m "a message"
|
256 | running pre-commit script
|
257 | pre-git pre-commit +0ms arguments [ 'node',
|
258 | '/instant-vdom-todo/node_modules/.bin/pre-commit' ]
|
259 | pre-commit No changes detected, bailing out.
|
260 | pre-git found package in folder +0ms /instant-vdom-todo
|
261 | pre-git commit message wizard name from +5ms
|
262 | ...
|
263 |
|
264 | This should provide plenty of information to debug the hooks
|
265 |
|
266 | ## Desktop Git clients
|
267 |
|
268 | The Git hooks should work in desktop clients, like [GitHub Desktop app](https://desktop.github.com/).
|
269 |
|
270 | ## Local development
|
271 |
|
272 | To execute commit message validation, run `npm run demo-commit-message` and vary the
|
273 | test message to see how the hook validates it.
|
274 |
|
275 | ## Recent contributors
|
276 |
|
277 | * [ybiquitous](https://github.com/ybiquitous)
|
278 | * [Marko Schulz](https://github.com/datenreisender)
|
279 |
|
280 | ### Small print
|
281 |
|
282 | Author: Gleb Bahmutov © 2014
|
283 |
|
284 | * [@bahmutov](https://twitter.com/bahmutov)
|
285 | * [glebbahmutov.com](http://glebbahmutov.com)
|
286 | * [blog](http://glebbahmutov.com/blog)
|
287 |
|
288 | License: MIT - do anything with the code, but don't blame me if it does not work.
|
289 |
|
290 | Spread the word: tweet, star on github, etc.
|
291 |
|
292 | Support: if you find any problems with this module, email / tweet /
|
293 | [open issue](https://github.com/bahmutov/pre-git/issues?state=open) on Github
|
294 |
|
295 | [snapci-image]: https://snap-ci.com/bahmutov/pre-git/branch/master/build_image
|
296 | [snapci-url]: https://snap-ci.com/bahmutov/pre-git/branch/master
|
297 | [pre-git-icon]: https://nodei.co/npm/pre-git.svg?downloads=true
|
298 | [pre-git-url]: https://npmjs.org/package/pre-git
|
299 | [pre-git-ci-image]: https://travis-ci.org/bahmutov/pre-git.svg?branch=master
|
300 | [pre-git-ci-url]: https://travis-ci.org/bahmutov/pre-git
|
301 | [pre-git-dependencies-image]: https://david-dm.org/bahmutov/pre-git.svg
|
302 | [pre-git-dependencies-url]: https://david-dm.org/bahmutov/pre-git
|
303 | [pre-git-devdependencies-image]: https://david-dm.org/bahmutov/pre-git/dev-status.svg
|
304 | [pre-git-devdependencies-url]: https://david-dm.org/bahmutov/pre-git#info=devDependencies
|