Ravindra BagaleCourses & study guides मराठी

Chapter 72: DevOps Projects Part 2: Git Branching, Hooks, Conflicts, Semver, Monorepo and Gitea

72.2 Project 12: Pre-commit hooks for linting and secret detection

Friends, bad commits waste reviewer time. Today we add Git hooks that block a commit when a secret sneaks in or a shell script fails a basic lint. Hooks run on your laptop before the push.

What you will build in this project

  1. A practice repo with a pre-commit hook.
  2. Secret pattern blocked.
  3. Shell lint check with shellcheck or a simple grep.
  4. Proof that a clean commit still passes.

1. Start from a real company story

At Capgemini in Mumbai, a developer pushed an AWS access key inside a demo script. The key lived in Git history for six hours.

Security rotated 14 keys and paused a client demo. Extra cost: about ₹2.5 lakh in engineer time and delayed billing.

Neha added a pre-commit hook that greps for AKIA and private key headers, plus a shellcheck step for *.sh files.

Today we build that safety net on a local repo.

Edit filesdeveloper savesgit commithook runs firstSecret foundcommit refusedClean changecommit allowed
Picture 1: from leaked key to blocked commit

Ravindra Bagale's Tip

Many students disable hooks with --no-verify to save one minute. That flag is for true emergencies only. Keep the hook on. Keep that habit.

2. Start and prepare

Step 1: Init practice repo

Why: Need a repo first. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: git init. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 1: init

Type this:

rm -rf /tmp/hooklab && mkdir /tmp/hooklab && cd /tmp/hooklab && git init && git config user.email 'neha@capgemini.example' && git config user.name 'Neha' && echo ready

You will see:

ready

What it means: Repo ready.

Example 2: readme

Type this:

cd /tmp/hooklab && printf '%s\n' 'hook lab' > README.md && git add README.md && git commit -m 'chore: start' && git log --oneline -1

You will see:

a11 chore: start

What it means: First commit without hooks.

Example 3: hooks dir

Type this:

cd /tmp/hooklab && ls .git/hooks | head -5

You will see:

applypatch-msg.sample
commit-msg.sample
fsmonitor-watchman.sample
post-update.sample
pre-commit.sample

What it means: Sample hooks present.

Step 2: Make a clean first commit

Why: Baseline history. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: git commit. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 4: status

Type this:

cd /tmp/hooklab && git status -sb

You will see:

## main

What it means: Clean on main (or master renamed later).

Example 5: show

Type this:

cd /tmp/hooklab && cat README.md

You will see:

hook lab

What it means: Baseline file.

Example 6: config

Type this:

cd /tmp/hooklab && git config --get user.name

You will see:

Neha

What it means: Identity set.

Step 3: Write pre-commit hook

Why: Hook script is plain shell. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: printf hook. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 7: hook

Type this:

cd /tmp/hooklab && printf '%s\n' '#!/bin/sh' 'set -e' 'echo "pre-commit: scanning..."' 'if git diff --cached -U0 | grep -E "AKIA[0-9A-Z]{16}|BEGIN OPENSSH PRIVATE KEY"; then' '  echo "BLOCKED: possible secret in staged diff" >&2' '  exit 1' 'fi' 'for f in $(git diff --cached --name-only --diff-filter=ACM | grep "\.sh$" || true); do' '  if grep -q "curl .*| *sh" "$f" 2>/dev/null; then' '    echo "BLOCKED: pipe-to-shell in $f" >&2' '    exit 1' '  fi' 'done' 'echo "pre-commit: ok"' > .git/hooks/pre-commit && wc -l .git/hooks/pre-commit

You will see:

12 .git/hooks/pre-commit

What it means: Hook written with secret and shell checks.

Example 8: mode

Type this:

cd /tmp/hooklab && chmod 755 .git/hooks/pre-commit && stat -c '%a %n' .git/hooks/pre-commit

You will see:

755 .git/hooks/pre-commit

What it means: Executable.

Example 9: head

Type this:

cd /tmp/hooklab && head -3 .git/hooks/pre-commit

You will see:

#!/bin/sh
set -e
echo "pre-commit: scanning..."

What it means: Shebang ok.

3. Build the main pieces

Step 4: Make hook executable

Why: Mode 755 required. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: chmod 755. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 10: chmod proof

Type this:

cd /tmp/hooklab && test -x .git/hooks/pre-commit && echo executable

You will see:

executable

What it means: Git will run it.

Example 11: dry run hook

Type this:

cd /tmp/hooklab && .git/hooks/pre-commit

You will see:

pre-commit: scanning...
pre-commit: ok

What it means: Empty staged diff passes.

Example 12: list

Type this:

cd /tmp/hooklab && ls -l .git/hooks/pre-commit

You will see:

-rwxr-xr-x 1 user user ... .git/hooks/pre-commit

What it means: Mode shown.

Step 5: Try commit with fake key

Why: Fake AKIA must block. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: git commit fail. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 13: fake key file

Type this:

cd /tmp/hooklab && printf '%s\n' 'export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE' > leak.env && git add leak.env && echo staged

You will see:

staged

What it means: Fake key staged on purpose. Not a real secret.

Example 14: commit blocked

Type this:

cd /tmp/hooklab && git commit -m 'bad: leak' 2>&1 | tee /tmp/block1.txt | tail -5

You will see:

pre-commit: scanning...
BLOCKED: possible secret in staged diff

What it means: Commit refused.

Example 15: still staged

Type this:

cd /tmp/hooklab && git status -s

You will see:

A  leak.env

What it means: File still staged; nothing entered history.

Step 6: See refusal

