Bird
Raised Fist0
Gitdevops~15 mins

pre-commit hook in Git - Deep Dive

Choose your learning style10 modes available
Overview - pre-commit hook
What is it?
A pre-commit hook is a script that runs automatically before a git commit is finalized. It checks or modifies your code to catch mistakes early, like formatting errors or failing tests. This helps keep the codebase clean and consistent without manual checks. It works locally on your computer before changes are saved in the project history.
Why it matters
Without pre-commit hooks, developers might commit broken or messy code, causing bugs and extra work for the team. These hooks act like a safety net, stopping problems before they enter the shared project. This saves time, reduces errors, and keeps the project healthy and easier to maintain.
Where it fits
Before learning pre-commit hooks, you should understand basic git commands like commit and push. After mastering hooks, you can explore continuous integration (CI) pipelines that run similar checks on shared servers. Hooks are a bridge between local development and automated quality control.
Mental Model
Core Idea
A pre-commit hook is an automatic gatekeeper that checks your code before it becomes part of the project history.
Think of it like...
It's like a security guard at a building entrance who checks your ID and bags before letting you in, preventing trouble inside.
┌───────────────┐
│  Developer    │
└──────┬────────┘
       │ git commit
       ▼
┌───────────────┐
│ Pre-commit    │
│ Hook Script   │
└──────┬────────┘
       │ Pass or Fail
       ▼
┌───────────────┐
│ Commit Saved  │
└───────────────┘
Build-Up - 6 Steps
1
FoundationWhat is a Git Hook
🤔
Concept: Introduce the idea of git hooks as scripts triggered by git events.
Git hooks are scripts placed in a special folder inside a git project. They run automatically when certain git actions happen, like committing or pushing. These scripts can check code, run tests, or stop bad commits.
Result
Learners understand that git hooks automate tasks during git operations.
Knowing that git hooks automate checks helps you trust your tools to catch errors early without manual effort.
2
FoundationLocating and Enabling Pre-commit Hooks
🤔
Concept: Show where pre-commit hooks live and how to activate them.
Inside your git project folder, there is a hidden folder called .git/hooks. It contains sample scripts like pre-commit.sample. To enable a pre-commit hook, rename or create a file named pre-commit without an extension and make it executable. This script runs before every commit.
Result
Learners can find and activate pre-commit hooks in their projects.
Understanding the location and activation process empowers you to customize your own checks.
3
IntermediateWriting a Simple Pre-commit Script
🤔Before reading on: do you think a pre-commit script can stop a commit if it finds a problem? Commit to your answer.
Concept: Teach how to write a basic script that blocks commits on failure.
A pre-commit script is a shell script that runs commands. For example, you can check if any files have 'TODO' comments and stop the commit if found: #!/bin/sh if git diff --cached | grep 'TODO'; then echo 'Remove TODO comments before committing.' exit 1 fi exit 0 If the script exits with 1, git stops the commit.
Result
Commits containing 'TODO' comments are blocked until fixed.
Knowing that exit codes control commit success lets you build powerful checks that enforce rules.
4
IntermediateUsing Pre-commit Frameworks
🤔Before reading on: do you think writing all hooks manually is the best way? Commit to your answer.
Concept: Introduce tools like 'pre-commit' that simplify managing hooks across projects.
'pre-commit' is a popular tool that manages multiple hooks easily. You create a config file listing checks (like linters or formatters). Then, 'pre-commit install' sets up the hooks. It runs checks automatically and updates them with one command, avoiding manual scripts.
Result
Developers can run many checks consistently without writing scripts themselves.
Understanding frameworks saves time and ensures consistent quality across teams.
5
AdvancedSharing Hooks Across Teams
🤔Before reading on: do you think pre-commit hooks are automatically shared with teammates? Commit to your answer.
Concept: Explain how to share hooks so all team members use the same checks.
Git hooks live locally and are not shared by default. To share hooks, teams commit hook configs (like .pre-commit-config.yaml) to the repo. Each developer runs setup commands to install hooks locally. This keeps everyone’s code checked the same way.
Result
Teams maintain consistent code quality by sharing hook setups.
Knowing hooks are local by default prevents confusion and encourages shared standards.
6
ExpertPerformance and Limitations of Pre-commit Hooks
🤔Before reading on: do you think pre-commit hooks run instantly no matter what? Commit to your answer.
Concept: Discuss how hooks affect commit speed and their limits in complex workflows.
Pre-commit hooks run before every commit, so slow or heavy checks can delay developers. Large projects use caching or selective checks to improve speed. Also, hooks can't enforce rules on commits pushed from other machines; server-side checks complement them. Understanding these tradeoffs helps design efficient workflows.
Result
Learners grasp when hooks help and when other tools are needed.
Knowing hooks’ performance impact guides smarter use and integration with CI pipelines.
Under the Hood
When you run 'git commit', git looks for a pre-commit script in .git/hooks. If found and executable, git runs it synchronously. The script can run any commands and must exit with 0 to allow the commit. If it exits with non-zero, git aborts the commit. This happens before the commit message editor opens, so the commit is blocked early.
Why designed this way?
Git hooks were designed as simple scripts to allow flexible, customizable checks without changing git’s core. Using exit codes to control flow is a standard Unix pattern. This design keeps git lightweight and lets users add any logic they want.
┌───────────────┐
│ git commit    │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ .git/hooks/   │
│ pre-commit    │
└──────┬────────┘
       │ runs script
       ▼
