Make the three states visible
kind: drill
Create a repository, add a file, and run git status after every single step:
after creating the file, after git add, after git commit, after editing the
file again.
Solution
Untracked → staged ("Changes to be committed") → clean → modified but not staged.
The fourth state is the one that surprises people: the file is committed and
changed, so the repository and your disk disagree. git diff shows exactly that
disagreement.
Recover a deleted file from the history
kind: drill
Commit a file, delete it in the working tree, then restore it from the last commit without retyping it.
Solution
git restore report.adoc # or: git checkout -- report.adoc
Works because the commit holds the whole state, not just a diff. If the deletion
was already committed, git restore --source=HEAD~1 report.adoc reaches one
commit further back.
Rewrite five bad commit messages in Conventional Commits form
kind: drill
Rewrite: update, asdf, fixed it, changes to the file, work. Assume
they belonged to: a CSV export you added, a crash on an empty member list, a
renamed field, an updated dependency, and a corrected README. Give each one a
type and, where it helps, a scope.
Solution
feat(export): write attendance to CSV
fix(members): stop the crash on an empty list
refactor(booking): rename date to startsAt
chore(deps): update asciidoctor to 1.83
docs(readme): correct the setup command
There is no single right wording, but each line must answer "what changes for
the reader", and its type must be the one an outsider would pick. Two checks
worth doing: refactor may not change behaviour — if it does, it is a feat
or a fix; and a commit whose type you cannot decide is usually too large. In
the team project the task id belongs in each message as well, as the project
guidelines require.
Read a history by type
kind: drill
In a repository with a few dozen commits, answer with git log alone: which
features were added, which bugs were fixed, and what was pure housekeeping.
Solution
git log --oneline | grep -E '^[0-9a-f]+ feat'
git log --oneline | grep -E '^[0-9a-f]+ fix'
git log --oneline | grep -E '^[0-9a-f]+ (chore|style|ci|build)'
This is the payoff of the convention: the question is answered from the history
itself, without asking anyone. In a repository whose messages read update,
work, asdf, the same question needs a meeting. Convention over reporting is
the whole idea.
Sort the commands by where they act
kind: drill
Sort into "works offline" and "needs the network":
git add, git commit, git clone, git diff, git fetch, git log,
git push, git status. Then say for each network command which two places in
the picture it connects.
Solution
Offline: add, commit, diff, log, status — they only touch the working
tree, the index and .git. Network: clone (remote → a new local repository
plus working tree), fetch (remote → local repository, your files untouched),
push (local repository → remote). The full history lies on both sides, which
is why almost everything works without a server.
Publish your practice repository on GitHub
kind: drill
Until now your repository exists on one disk. Create an empty repository in your
GitHub account, connect it as origin, push main, and check in the browser
that the commits and their messages are there. Then clone the repository into a
second directory and compare git log on both sides.
Solution
gh repo create syp-practice --private --source=. --remote=origin --push
# without gh, after creating the empty repository in the web interface:
git remote add origin git@github.com:<account>/syp-practice.git
git push -u origin main
git remote -v
git clone git@github.com:<account>/syp-practice.git ~/tmp/copy
-u records origin/main as the upstream branch, so later git push and
git pull work without arguments. The clone carries the same commits with the
same hashes — the history is copied, not summarised. Permission denied
(publickey) means the SSH key created by setup-tools.sh is not registered in
your GitHub account; add it under Settings → SSH and GPG keys and push again.
Set up your project repository
kind: project
Create the repository for your team project from the template, add a
.gitignore that fits your stack, and make the first commit.