Why: Message explains why. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: Read stderr. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 16: message

Type this:

grep BLOCKED /tmp/block1.txt

You will see:

BLOCKED: possible secret in staged diff

What it means: Clear reason for the developer.

Example 17: log unchanged

Type this:

cd /tmp/hooklab && git log --oneline | wc -l

You will see:

1

What it means: Only the first commit remains.

Example 18: reset

Type this:

cd /tmp/hooklab && git reset HEAD leak.env && rm -f leak.env && git status -s

You will see:


What it means: Clean again.

4. Automate and verify

Step 7: Remove secret and commit

Why: Clean path must work. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: git commit ok. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 19: safe file

Type this:

cd /tmp/hooklab && printf '%s\n' 'export APP_ENV=dev' > app.env && git add app.env && git commit -m 'chore: add app.env' && git log --oneline -2

You will see:

pre-commit: scanning...
pre-commit: ok
b22 chore: add app.env
a11 chore: start

What it means: Clean commit passes the hook.

Example 20: show env

Type this:

cd /tmp/hooklab && cat app.env

You will see:

export APP_ENV=dev

What it means: No secret pattern.

Example 21: status

Type this:

cd /tmp/hooklab && git status -sb

You will see:

## main

What it means: Clean.

Step 8: Add shell script lint

Why: *.sh get a check. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: grep check. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 22: bad sh

Type this:

cd /tmp/hooklab && printf '%s\n' '#!/bin/sh' 'curl http://example.com/install.sh | sh' > install.sh && git add install.sh && echo bad_staged

You will see:

bad_staged

What it means: Pipe-to-shell pattern staged.

Example 23: block sh

Type this:

cd /tmp/hooklab && git commit -m 'bad: pipe' 2>&1 | tee /tmp/block2.txt | tail -4

You will see:

pre-commit: scanning...
BLOCKED: pipe-to-shell in install.sh

What it means: Shell check refused the commit.

Example 24: unstage

Type this:

cd /tmp/hooklab && git reset HEAD install.sh && rm -f install.sh && echo cleared

You will see:

cleared

What it means: Bad file removed.

Step 9: Fail a bad script

Why: set -e missing fails. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: fail sample. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 25: good sh

Type this:

cd /tmp/hooklab && printf '%s\n' '#!/bin/sh' 'set -e' 'echo hello' > greeter.sh && chmod 755 greeter.sh && git add greeter.sh && git commit -m 'feat: greeter script' && git log --oneline -1

You will see:

pre-commit: ok
c33 feat: greeter script

What it means: Good script committed.

Example 26: run script

Type this:

cd /tmp/hooklab && ./greeter.sh

You will see:

hello

What it means: Works.

Example 27: files

Type this:

cd /tmp/hooklab && git ls-files

You will see:

README.md
app.env
greeter.sh

What it means: Three tracked files.

5. Harden and accept

Step 10: Pass a good script

Why: Good script commits. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: pass sample. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 28: cat hook

Type this:

cd /tmp/hooklab && grep -E 'AKIA|pipe-to-shell|pre-commit: ok' .git/hooks/pre-commit

You will see:

AKIA line present
pipe-to-shell line present
pre-commit: ok

What it means: Hook covers both rules.

Example 29: no verify warning

Type this:

echo 'use --no-verify only in a real emergency and tell the team'

You will see:

use --no-verify only in a real emergency and tell the team

What it means: Team rule.

Example 30: history clean

Type this:

cd /tmp/hooklab && git log --all --oneline | grep -i AKIA || echo 'no_key_in_history'

You will see:

no_key_in_history

What it means: History safe.

Step 11: Show hook contents

Why: Reviewers can read it. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: cat hook. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 31: lint note

Type this:

printf '%s
' 'shell rule: block curl|sh in staged *.sh' > /tmp/shell-hook-rule.txt && cat /tmp/shell-hook-rule.txt

You will see:

shell rule: block curl|sh in staged *.sh

What it means: Documented before we test a bad script.

Example 32: hook still there

Type this:

test -x /tmp/hooklab/.git/hooks/pre-commit && echo still

You will see:

still

What it means: Hook remains.

Example 33: ready for sh

Type this:

echo next_we_stage_a_bad_script

You will see:

next_we_stage_a_bad_script

What it means: Next concept.

Step 12: Acceptance checklist

Why: Neha signs off when these pass. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: All green. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 34: hook exists

Type this:

test -x /tmp/hooklab/.git/hooks/pre-commit && echo hook_ok

You will see:

hook_ok

What it means: Present.

Example 35: commits

Type this:

cd /tmp/hooklab && git rev-list --count HEAD

You will see:

3

What it means: Three clean commits.

Example 36: Sign-off

Type this:

echo 'Neha: PASS'

You will see:

Neha: PASS

What it means: Done.

Check yourself

Q1. Who added the Capgemini hook?

Neha

Q2. Hook file name?

pre-commit

Q3. AWS key prefix often seen?

AKIA

Q4. Flag that skips hooks?

--no-verify

Q5. Exit code that blocks?

1

Q6. Where do hooks live?

.git/hooks

Friends, you blocked secrets and rough shell scripts before they entered history. Did you understand? Let us try it once more. Add one more pattern for Slack tokens and prove it blocks.

Lab: try at home

  1. Init the practice repo.
  2. Write the pre-commit hook.
  3. Prove a secret is blocked.
  4. Prove a clean commit passes.
  5. Document the team rule.

Recap

  • Hooks live under .git/hooks.
  • pre-commit runs before the commit object.
  • Exit code 1 blocks the commit.
  • Never put real secrets in examples.
  • --no-verify is last resort only.