Session 14: Git Best Practices: Write commits you'll still understand later
You can type Git commands. Your code is on GitHub. But there’s a difference between “using Git” and “using Git well.”
This session is about the habits experienced developers apply every day. No new commands, just sharper rules. At the end you write commit messages you’ll still get something out of a year from now, and you work with a branching strategy that keeps your project tidy.
What you’ll learn today
- How to write a commit message that says something
- Three simple rules for branching
- What
git stashis and when to use it - The pull-before-you-push rule
Part 1: Commit messages that say something
A bad commit message looks like this:
git commit -m "fix"
git commit -m "update"
git commit -m "changed stuff"Three months from now you look back. What was “fix”? Which “things”? You don’t know any more. You have to dig through the code to work out what happened. That’s a waste of time.
The good commit message: 3 parts
A professional commit message has three parts:
1. A short summary (max 72 characters)
Write in English. Start with a verb in the present tense. This is called “imperative mood”: as if you’re giving an order to the codebase. Think: “Add”, “Fix”, “Remove”, “Update”, “Refactor”.
Add highscore tracking
Fix star spawning off-screen
Remove unused collision code2. A blank line
3. A longer explanation (optional, if it’s needed)
Add highscore tracking
Saves the highest score in highscore.txt. The score is
updated after every game-over. The file is created if it
doesn't exist yet.
This replaces the old method where the score only lived in
memory and got lost when the game closed.The longer explanation tells why you changed something, not just what. The code itself already shows the “what”. The “why” is what you need in three months.
Commit message rules at a glance
| Do this | Not this |
|---|---|
| “Add player health bar” | “added health bar thing” |
| “Fix collision detection on left wall” | “fix” |
| “Remove debug print statements” | “cleanup” |
| Max 72 characters for the title | A whole story in the title |
| Present tense, English | Past tense (“added”, “fixed”) |
Why English? Because nearly every open source project uses English. Code is international. You write your Python code in English too (def calculate_score). Your commit messages follow that same language.
Why present tense? A commit describes what this change does, not what you did. “Add feature” (this commit adds a feature), not “Added feature” (I added a feature once). Git itself uses present tense too: Merge branch 'feature', not Merged.
Multi-line commits in the terminal
You can write a commit message over several lines by not closing the quotes:
git commit -m "Add highscore tracking
Saves the highest score in highscore.txt. The file is
created automatically on the first game-over."Note: you only type the closing quote on the last line. Everything in between is part of your message.
When do you commit?
Commit often. Commit small.
Not: working for three hours, one enormous commit with 47 changed files. Yes: a commit every 15 to 30 minutes, each time one logical piece is done.
A rule of thumb: if your commit message contains “and”, your commit is too big. “Add highscore tracking and fix menu bug and update sprites” → those should be three separate commits.
Small commits make it easier to:
- Understand what changed and when
- Undo one specific change without breaking other things
- Solve merge conflicts (small chunks = fewer conflicts)
Part 2: Branching: three simple rules
You already know how to make branches (session 12). Now: when and why.
Rule 1: master always works
The master branch is your shop window. Someone who clones your repo has to be able to run your code without error messages. master never contains half-finished work.
Not OK on master: code with # TODO: still needs finishing, commented-out functions, experiments you’ll “fix later.”
Fine on master: working code. Full stop.
Rule 2: One feature, one branch
A branch does exactly one thing. No more.
- Good:
feature/player-health-bar - Bad:
feature/health-bar-and-menu-and-sound-effects
If, while working on a feature, you think: “Oh, I can quickly fix that menu bug too”: stop. Make a new branch for the bugfix. Merge that one first. Then carry on with your feature.
Rule 3: Branches have a short life
A branch that exists for more than a few days becomes a problem. master changes in the meantime, and your branch falls behind. The longer you wait to merge, the bigger the chance of merge conflicts.
Merge your branch as soon as the feature is done. For small things (a 10-minute bugfix): you might not even need a separate branch.
Branch naming
Give branches names you’ll still understand a week from now:
feature/highscore-tracking
bugfix/star-spawn-offscreen
experiment/particle-effectsThe prefix (feature/, bugfix/, experiment/) immediately tells you what kind of work is in this branch. It’s a convention, not a technical requirement, but it helps.
Part 3: Handy workflow commands
git stash: putting work aside
Say: you’re working on a feature branch. Your code is half done. You want to switch to master for a quick bugfix, but you don’t want to commit your half-finished work. That’s what git stash is for:
git stashGit stores all your changes temporarily and puts your working directory back to the last commit. Now you can switch, do the bugfix, commit, and come back:
git switch master
# ... do the bugfix, commit ...
git switch feature-branch
git stash popgit stash pop brings your stored changes back. Everything is as you left it: half done, but safely kept.
git pull --rebase: a cleaner history
Normally git pull does a merge. That creates an extra merge commit. Sometimes you don’t want that; you want a straight line of commits without branches.
git pull --rebaseThis fetches the newest commits and puts your local commits on top of them, as if you made them after the remote commits. The result is a linear history: no merge commits that only say “Merge branch ‘master’”.
Note: only use --rebase on branches that you alone use. On shared branches a plain git pull (merge) is safer.
The pull-before-you-push rule
Before you git push:
git pullAlways. Even if you think nobody else pushed. It takes one second and stops GitHub from refusing your push with “Updates were rejected because the remote contains work that you do not have locally.”
This rule matters most when you work together. If you’re the only one working on a repo, the risk is smaller, but the habit is worth gold.
Part 4: The .gitignore you always need
Every project has files that don’t belong in Git. Your .gitignore is your first line of defence against accidentally committing passwords.
Minimal .gitignore for a Python project:
# Python
__pycache__/
*.pyc
*.pyo
# Virtual environment
venv/
.venv/
# Environment variables (often contain passwords/keys)
.env
# Your editor
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.dbWhy ignore __pycache__/? These are compiled Python files that your program creates automatically. They differ per Python version and per computer. Putting them in Git only adds noise.
Why ignore .env? .env files often contain secret keys, API keys, database passwords. Those must never, ever go into Git.
Showcase
Show a coach and a buddy:
- Your last 5 commits, with good commit messages.
- Your
.gitignorefile. - A branch name that follows the feature/ prefix convention.
See you next time!
“Now you work with Git like a professional. But there’s one more concept that every team uses: the pull request. Your code is ready, but before it goes into master, someone else has to approve it. How does that work? Next time: pull requests, the review wall that every change has to pass through.”
Take it home
- Easy: Rewrite the commit messages of your last 5 commits. Use the rules from this session.
- Medium: Create a branch with the
feature/prefix, work in it, merge it back, and delete it. Do the same for abugfix/branch. - Hard: Use
git stashto save half-finished work, switch tomaster, make a quick fix, push, and come back to your feature withgit stash pop. - Very hard: Create a situation where
git pullfails (clone your repo in two folders, make a different commit in both, push the first one, and try to push the second). Solve it:git pull, fix the merge conflict, and only then push.