Chapter 17Lesson 04~125 minutes

Hooks, Aliases, Templates, Attributes, and Local Automation: Diagnostics, Failure Modes, Security, and Performance

Diagnose non-executable or misplaced hooks, non-cloned activation, confusing aliases, attribute-pattern/precedence errors, EOL normalization noise, and untrusted executable Git customization.

DiagnosticsHook failuresAttribute precedenceSecurity

Learning objectives

  • Capture config origin/scope and effective path behavior before changing the repository.
  • Diagnose hook executability, runtime, and core.hooksPath failures.
  • Recognize why local automation works in one clone but not another.
  • Repair non-recursive gitattributes patterns and local-precedence surprises.
  • Analyze normalization, external-driver trust, and hook latency only where causally relevant.

1. Diagnostic sequence for local automation failures

  1. Preserve evidence: exact Git command/output, version, platform/shell, ref, working-tree/index status, config origin/scope, and relevant hook/attribute files.
  2. Inspect before changing: hook path/executability, alias definitions, attributes, ignore patterns, and line-ending state.
  3. Identify the layer: tracked content, local config, filesystem/runtime, template seed, CI/server policy, or external driver.
  4. Choose the least destructive correction.
  5. Verify with a deliberately triggering operation.

2. Capture a customization evidence bundle

git --version
git status --short --branch
git config --list --show-origin --show-scope
git config --get core.hooksPath
git config --get-regexp '^alias\.'
git check-attr --all -- path/to/file
git check-ignore -v -- path/to/untracked-file
git ls-files --eol -- path/to/text-file

3. Intentionally broken example — hook file exists but is not executable

On a POSIX filesystem, create a hook and remove executable permission:

printf '#!/bin/sh\necho ran >> .git/hook.log\n' > .git/hooks/pre-commit
chmod -x .git/hooks/pre-commit

git status --short
git commit -m "DEMO: test non-executable hook"

Current Git's hook contract says non-executable hooks are ignored. Depending on version/configuration, Git may emit advice. Diagnose by inspecting the file and permissions rather than assuming the hook ran.

Repair in the disposable lab

chmod +x .git/hooks/pre-commit
git commit --allow-empty -m "DEMO: verify executable hook"
cat .git/hook.log

Windows filesystems do not expose POSIX execute permission identically; verify the Git-for-Windows/runtime behavior actually used by your team.

4. Failure mode — core.hooksPath points somewhere else

git config --show-origin --get core.hooksPath
git config --path --get core.hooksPath
ls -la .githooks
ls -la .missing-hooks 2>/dev/null || true

If Git is configured for .missing-hooks, a correct script in .githooks is irrelevant. Repair the configuration, then trigger the hook with a harmless empty/staged commit in the disposable repository.

5. Failure mode — hook works in source but not in a fresh clone

This is often expected architecture, not corruption. Ask what actually traveled:

git config --get core.hooksPath
git config --get-regexp '^alias\.'
test -f .githooks/commit-msg && echo "tracked script exists"
test -f .git/hooks/commit-msg && echo "default active hook exists"

A tracked hook script may exist while activation config does not. Source repository .git/hooks and local aliases/config do not become ordinary clone content.

6. Failure mode — alias obscures canonical behavior

Git aliases cannot replace existing Git commands, so trying to redefine status is ignored for git status. But custom aliases can still hide complex options or shell code.

git config --local alias.audit 'log --all --since=1.week --oneline'
git config --get-regexp '^alias\.'
git audit

Before copying git audit into a runbook, expand it and ask which refs/time filters it selects. Avoid recursive shell aliases such as alias.loop=!git loop; do not run such a definition because it can recurse indefinitely.

7. Intentionally broken attribute pattern — directory syntax does not recurse

docs/ export-ignore
git check-attr export-ignore -- docs/internal.md

The result is unspecified because docs/ does not recursively match files in a gitattributes file. Repair it:

