Improve Git hooks documentation

This commit is contained in:
Pete Gonzalez 2020-08-04 16:11:12 -07:00
Родитель 5ebbc58d6b
Коммит e0dc9c0c6e
1 изменённых файлов: 50 добавлений и 73 удалений

Просмотреть файл

@ -4,89 +4,66 @@ title: Installing Git hooks
navigation_source: docs_nav
---
The Git version control system allows you to configure hook scripts that will be invoked when certain actions are
performed. (See Git's [Customizing Git](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) chapter
for complete documentation.) The basic idea is that you create shell scripts under your `.git/hooks` folder with
well-known names such as **pre-commit**, **post-update**, **prepare-commit-msg**, and so forth.
If the Git client sees these scripts, it will invoke them whenever the corresponding operations are performed.
The Git version control system allows you to configure hook scripts that will be invoked whenever certain actions
are performed. (See Git's [Customizing Git](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) chapter
for complete documentation.) The basic idea is that you create shell scripts with well-known names such as
**pre-commit**, **post-update**, **prepare-commit-msg**, and so forth. If the Git client finds these scripts
in the local **.git/hooks** folder, it will run the scripts whenever the corresponding operations are performed.
For security reasons, Git does not automatically install these scripts when you clone a repo. Instead, you must
invoke a command that creates them and chmods them to be executable. Rush can automate this for you!
For security reasons, Git will not automatically install these scripts when you clone a repo. Instead, each
developer must invoke a command that creates the files and chmods them to be executable. Rush can automate
this for you!
## Configuring Rush to install a Git hook script
As an example, suppose that we want to keep our source code tidy by automatically invoking the
[Prettier](https://prettier.io/) code formatter whenever someone commits a change to Git.
As an example, suppose we find that developers are making commits without a meaningful description of their work.
As a result, the Git history is difficult to understand. To solve this problem, might want to add a `commit-msg`
hook that requires the commit message to meet certain requirements. For example, here's a simple Bash script that
requires at least 3 words of text:
Here's how to set that up:
**1<!---->. Check your Rush version.** Make sure your **rush.json** file installs Rush 5.5.1 or newer, which
introduced support for Git hooks.
**2<!---->. Write the hook script.** In your repo folder, create a **pre-commit** shell script under the
"common" folder where Rush stores its configuration files. For this example, we'll use the popular
[pretty-quick](https://github.com/azz/pretty-quick) helper that invokes Prettier on a Git change set.
(This avoids reformatting the entire code base every time someone makes a change.)
**common/git-hooks/pre-commit**
```sh
**common/git-hooks/commit-msg**
```bash
#!/bin/sh
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# This is an example Git hook for use with Rush. To enable this hook, rename this file
# to "commit-msg" and then run "rush install", which will copy it from common/git-hooks
# to the .git/hooks folder.
#
# TO LEARN MORE ABOUT GIT HOOKS
#
# The Git documentation is here: https://git-scm.com/docs/githooks
# Some helpful resources: https://githooks.com
#
# ABOUT THIS EXAMPLE
#
# The commit-msg hook is called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero status after issuing
# an appropriate message if it wants to stop the commit. The hook is allowed to edit
# the commit message file.
COMMAND=common/temp/node_modules/.bin/pretty-quick
echo --------------------------------------------
echo Starting Git hook: pre-commit
if [ -f $COMMAND ]; then
echo Invoking $COMMAND
$COMMAND
else
echo Command not installed: $COMMAND
# This example enforces that commit message should contain a minimum amount of
# description text.
if [ `cat $1 | wc -w` -lt 3 ]; then
echo ""
echo "Invalid commit message: The message must contain at least 3 words."
exit 1
fi
echo Finished Git hook: pre-commit
echo --------------------------------------------
```
**3<!---->. Configure any required dependencies.** The script above requires the **pretty-quick** NPM package,
which in turn has a peer dependency on **prettier**. Since we're not setting up a full tooling project with its own
**package.json** file, we can simply add **prettier** and **pretty-quick** as Rush "preferred versions". This will
ensure that they get installed in the **common/temp/node_modules** folder root whenever `rush install` runs.
You would use it as follows:
**common/config/rush/common-versions.json**
```json
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json",
1. Add this file in your **common/git-hooks** folder, and commit to Git.
2. When a developer runs `rush install`, Rush will copy this file to be **.git/hooks/commit-msg**
3. When you run `git commit`, Git will find the script and invoke it
4. If the commit message is too short, the script returns a nonzero exit code; Git shows the
`Invalid commit message` notice and rejects the operation.
"preferredVersions": {
"prettier": "~1.15.1",
"pretty-quick": "~1.8.0"
}
}
Using Rush to install the hook script avoids the need for a separate solution such as the popular
[Husky](https://www.npmjs.com/package/husky) package. Note that Husky expects your repo to have a
root-level **package.json** and **node_modules** folder, and Husky runs shell commands for every Git operation
(even unused hooks); using Rush to install hooks avoids those limitations.
```
**4<!---->. Confirm that the hooks were installed.** Run `rush update`, and verify that Rush copied your
**pre-commit** script into into the **.git/hooks** folder of your local working folder.
Now we can try committing a change to Git. You should see our `Starting Git hook: pre-commit` message included
in Git's log output:
```sh
$ git commit -m "This is a test"
--------------------------------------------
Starting Git hook: pre-commit
Invoking common/temp/node_modules/.bin/pretty-quick
🔍 Finding changed files since git revision ac03c77b6.
🎯 Found 1 changed files.
✍️ Fixing up projects/test/src/TestClass.ts.
✅ Everything is awesome!
Finished Git hook: pre-commit
--------------------------------------------
[my-branch 0d4550305] test
1 file changed, 3 insertions(+), 1 deletions(-)
```
> The sample file shown above is a template that `rush init` generates when setting up a new repo.
> You can probably find a copy as
> [common/git-hooks/commit-msg.sample](https://github.com/microsoft/rush-example/blob/master/common/git-hooks/commit-msg.sample)
> in your own repo.