Git: tags, releases & finding the bad commit
“It worked in the last release.” That sentence starts a lot of investigations. This lesson gives you both halves: tags to mark exactly what each release was, and the detective tools to find which commit broke something: log searches, blame, and bisect, which finds the bad commit for you by halving the history again and again.
You will learn
- Tag releases (lightweight and annotated) and pick version numbers
- Look at an old release, and what “detached HEAD” means
- Search history with
log -S,--grep,--authorandblame - Find the commit that broke something with
git bisect, by hand and automatically - Publish a release with
git pushandgh release
Tags: a name for a commit
A branch moves every time you commit. A tag stays put. It's a permanent label like v1.1 on one exact commit, so “what did we ship in 1.1?” always has an answer.
git tag # list tags git tag -a v1.2 -m "Contact link is back" # annotated tag on the current commit git tag -a v1.0 -m "First release" 3f9a1c2 # …or on an older commit git show v1.2 # who tagged it, when, why, and the commit git describe # v1.2, or v1.1-4-g8d2e1f0 = 4 commits after v1.1 git push origin v1.2 # tags are NOT pushed by a plain git push
Annotated tags (-a) store who made them, when, and a message, so use them for releases. A lightweight tag (git tag NAME) is just a bookmark. Most tools, including git describe, only look at annotated tags by default.
Version numbers
Most projects use semantic versioning, MAJOR.MINOR.PATCH:
- PATCH (1.1.0 → 1.1.1): bug fixes only
- MINOR (1.1 → 1.2): new features, and everything that worked still works
- MAJOR (1.x → 2.0): something changed in a way that can break people who use it
Looking at an old release
You can switch to any tag or commit to see the files exactly as they were:
git switch --detach v1.0 # or the classic: git checkout v1.0 git switch - # back to the branch you came from
Git calls this detached HEAD: you're on a commit, not on a branch. Looking around is perfectly safe. If you commit there, though, no branch points at the new commits, so they're easy to lose. Make a branch first if you want to keep work: git switch -c fix-1.0 v1.0.
Detective tools
| Question | Command |
|---|---|
| Which commits added or removed this text? | git log -S "contact.html" --oneline |
| Which commits mention this word in their message? | git log --grep=nav --oneline |
| What did this person change? | git log --author=Sam --oneline |
| What happened to this one file? | git log --oneline -- index.html |
| Who last changed each line, and in which commit? | git blame index.html |
| What changed between two releases? | git log --oneline v1.0..v1.1 · git diff v1.0 v1.1 |
“Blame” is git's word, not a verdict. It points at a commit, so you can read why a line changed, and ask the right person.
git bisect: let git do the searching
When you can't search for the cause (a page got slow, a button stopped working), you can still test each version. bisect does a binary search: you name one bad commit and one good one, it checks out the commit halfway between, and you say “good” or “bad”. Every answer halves the suspects, so even 1,000 commits take about 10 tests.
git bisect start git bisect bad # the current commit is broken git bisect good v1.1 # this release was fine # git checks out a commit in the middle. Test it, then say: git bisect good # …or… git bisect bad # repeat until: "abc1234 is the first bad commit" git bisect reset # back to where you started
Even better, if a command can test it, git runs the whole search by itself. The command must exit 0 for good and 1 for bad, and grep -q does exactly that:
git bisect run grep -q contact.html index.html # or: git bisect run ./test.sh
Releases on GitHub
A GitHub release is a tag plus a title, notes, and optional files to download. Push the tag, then:
gh release create v1.2 --title "v1.2" --notes "The contact link is back."
gh release create v1.2 --generate-notes # notes listing every change since the last release
gh release list
Try it: the vanishing contact link 🔍
Someone noticed the Contact link is gone from the club's home page. It was definitely there in release v1.1. Find the commit that removed it, fix it, and ship v1.2.
Quick check
1. You tagged a release with git tag -a v2.0 -m "…" and ran git push. Your teammates can't see the tag. Why?
✓ Push tags by name, or with --tags / --follow-tags.
2. There are 500 commits between the last good release and today. About how many tests does git bisect need?
✓ Each test halves the suspects: 500 → 250 → 125 → … → 1.
3. You fixed a bug in v1.1.0 without adding features. What's the next version number?
✓ Bug fixes only bump the PATCH number.