# Git hook

When I work on a Flutter project with a team, I want clean code before every push.\
So I use **Git hook** to run checks automatically when we run Git commands.

Main idea:

* Stop errors early before code goes to remote.
* Reduce errors from forgetting `analyze` or tests.
* Help new teammates follow the same flow.

## Step 1: Create `.githooks` folder

```bash
mkdir -p .githooks
```

## Step 2: Create `pre-push` file

Goal in this example: always run `fvm flutter analyze` before push.

Create file:

```
.githooks/pre-push
```

Content:

```bash
#!/usr/bin/env bash

# Flutter Analyzer
printf "\e[33;1m%s\e[0m\n" '=== Running Flutter analyzer ==='

# Undo the stash of the files
pop_stash_files () {
    if [ -n "$hasChanges" ]; then
        printf "\e[33;1m%s\e[0m\n" '=== Applying git stash changes ==='
        git stash pop
    fi
}

fvm flutter analyze
if [ $? -ne 0 ]; then
  printf "\e[31;1m%s\e[0m\n" '=== Flutter analyzer error ==='
  pop_stash_files
  exit 1
fi

printf "\e[33;1m%s\e[0m\n" 'Finished running Flutter analyzer'
```

## Step 3: Activate Git hook

Run:

```bash
# Allow bash script execute
chmod -R 777 .githooks

# Authorize system can run all script in scripts folder
chmod -R 777 scripts

# Distinct the case sensitive file name
git config core.ignorecase false

git config core.hooksPath .githooks

# Append git env
bash scripts/appendGitEnvs.sh
```

## Combine with Make to group setup commands

You can group Git hook setup commands in one `Makefile` target so your team can run it quickly.

Example:

```makefile
.PHONY: setup-project
setup-project:
	@echo "Setting up project with git hooks"
	chmod -R 777 .githooks
	chmod -R 777 scripts
	git config core.ignorecase false
	git config core.hooksPath .githooks
	bash scripts/appendGitEnvs.sh
```

If you want full Make details, check this article:

{% content-ref url="../easy-code/make" %}
[make](https://wong-coupon.gitbook.io/flutter/easy-code/make)
{% endcontent-ref %}

## How it works

Git hook works by **hook file name**.\
If the file name is correct, Git will detect it and run it at the right time.

Common hook file names:

```
applypatch-msg
pre-applypatch
post-applypatch
pre-commit
prepare-commit-msg
commit-msg
post-commit
pre-rebase
post-checkout
post-merge
pre-push
pre-receive
update
post-receive
post-update
reference-transaction
push-to-checkout
pre-auto-gc
post-rewrite
sendemail-validate
fsmonitor-watchman
p4-changelist
p4-prepare-changelist
p4-post-changelist
p4-pre-submit
post-index-change
```

Example:

* `pre-commit` runs before `git commit`
* `pre-push` runs before `git push`

## How to disable

If you want to skip hook one time:

```bash
git commit --no-verify
git push --no-verify
```

If you want to disable project hook path:

```bash
git config --unset core.hooksPath
```

## Update Git hook in project

When you update scripts in `.githooks`, just commit it.\
Then the team can pull and run `setup-project` (or activation commands) to use the new hooks.

[Buy Me a Coffee](https://buymeacoffee.com/ducmng12g) | [Support Me on Ko-fi](https://ko-fi.com/I2I81AEJG8)
