Upcoming and OnDemand Webinars View full list

Git Treeishes Considered Awesome

Will Farrington

A Street Called Awesome

As developers, we love having quality tools like git, available to us.

Using git, we can easily navigate through all the code ever “committed” or added to a project throughout its history. We do this via git treeishes. Treeishes are git’s way of referencing commits and relations between commits. Treeishes can improve your workflow immensely if you’re a frequent git user.

In this post, we’ll cover some of the more basic treeishes and then work into the advanced ones, with some real-world examples.

The Basics

You’ll probably be familiar with the types of treeishes in this first section if you’ve ever used git before. The following section will cover some more advanced uses of treeishes that even long-time git users may not know about.

SHAs

Every commit in git is identified by its SHA — a unique hash. These hashes are pretty long (40 characters in fact), but git also allows you to reference any commit with any truncated version of its hash so long as the truncated portion is unique (generally, this means at least 5 characters long).

Branches, Remotes, and Tags

Branches, remotes, and tags are another kind of treeish. Each of these is actually just a pointer to a git commit.

Advanced Treeishes

Now we’re getting to the really good stuff!

It’s important to have a good understand of the git reference log (reflog for short) which enables most of the more advanced treeishes.

The git reflog is a running log of recent changes to tips of branches. In practice, this means that every time you commit to a branch, pull commits down from a remote repository, or checkout a new branch, your reflog will update. It’s important to recall that reflogs are specific to individual checkouts of a repository so the reflogs for the same project can differ across machines.

Here’s an example reflog from one of my personal projects:

› git reflog
0a4faaa HEAD@{0}: checkout: moving from 0a4faaaf0081e2a5e439e79f48e236cdfbcb687b to i-herd-u-liek-chef
0a4faaa HEAD@{1}: commit: Remove unnecessary comment.
d4fdbdb HEAD@{2}: commit: Real namespaces in the app code now.
fc16081 HEAD@{3}: commit: Suddenly, NAMESPACES
b36e3a8 HEAD@{4}: clone: from git@github.com:wfarr/censored.git

This reflog shows that some of the more recent changes to this project include:

  • Cloning the project from the remote repository
  • Making a few commits
  • Checking out a new branch from the tree at 0a4faaa (which just happens to be master)

Using the reflog, git can infer some interesting relative context for commits that will allow us some more flexibility in what we can get at with treeishes.

Date Specs

We use the date spec here at Highgroove as part of our weekly code reviews. With the date spec, I can easily look at the activity on a feature branch over the course of the last week:

git diff master@{1 week ago}

Tilde Spec

Similar to the ordinal spec, the tilde spec allows you to reference the Nth grandparent of a commit.

This is useful just to go back 2 or more commits in time in one command.

master~2

Caret Parent Spec

Unlike the tilde spec, the caret parent spec allows you to reference the Nth parent of a commit. The distinction here is important as the caret parent spec can walk backwards through commits that have more than one parent (merge commits), while the ordinal spec cannot.

The caret parent spec looks like:

master^2

The caret parent spec and the tilde spec can also be chained together, so master^^ would actually point to the same commit as master~2.

Range Spec

The range spec allows you to express a range of commits as a first-class object in git. These are frequently used for things like diffs where you may want to view the changes across a number of commits.

For example, the following command would show a diff of all commits between master and my current feature branch:

git diff master..i-herd-u-liek-chef

You can also refer to the range from the current commit through all commits after it by just leaving off the other ref after the “..”.

All of these treeishes are available from the git command line interface – though if you’re using a GUI to interact with git your particular application it may support some or all of these. I know that Github’s compare view can be used with treeishes as well. Hopefully if you’re not already using treeishes you’ll find that they’re as useful to you as they are to us.

How are you using git treeishes to improve your workflow?

Image credit: @moonlightbulb

Not Happy with Your Current App, or Digital Product?

Submit your event

Let's Discuss Your Project

Let's Discuss Your Project