Checkpoint Lab — Hooks, Aliases, Templates, Attributes, and Local Automation
Checkpoint local Git automation by proving what tracked scripts, attributes, aliases, hook activation, local metadata, templates, and server policies do and do not carry into a second repository context.
Learning objectives
- Predict which customizations travel through clone and verify each prediction.
- Activate a reviewed tracked hook in a second context and diagnose a broken hooksPath.
- Break and repair an attribute path rule using git check-attr evidence.
- Contrast optional local feedback with an authoritative local receive hook.
- Write a policy assigning checks to local development, CI, and server/hosting enforcement.
1. Checkpoint scenario — prove what travels and what enforces policy
You are preparing a small internal repository standard. The source
repository will contain one tracked hook script, one tracked
.gitattributes policy, and one tracked
.gitignore. It will also have one local Git alias and
local core.hooksPath activation. Separately, an init
template contains a harmless metadata notice. You will clone to a
second context and prove which pieces travel automatically.
2. Predictions before setup
-
Will the tracked
.githooks/commit-msgfile appear in a normal clone? -
Will the source repository's local
core.hooksPathsetting appear in the clone? -
Will tracked
.gitattributesrules apply in the clone? -
Will a file copied by a separate init template into one
repository's
.gitmetadata appear in an unrelated clone?
3. Create the isolated source repository
Git Bash, Bash, or zsh
mkdir git-policy-checkpoint
cd git-policy-checkpoint
git init -b trunk source
cd source
git config user.name "Policy Checkpoint"
git config user.email "policy-checkpoint@example.invalid"
mkdir -p .githooks docs scripts assets
cat > .githooks/commit-msg <<'EOF'
#!/bin/sh
msgfile=$1
gitdir=$(git rev-parse --git-dir)
printf 'commit-msg arg=%s\n' "$msgfile" >> "$gitdir/policy-hook.log"
case "$(sed -n '1p' "$msgfile")" in
"POLICY: "*) exit 0 ;;
*)
echo "policy hook: subject must start with POLICY: " >&2
exit 1
;;
esac
EOF
chmod +x .githooks/commit-msg
cat > .gitattributes <<'EOF'
* text=auto
*.sh text eol=lf
*.png binary
docs/** export-ignore
EOF
printf "*.log\n" > .gitignore
printf "# Policy Demo\n" > README.md
printf "# Public guide\n" > docs/guide.md
printf "# Internal guide\n" > docs/internal.md
printf "echo build\n" > scripts/build.sh
printf "fake image\n" > assets/logo.png
git config --local core.hooksPath .githooks
git config --local alias.st 'status --short --branch'
git add .
git commit -m "POLICY: establish repository automation"
SOURCE_TIP=$(git rev-parse HEAD)
PowerShell setup alternative
Use the same repository content with Set-Content and
create the hook file from a here-string. In Git for Windows, verify
that the hook interpreter/execution model actually invokes the
script; do not assume POSIX permission bits behave identically on
every filesystem.
4. Add a local-only attribute override and prove it is not history
printf "local-only.dat custom=source-only\n" > .git/info/attributes
git check-attr custom -- local-only.dat
git status --short
The result should report custom: source-only, but
status remains clean because .git/info/attributes is
repository metadata rather than tracked content.
5. Create one init-template file and initialize a separate repository
cd ..
mkdir template-seed
printf "policy-template-version=1\n" > template-seed/policy-notice.txt
git init --template=template-seed -b trunk seeded
cat seeded/.git/policy-notice.txt
This proves template seeding separately from cloning. The notice
belongs to seeded/.git; it is not source repository
history.
6. Preflight the source customizations
git -C source config --show-origin --get core.hooksPath
git -C source config --get-regexp '^alias\.'
git -C source check-attr --all -- scripts/build.sh
git -C source check-attr --all -- assets/logo.png
git -C source check-attr export-ignore -- docs/internal.md
git -C source check-ignore -v -- debug.log || true
test -f source/.githooks/commit-msg
test -f source/.git/policy-hook.log
The hook log should exist because the initial POLICY commit triggered it. It is local metadata and will become an important comparison point.
7. Clone to a second context and compare distribution
git clone source clone
git -C clone config user.name "Clone Learner"
git -C clone config user.email "clone-learner@example.invalid"
test -f clone/.githooks/commit-msg && echo "tracked hook script traveled"
test -f clone/.gitattributes && echo "attributes traveled"
test -f clone/.gitignore && echo "ignore policy traveled"
git -C clone config --get core.hooksPath || echo "core.hooksPath did not travel"
git -C clone config --get-regexp '^alias\.' || echo "local aliases did not travel"
test ! -f clone/.git/policy-hook.log && echo "source hook log did not travel"
test ! -f clone/.git/policy-notice.txt && echo "separate template notice did not travel"
Verify predictions 1–4: tracked files travel; source local config/metadata and an unrelated template seed do not.
8. Verify tracked attributes are active in the clone immediately
git -C clone check-attr text eol -- scripts/build.sh
git -C clone check-attr text diff merge -- assets/logo.png
git -C clone check-attr export-ignore -- docs/internal.md
git -C clone check-attr custom -- local-only.dat
The shared attributes resolve from tracked history. The
custom=source-only rule should be unspecified because
the source's .git/info/attributes did not clone.
9. Prove the tracked hook is not active until configured
cd clone
printf "clone context\n" > clone-note.txt
git add clone-note.txt
git commit -m "plain subject succeeds before hook activation"
git log -1 --oneline
test ! -f .git/policy-hook.log && echo "hook did not run"
The tracked script exists, but the clone has no
core.hooksPath=.githooks setting. This is direct
evidence that distribution and activation are separate.
10. Activate the reviewed hook in the clone
git config --local core.hooksPath .githooks
git config --show-origin --get core.hooksPath
printf "activation test\n" > activation.txt
git add activation.txt
git commit -m "invalid subject"
echo "invalid commit exit=$?"
git status --short
git commit -m "POLICY: verify activated hook"
cat .git/policy-hook.log
The invalid commit should fail and leave the staged file intact; the valid POLICY commit should succeed.
11. Break the hook path deliberately and diagnose false confidence
git config --local core.hooksPath .missing-hooks
git config --path --get core.hooksPath
test ! -d .missing-hooks && echo "configured hook directory is missing"
printf "broken path demo\n" > broken-path.txt
git add broken-path.txt
git commit -m "plain subject succeeds because configured hook is missing"
This commit succeeding is the failure: policy appeared configured but no hook program existed at the selected location. Diagnose and repair:
git config --local core.hooksPath .githooks
git config --path --get core.hooksPath
test -x .githooks/commit-msg && echo "hook candidate exists and is executable"
12. Break one attribute path rule and repair it from evidence
cp .gitattributes .gitattributes.good
sed 's#docs/\*\* export-ignore#docs/ export-ignore#' .gitattributes.good > .gitattributes
git check-attr export-ignore -- docs/internal.md
git diff -- .gitattributes
The attribute becomes unspecified because a
directory-only pattern does not recurse in gitattributes. Restore
the correct recursive pattern:
mv .gitattributes.good .gitattributes
git check-attr export-ignore -- docs/internal.md
git add .gitattributes
git status --short
13. Add an authoritative local receive boundary
cd ..
git init --bare central.git
cat > central.git/hooks/pre-receive <<'EOF'
#!/bin/sh
while read old_oid new_oid ref_name
do
case "$ref_name" in
refs/heads/trunk)
echo "server policy: direct trunk updates are blocked in this demo" >&2
exit 1
;;
esac
done
exit 0
EOF
chmod +x central.git/hooks/pre-receive
git -C clone remote add central ../central.git
git -C clone push central HEAD:refs/heads/review/demo
git -C clone push central HEAD:refs/heads/trunk
echo "trunk push exit=$?"
The review branch push should succeed and the trunk push should fail. This demonstrates the boundary between optional/bypassable local feedback and authoritative receive policy.
14. Write the local/CI/server responsibility policy
| Rule | Local | CI | Server/hosting |
|---|---|---|---|
| Commit message starts with project prefix | commit-msg fast feedback | Validate submitted range | Enforce if organizationally mandatory |
| Shell scripts use LF | Tracked .gitattributes | Verify checkout/build | No special receive hook normally needed |
| Tests pass | Optional fast subset | Mandatory full suite | Allow trunk update only after required result |
| Protected trunk update | Cannot authoritatively enforce | Produces approval signal | Mandatory gate |
| Custom diff/merge tools | Explicit trusted install | Controlled runner image | Not a client trust substitute |
15. Verification checklist
-
Source hook script is tracked and source
core.hooksPathis local config. - Source alias is local config and does not appear in clone.
-
Tracked
.gitattributes,.gitignore, and.githooksfiles appear in clone. -
Source
.git/info/attributesand hook-observation log do not appear in clone. - The separate init-template notice exists only in the repository seeded with that template.
-
The clone's tracked hook is inactive until
core.hooksPathis set. - After activation, an invalid message is rejected and staged work remains.
- A deliberately missing hooksPath lets a plain commit through, proving false-confidence risk.
-
docs/ export-ignorefails recursively;docs/** export-ignoresucceeds. - The local server allows a review branch but rejects direct trunk updates.
16. Cleanup
Git Bash / Bash / zsh
cd ../..
pwd
rm -rf git-policy-checkpoint
PowerShell
Set-Location ../..
Get-Location
Remove-Item -Recurse -Force git-policy-checkpoint
17. Knowledge check
Question 1. Why did the .githooks file travel while core.hooksPath did not?
Question 2. What proved that the source's local attribute override did not travel?
Question 3. A plain commit succeeds after hooksPath is changed to .missing-hooks. What failed?
Question 4. Why did the server reject trunk even though the client created the commit successfully?
Question 5. Which chapter principle should guide automation placement?
18. What Chapter 17 adds to a production Git operating model
You can now distinguish executable local automation from versioned repository policy, seed repositories without confusing templates with ongoing management, diagnose attribute/ignore behavior from Git's effective view, and design layered enforcement that remains understandable across Windows, Linux, macOS, CI, and remote servers.
19. Chapter checkpoint summary
The operational rule is straightforward: know what travels, what executes, and what can enforce. Tracked files are reviewable but not automatically active; local configuration is powerful but non-portable; templates are init-time seeds; server policy is centralized; custom drivers and hooks are code and deserve a trust review.
Authoritative references
githooks
git-config
git-init
gitattributes
git-check-attr
git-check-ignore
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.