Hooks, Aliases, Templates, Attributes, and Local Automation: Concepts, Architecture, and Mental Model
Build a safe mental model for Git hooks, aliases, init templates, attributes, ignore rules, executable drivers, and the boundary between local feedback and authoritative policy.
Learning objectives
- Distinguish client-side and server-side hook execution and enforcement boundaries.
- Explain why tracked hook scripts, active hook configuration, and .git/hooks are different distribution layers.
- Separate Git aliases from shell aliases and executable shell-command aliases.
- Model init templates as one-time repository metadata seeding.
- Separate .gitattributes path behavior from .gitignore untracked-file policy.
1. Local automation is useful precisely because Git itself stays general-purpose
Chapter 16 used Git history as evidence. Chapter 17 moves from read-only investigation to controlled customization. Teams often want fast feedback before a commit, shorter command names, consistent repository initialization, and path-specific text/diff/merge behavior. Git supplies extension points for these needs, but each extension has a different distribution and trust model.
The central production question is not “how do I make Git run a script?” It is: where does this behavior live, who receives it, who can bypass it, what executable code can it invoke, and which repository layer does it change?
2. Inspect customization state before adding more
git status --short --branch
git config --list --show-origin --show-scope
git config --get core.hooksPath
git config --get init.templateDir
git config --get-regexp '^alias\.'
git check-attr --all -- README.md
git check-ignore -v -- debug.log
Some commands may produce no output when the corresponding setting or pattern is absent. That absence is evidence: it tells you Git is using defaults or that no matching rule exists. For automation incidents, capture configuration origin and scope so you know whether behavior came from system, global, local, or worktree configuration.
3. A hook is an executable program tied to a Git lifecycle event
A hook is a program Git invokes at a documented
point such as before a commit, after a commit, during a rebase, or
while a server receives pushed refs. By default Git looks in
$GIT_DIR/hooks; core.hooksPath can
redirect that lookup.
flowchart TD DEV[Developer working tree] CLIENT[Client Git] CH[Client hook] REMOTE[Authoritative bare or hosted repository] SH[Server receive hook] REFS[Remote refs] DEV -->|git commit| CLIENT CLIENT -->|pre-commit or commit-msg| CH CH -->|allow| CLIENT CLIENT -->|git push| REMOTE REMOTE -->|pre-receive or update| SH SH -->|allow| REFS
The first hook runs on the developer's machine and may be missing or bypassable depending on the hook. The server-side receive hook runs where the authoritative repository processes the push and can reject the ref update for every client. Hosted platforms may implement equivalent policy through product-specific controls rather than exposing raw hook installation.
4. Hooks communicate through arguments, standard input, environment, and exit status
Each hook has its own contract. A commit-msg hook
receives the proposed message-file path as its first argument;
non-zero exit aborts the commit and --no-verify can
bypass that hook. A pre-receive hook receives proposed
ref updates on standard input and a non-zero exit rejects the entire
receive operation.
Git also exports repository-related environment variables to hooks. A hook that calls Git in another repository must avoid accidentally carrying the current repository's environment into that foreign operation.
5. Active local hook configuration is not ordinary cloned project history
A file living only in .git/hooks is inside repository
metadata rather than the tracked working tree, so an ordinary clone
does not copy that source repository's hook as project content.
Likewise, local .git/config settings such as
core.hooksPath do not travel as commits.
A team can track hook scripts in a directory such as
.githooks/, but cloning those files does not by itself
activate them. A bootstrap step must configure
core.hooksPath, or another controlled distribution
mechanism must install hooks.
6. Local hooks improve feedback; authoritative enforcement belongs at an authoritative boundary
A developer can lack a client hook, modify it, or bypass hooks that
explicitly support --no-verify. Therefore client hooks
are excellent for convenience and fast feedback but are weak as the
only enforcement mechanism. Requirements such as protected-ref
update rules need CI and/or server-side governance.
7. A Git alias expands a git subcommand; a shell alias
belongs to the shell
git config --local alias.st 'status --short --branch'
git st
Here git st is expanded by Git. Git aliases cannot
replace an existing built-in Git command. An alias beginning with
! is different: Git invokes it as a shell command,
which adds shell quoting, runtime, path, and security concerns.
A shell alias such as alias gs='git status' is
configured by Bash/zsh (or an equivalent facility in another shell),
not Git. It will not appear in git config.
8. Prefer aliases for interactive ergonomics, not opaque production protocols
Human shorthand such as git st is harmless when the
canonical command is obvious. CI scripts and runbooks should
generally spell out the underlying Git command. An alias can depend
on local configuration, shell behavior, or hidden options that
another machine does not have.
9. An init template seeds new repository metadata at creation time
git init can copy files and directories from a
template directory into the new repository's
$GIT_DIR. The template source is selected by
--template, GIT_TEMPLATE_DIR,
init.templateDir, then Git's default template
directory.
Templates are a seeding mechanism, not continuous synchronization. Updating a template later does not automatically update repositories that were initialized earlier.
10. Git attributes assign behavior to paths; gitignore controls untracked visibility
A tracked .gitattributes file says how matching paths
should be treated by Git operations such as text normalization,
diff, merge, archive export, and filters. A tracked
.gitignore file says which intentionally untracked
paths should normally be ignored by commands such as status/add.
* text=auto
*.sh text eol=lf
*.png binary
docs/internal.md export-ignore
*.log
build/
.env.local
An ignored file is not automatically binary, and a binary attribute does not make a file ignored. They solve different problems.
11. Attribute decisions can come from tracked, repository-local, user, or system sources
Tracked .gitattributes files distribute project policy.
$GIT_DIR/info/attributes is repository-local and has
higher precedence, which makes it suitable for one user's local
overrides that should not be committed.
core.attributesFile supplies per-user attributes, and a
system-wide attributes file can apply lower-precedence defaults.
git check-attr text eol diff merge export-ignore -- path/to/file
Use git check-attr to ask Git for the effective result
instead of guessing which pattern won.
12. Text attributes separate repository normalization from working-tree line endings
With text enabled, Git normalizes text to LF when
content enters the index. The eol attribute can request
LF or CRLF in the working tree. That distinction is critical on
mixed Windows/Linux/macOS teams: the committed blob can remain
normalized while working-tree presentation varies deliberately.
13. Binary classification prevents misleading textual merge/diff behavior
The built-in binary macro effectively disables text
normalization, textual diff, and normal textual merge for matching
paths. This is useful for file formats where a line-oriented patch
is meaningless.
*.png binary
*.zip binary
14. Attribute driver names and executable driver commands are separate trust layers
A tracked attribute can say *.special diff=policy or
*.lock merge=lockfile. The actual external command for
diff.policy.command or
merge.lockfile.driver lives in Git configuration. When
such a driver is configured, Git may execute that command during
diff/merge operations.
15. DevOps connection — distribute policy according to the enforcement boundary
Tracked attributes and scripts are reviewable repository content. Local aliases and hook activation are workstation configuration. Templates seed new repositories. CI evaluates shared automation in a centralized runner. Server/hosting controls enforce authoritative ref policy. Production design should choose the narrowest layer that provides both the desired feedback speed and the required enforcement strength.
16. Knowledge check
Question 1. Does cloning a repository copy the source
repository's active .git/hooks directory?
Question 2. If .githooks/commit-msg is tracked, is
it automatically active after clone?
core.hooksPath=.githooks.
Question 3. Why is a client-side commit hook insufficient as the only protected-branch policy?
Question 4. What is the difference between .gitattributes and .gitignore?
Question 5. Does changing an init template automatically update already-created repositories?
17. Summary
Hooks, aliases, templates, and attributes are four different
extension mechanisms. Hooks execute programs at lifecycle points;
aliases expand commands; templates seed new
$GIT_DIR content; attributes assign path behavior.
Their portability and enforcement properties differ, so production
Git customization starts with a distribution/trust model rather than
with scripting.
Authoritative references
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.