Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
How to Git

Note: this is an extract from Heyday's internal docs, written by me. Published as a Gist to share the love.

Authoring commits

We like sensible commit messages. There're a lot of good articles about writing great, useful commit messages, but here's the gist of what we like:

  • The single most important thing is: commit messages should explain why you are making the change.
  • Think, "what would future me want to know about this change?"
  • Avoid committing multiple sets of ideas/changes in the same commit: split them up.
  • Don't assume the reader understands what the original problem was.
  • Don't assume the code is self-evident/self-documenting

Practical benefits of writing "good" commit messages

The main reason to fill your commit history with useful information is so that you, other developers, and future you can understand the context and reasoning behind changes to code, without talking to the original developer (who might be long gone, or has at least forgotten the reason their code is the way it is). Git provides a lot of tools for working with the history, which are useful once you get to know them - you can make use of all these awesome commit messages everyone has been writing. Also consider:

The body of commit messages can document all of the things that probably don't belong in code comments.

Relevant quotes from emails, error messages, ticket numbers, links to discussions about issues, relevant articles, specific reasons for choosing a solution, thoughts about alternative solutions.

Explaining why a change was made means you need to think about what you've done.

Is this the best solution? Have I missed something? If it's a hack, then why is it ok? Can it be avoided? Can the problem be solved in a better way? If you've done something hacky and can't justify it, should you really be doing that?

A "good" commit message according to the creator of Git

Header line: explain the commit in one line

Body of commit message is a few lines of text, explaining things
in more detail, possibly giving some background about the issue
being fixed, etc etc.

Make sure you explain your solution and why you're doing what you're
doing, as opposed to describing what you're doing. Reviewers and your
future self can read the patch, but might not understand why a
particular solution was implemented.

Fixes BUG-123

That header line really should be meaningful, and really should be just one line. The header line should summarise the change in one readable line of text, independently of the longer explanation.

Further reading

If you have time and really want to be awesome, here's some more information about what makes good (and bad) commit messages:

Working with the history

Git has a lot of powerful tools for digging through the history of projects. While these are not all everyday tools, being aware of and including them in your workflow can be very useful when you do need to dig through the history of a project.

Most editors have the capability to quickly access information from a project's history, either by a built-in function or through a plugin. If you're using Sublime Text, sublime-text-git is a good solution that allows quickly blaming lines and viewing older versions of a file through the command pallete. In PHPStorm you can right-click on the margin of an editor and select "Annotate". SourceTree also exposes a few simple history searching features, which can be a good place to start.

History tools

A bunch of useful (but not particularly well advertised) tools that are bundled with Git. These are all started on the command line inside a repository.

SourceTree's search view

If you just need basic search of code and commit messages in the history, SourceTree's search view can do this. You can alternatively use git log on the command line with one or two flags to achieve the same thing.

{F697 size=full}

gitk - GUI history browser with powerful filtering

Gitk is a GUI that can utilise most of the filters available in git log. It's looks a bit like SourceTree, but it's only for working with history (to stage, commit, merge, etc the sibling program is git gui). Most of the functions listed below can be achieved with or started from gitk.

Basic usage:

  • A simple code, path, and commit message matching filter is along the middle of the window
  • More filter settings are under the "View" > "New view" menu
  • The default font size is pretty small. You can bump this up in the application's preferences

{F685 size=full}

git gui blame [file] - Interface for drilling through the history of a file

Git's blame GUI is fundamentally the same as git blame or your editors annotate/blame functionality, however it's smarter than "who last edited that line" - allowing drilling back through the history inside a single file, as well as identifying where code actually came from, rather than who put it where it is now. This makes it a trivial task to find out who originally wrote lines that have since been copy-pasted around, re-indented, and moved between files.

{F689 size=full}

git log -S 'case-sensitive string search' - Find commits that add or remove a string

This makes it possible to track when a code snippet was added to a file, moved or copied between files, and eventually deleted or replaced.

git log --grep 'case-sensitive string/regex' - Find commits where the log message matches a string/pattern

Another reason to add detail to commit messages: you can search them later in addition to the searching for code changes.

git bisect - Figure out where bugs were introduced in code by binary search

Bisect is one of those tools you might use once in an aeon, but it's a life-saver when you do. Particularly useful when working with code that you're not familiar with, or a bug you can't pin down, git bisect asks for a known bad commit (where your bug is), and a known good commit (somewhere in the past that works correctly), then steps you through commits in the most efficient sequence to find the exact commit that introduced the problem.

See Git Tools - Debugging with Git for more information on this binary search function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment