Git · Lesson 6 · 35 min

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, --author and blame
  • Find the commit that broke something with git bisect, by hand and automatically
  • Publish a release with git push and gh 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.

Same on both
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:

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

QuestionCommand
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.

Same on both
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

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?

2. There are 500 commits between the last good release and today. About how many tests does git bisect need?

3. You fixed a bug in v1.1.0 without adding features. What's the next version number?

Finished the missions and the quiz? Mark it done to track your progress.