┌───────────────┐
│ exit code?    │
│ 0 = continue  │
│ ≠0 = abort   │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ commit saved  │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do pre-commit hooks run on the remote server automatically? Commit yes or no.
Common Belief:Pre-commit hooks run on the remote repository when you push code.
Tap to reveal reality
Reality:Pre-commit hooks only run locally on your machine before committing. Remote servers do not run them automatically.
Why it matters:Assuming hooks run remotely can lead to broken code entering the shared repository if local hooks are skipped.
Quick: Can a pre-commit hook fix code automatically without blocking the commit? Commit yes or no.
Common Belief:Pre-commit hooks only check code and cannot modify it automatically.
Tap to reveal reality
Reality:Pre-commit hooks can modify files (like auto-formatters) and then allow the commit to proceed.
Why it matters:Knowing hooks can fix code helps automate style consistency and reduces manual work.
Quick: Do all git users on a team share the same hooks by default? Commit yes or no.
Common Belief:Git hooks are shared automatically with the project and all team members use the same hooks.
Tap to reveal reality
Reality:Git hooks are local and not shared by default; teams must share hook configs and install hooks manually.
Why it matters:Misunderstanding this causes inconsistent code quality and confusion about why hooks don’t run for everyone.
Quick: Does a pre-commit hook guarantee perfect code quality? Commit yes or no.
Common Belief:Using pre-commit hooks means your code is always error-free and perfect.
Tap to reveal reality
Reality:Hooks help catch common issues but cannot guarantee perfect code; manual review and testing are still needed.
Why it matters:Overreliance on hooks can lead to missed bugs and false confidence.
Expert Zone
1
Pre-commit hooks can be combined with other hooks like commit-msg or pre-push for layered quality control.
2
Hooks can be bypassed with git commit --no-verify, which can be dangerous if misused.
3
Using caching and selective file checks in hooks improves performance in large codebases.
When NOT to use
Pre-commit hooks are not suitable for enforcing rules on code pushed from other machines or CI environments; use server-side hooks or CI pipelines instead.
Production Patterns
Teams use pre-commit frameworks like 'pre-commit' to manage hooks centrally, share configs via the repo, and integrate with CI to ensure consistent quality across all environments.
Connections
Continuous Integration (CI)
Builds-on
Pre-commit hooks catch issues early locally, while CI runs similar checks on shared servers to catch problems from all contributors.
Unix Shell Scripting
Same pattern
Pre-commit hooks are scripts that use standard shell commands and exit codes, so knowing shell scripting unlocks powerful hook customization.
Quality Control in Manufacturing
Analogous process
Just like inspecting parts before assembly prevents defects downstream, pre-commit hooks inspect code before it enters the project history.
Common Pitfalls
#1Assuming pre-commit hooks run on all machines automatically.
Wrong approach:Relying on .git/hooks/pre-commit scripts without sharing setup instructions or configs.
Correct approach:Commit a shared hook config file (e.g., .pre-commit-config.yaml) and instruct team members to install hooks using a tool like 'pre-commit install'.
Root cause:Misunderstanding that git hooks are local and not shared via the repository.
#2Writing slow or heavy checks that delay every commit.
Wrong approach:#!/bin/sh pytest --full-suite exit $?
Correct approach:#!/bin/sh pytest --changed-files-only exit $?
Root cause:Not optimizing checks for speed causes developer frustration and reduced productivity.
#3Ignoring exit codes and always exiting with 0.
Wrong approach:#!/bin/sh echo 'Check done' exit 0
Correct approach:#!/bin/sh if grep -q 'FIXME' files; then echo 'Fix FIXME before commit' exit 1 fi exit 0
Root cause:Not using exit codes properly means git never blocks bad commits.
Key Takeaways
Pre-commit hooks run scripts automatically before git commits to catch errors early.
They live locally in the .git/hooks folder and must be enabled and shared properly.
Hooks use exit codes to allow or block commits, enabling powerful quality checks.
Frameworks like 'pre-commit' simplify managing and sharing hooks across teams.
Hooks improve code quality but should be combined with CI and manual review for best results.

Practice

(1/5)
1. What is the main purpose of a pre-commit hook in Git?
easy
A. To push commits to the remote repository automatically
B. To run scripts before a commit is saved to catch errors early
C. To delete files from the repository before committing
D. To automatically merge branches after a commit

Solution

  1. Step 1: Understand what pre-commit hooks do

    Pre-commit hooks run scripts before a commit is finalized to check code or enforce rules.
  2. Step 2: Identify the correct purpose

    They help catch errors early by running checks before saving changes.
  3. Final Answer:

    To run scripts before a commit is saved to catch errors early -> Option B
  4. Quick Check:

    Pre-commit hook purpose = run scripts before commit [OK]
Hint: Pre-commit hooks run before saving commits to catch issues [OK]
Common Mistakes:
  • Confusing pre-commit with post-commit hooks
  • Thinking hooks automatically push commits
  • Believing hooks delete files automatically
2. Which of the following is the correct way to make a pre-commit hook script executable on Linux?
easy
A. chmod +x .git/hooks/pre-commit
B. git enable pre-commit
C. chmod 000 .git/hooks/pre-commit
D. git hook run pre-commit

Solution

  1. Step 1: Identify how to make scripts executable

    On Linux, chmod +x sets execute permission on a file.
  2. Step 2: Apply to pre-commit hook script

    Running chmod +x .git/hooks/pre-commit makes the hook script executable so Git can run it.
  3. Final Answer:

    chmod +x .git/hooks/pre-commit -> Option A
  4. Quick Check:

    Make hook executable = chmod +x [OK]
Hint: Use chmod +x to make hook scripts executable [OK]
Common Mistakes:
  • Using git commands instead of chmod for permissions
  • Setting permissions to 000 disables execution
  • Assuming hooks run without executable permission
3. Given this pre-commit hook script content:
#!/bin/sh
if git diff --cached --name-only | grep -q '\.py$'; then
  echo 'Python files changed'
else
  echo 'No Python files changed'
fi

What will be the output if you commit a changed file named app.js?
medium
A. No Python files changed
B. Python files changed
C. Syntax error in script
D. Hook will not run

Solution

  1. Step 1: Understand the script logic

    The script checks staged files for names ending with '.py'. If found, it prints 'Python files changed'. Otherwise, it prints 'No Python files changed'.
  2. Step 2: Apply to the committed file

    The committed file is 'app.js', which does not end with '.py', so the else branch runs.
  3. Final Answer:

    No Python files changed -> Option A
  4. Quick Check:

    File extension check = no match = else output [OK]
Hint: Check file extensions in staged files to predict output [OK]
Common Mistakes:
  • Assuming any changed file triggers 'Python files changed'
  • Confusing staged vs unstaged files
  • Ignoring the file extension check
4. You wrote a pre-commit hook script but it does not run when committing. Which of these is the most likely cause?
medium
A. The script is placed outside the .git/hooks directory
B. The script is named pre-commit.sh instead of pre-commit
C. All of the above
D. The script is not executable

Solution

  1. Step 1: Check script permissions

    If the script is not executable, Git cannot run it.
  2. Step 2: Check script name and location

    The script must be named exactly 'pre-commit' and placed inside the '.git/hooks' folder to be recognized.
  3. Step 3: Combine all issues

    Any of these problems will prevent the hook from running, so all are valid causes.
  4. Final Answer:

    All of the above -> Option C
  5. Quick Check:

    Hook runs only if name, location, and permissions are correct [OK]
Hint: Check name, location, and execute permission for hooks [OK]
Common Mistakes:
  • Ignoring file permissions
  • Naming script with extensions like .sh
  • Placing script outside .git/hooks folder
5. You want a pre-commit hook that prevents commits if any staged file contains the word 'TODO'. Which script snippet correctly implements this?
hard
A. #!/bin/sh git commit -m 'Check TODOs' || exit 1
B. #!/bin/sh grep -r 'TODO' . && echo 'TODO found' && exit 1
C. #!/bin/sh git status | grep 'TODO' && exit 1
D. #!/bin/sh git diff --cached | grep -q 'TODO' && echo 'Remove TODOs before commit' && exit 1

Solution

  1. Step 1: Understand the goal

    The hook must check staged changes for the word 'TODO' and stop commit if found.
  2. Step 2: Analyze each option

    #!/bin/sh git diff --cached | grep -q 'TODO' && echo 'Remove TODOs before commit' && exit 1 uses git diff --cached to check staged changes and exits with error if 'TODO' is found, which is correct.
    #!/bin/sh grep -r 'TODO' . && echo 'TODO found' && exit 1 searches all files recursively, not just staged changes.
    #!/bin/sh git commit -m 'Check TODOs' || exit 1 tries to run a commit inside the hook, which is incorrect.
    #!/bin/sh git status | grep 'TODO' && exit 1 checks git status output, which does not show file contents.
  3. Final Answer:

    #!/bin/sh git diff --cached | grep -q 'TODO' && echo 'Remove TODOs before commit' && exit 1 -> Option D
  4. Quick Check:

    Check staged diff for TODO and exit if found [OK]
Hint: Use git diff --cached to scan staged changes for keywords [OK]
Common Mistakes:
  • Searching unstaged files instead of staged
  • Running git commit inside hook
  • Checking git status output for content
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard