These ten questions run the length of the chapter, and each turns on a Git 1,932 behavior that catches experienced developers: where commit hashes come from, ignore rules that cannot be undone, renames Git never records, parent and ancestor syntax, what a stash leaves behind, tags a push skips, what a clone leaves out, tag objects, commands that bypass hooks, and aliases Git refuses. Every snippet ran with Git 2.55.0 on this chapter's WSL2 6 Ubuntu 26.04 225 host, from BookNest's directory as GUIs and Terminal Tools left it. Read each numbered block, write down what it prints and why, and only then check Appendix H, which gives the real output, the reason and the section it comes from.
Setup
mkdir ../ty
git --versionQuestions
# 1. Unrelated repositories, one file, one message, one moment in time. (Sections 2.2.4, 2.2.5)
# Predict: how many different commit hashes do the three repositories print?
for r in q1a/00:00:00Z q1b/00:00:00Z q1c/08:00:00+08:00; do
export GIT_AUTHOR_DATE=2026-01-01T${r#*/} GIT_COMMITTER_DATE=2026-01-01T${r#*/} r=${r%/*}
git init -q ../ty/$r && echo "BookNest" > ../ty/$r/README.md && git -C ../ty/$r add .
git -C ../ty/$r commit -qm "First commit" && git -C ../ty/$r log --format="$r %h %ad"
done
unset GIT_AUTHOR_DATE GIT_COMMITTER_DATE
# 2. Ignore build/ but keep build/keep.txt, then try build/* instead. (Section 2.3.3)
# Predict: which of the two .gitignore files lets Git see build/keep.txt?
mkdir -p ../ty/q2/build && cd ../ty/q2 && git init -q && touch build/keep.txt
printf 'build/\n!build/keep.txt\n' > .gitignore && git status --short --untracked-files=all
git check-ignore -v build/keep.txt
printf 'build/*\n!build/keep.txt\n' > .gitignore && git status --short --untracked-files=all
cd ../../booknest
# 3. Rename a file and rewrite most of it in the same commit. (Sections 2.3.4, 2.3.6)
# Predict: does Git report a rename, and does --follow find a.txt's history?
git init -q ../ty/q3 && cd ../ty/q3 && seq 1 10 > a.txt && git add a.txt
git commit -qm "Add a.txt" && git mv a.txt b.txt && seq 8 17 > b.txt && git add b.txt
git status --short; git diff --staged -M20% --name-status
git commit -qm "Rename a.txt" && git log --follow --format=%s -- b.txt; cd ../../booknest# 4. e2b46bd merged the ui-search branch into main. (Sections 2.4.3, 2.4.8)
# Predict: are ^2 and ~2 the same commit? --first-parent shows the chain.
git log -1 --format='%h %s' e2b46bd^2
git log -1 --format='%h %s' e2b46bd~2
git log --first-parent --format='%h %s' -3 e2b46bd
# 5. Stash with a changed tracked file and a new file present; then stash -u. (Section 2.8.1)
# Predict: what does git status show after each stash?
cd ../ty/q3 && echo 18 >> b.txt && echo new > new.txt
git stash -q && git status --short
git stash pop -q && git stash -q -u && git status --short; git stash list; cd ../../booknest
# 6. A lightweight and an annotated tag, then push --follow-tags. (Sections 2.7.1, 2.7.3)
# Predict: which tags reach the server with --follow-tags, and which with --tags?
git init -q --bare ../ty/q6.git && cd ../ty/q3 && git tag light && git tag -a -m "1.0" v1.0
git push -q --follow-tags ../q6.git main && git ls-remote --tags ../q6.git | cut -f2
git push -q --tags ../q6.git && git ls-remote --tags ../q6.git | cut -f2
cd ../../booknest
# 7. Clone BookNest. Which of its settings and states come along? (Sections 2.11.4, 2.13.3)
# Predict: which settings are empty in the clone, and how many stashes does it have?
GIT_LFS_SKIP_SMUDGE=1 git clone -q ../server/booknest.git ../ty/q7
for key in core.hooksPath commit.gpgSign gpg.format; do
echo "$key: $(git -C ../ty/q7 config get $key)"
done
ls ../ty/q7/.git/hooks | grep -vc sample
git stash list | wc -l; git -C ../ty/q7 stash list | wc -l# 8. Is v1.2.0 the name of the commit it tags? (Sections 2.2.7, 2.7.1)
# Predict: do the two hashes match?
git rev-parse v1.2.0 'v1.2.0^{commit}' | cut -c 1-7
git cat-file -t v1.2.0 && git cat-file -p v1.2.0 | head -n 3
# 9. A commit-msg hook that rejects every message. What gets past it? (Sections 2.11.1, 2.11.3)
# Predict: which of commit, cherry-pick and revert does the hook stop?
git init -q ../ty/q9 && cd ../ty/q9 && git commit -q --allow-empty -m "Start"
git switch -qc side && echo x > x.txt && git add x.txt && git commit -qm "wip!!"
git switch -q main && printf '#!/bin/sh\necho rejected; exit 1\n' > .git/hooks/commit-msg
chmod +x .git/hooks/commit-msg
git commit -q --allow-empty -m "Try"; echo "commit: $?"
git cherry-pick side > /dev/null; echo "cherry-pick: $?"
git revert --no-edit HEAD > /dev/null; echo "revert: $?"
git log --format=%s; cd ../../booknest
# 10. Can an alias change what git log prints? (Section 2.15.2)
# Predict: one line or the full commit header? Then a new name for the same alias.
git config set --global alias.log "log --oneline"
git log -1 | head -n 1
git config unset --global alias.log
git config set --global alias.hist "log --oneline" && git hist -1
git config unset --global alias.hist