docs/** export-ignore
git check-attr export-ignore -- docs/internal.md

Now the attribute should be set.

8. Failure mode — a local attribute override wins over the tracked file

git check-attr text -- important.dat
cat .gitattributes
cat .git/info/attributes 2>/dev/null || true
git config --show-origin --get core.attributesFile

If .git/info/attributes sets -text, it can override tracked project policy for that repository. This is why check-attr is more reliable than reading only the root file.

9. Failure mode — line-ending normalization creates a large apparent diff

A team adds text normalization to a repository whose tracked text was historically inconsistent. The safe diagnostic sequence is:

git status --short
git ls-files --eol
git diff --stat

# In a disposable lab or controlled normalization branch:
git add --renormalize .
git diff --cached --stat
git diff --cached --check

The staged changes may be normalization rather than semantic edits. Do not mix a repository-wide normalization commit with feature work. Review the staged patch and binary classifications before committing.

10. Security failure — executing customization from an untrusted repository context

An ordinary clone does not import the source's local .git/config or active .git/hooks. However, an existing working directory received from elsewhere, an organization template, bootstrap script, or local tooling can install executable hooks/config. Custom diff/merge drivers can also execute configured programs when their attributes are encountered.

Review executable configuration before trusting it. Inspect git config --show-origin --show-scope, core.hooksPath, hook files, and external driver definitions. Do not run unknown hooks/drivers merely to “see what they do.”

11. Security/diagnostic detail — hooks inherit Git repository environment

Git exports repository-related variables to hooks. If a hook invokes Git in a different repository, those variables can accidentally make the nested command operate on the wrong repository. Current hook documentation recommends clearing local Git environment variables for foreign-repository operations.

git rev-parse --local-env-vars

Production hook authors should explicitly manage environment boundaries rather than assuming git -C ../other always defeats inherited repository variables.

12. Performance relevance — hooks and drivers sit on hot developer paths

A pre-commit hook that starts containers or scans the whole monorepo can turn every commit into a long wait, encouraging bypasses. External diff/textconv tools can make routine review commands expensive. Measure latency, cache safe intermediate results, scope checks to staged/changed paths where correctness permits, and keep comprehensive validation in CI.

13. Failure mode — local success mistaken for authoritative acceptance

A local commit hook succeeding says nothing about whether the remote will accept the push. Server-side receive policy, branch protection, or CI gates may still reject it. Conversely, local hook absence does not mean the server lacks enforcement.

git push --dry-run origin trunk
git remote -v

A dry run can check some client/server negotiation, but product-specific branch protection and CI policy remain hosting/server concerns.

14. No history rewrite is needed to diagnose customization failures

Do not reset hard, clean untracked files, rewrite commits, force-push refs, expire reflogs, or prune objects to fix a missing hook or attribute mismatch. Preserve repository history and correct the configuration/pattern/runtime layer.

15. Symptom → layer → least-destructive correction

Symptom Likely layer Correction
Hook file exists but never runs Executable bit/runtime/hooksPath Inspect path + permissions + interpreter
Fresh clone lacks local behavior Config/metadata not distributed Bootstrap tracked scripts; centralize mandatory policy
Attribute is unspecified Pattern/precedence check-attr, fix docs/**-style scope
Huge staged EOL diff Normalization policy Separate/inspect renormalization change
Diff/merge runs unexpected program External driver config Inspect config origin and disable/review untrusted driver

16. Knowledge check

Question 1. Why can an existing hook file still be ignored?

Question 2. Why does docs/ export-ignore fail to cover docs/internal.md?

Question 3. What should you inspect when tracked attributes and observed behavior disagree?

Question 4. Why should normalization be separated from feature work?

Question 5. Why can an external diff or merge driver be a security risk?

17. Summary

Customization failures are usually path, scope, runtime, precedence, or trust-boundary problems. Inspect configuration origin, hook executability, tracked versus local distribution, attribute results, and EOL state. These problems are fixed by correcting configuration and policy—not by rewriting repository history.

Next

Checkpoint which customizations actually travel to a second context

Lesson 5 builds one policy repository, clones it, tests what arrived, deliberately breaks hook activation and an attribute rule, then writes a local/CI/server responsibility policy.

Authoritative references

 githooks
 git-config
 gitattributes
 git-check-attr

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.