Git Tips

This page is meant to be a collection of the useful bits that I’ve been learning about git. In particular, commands and their options that are useful, but wouldn’t necessarily know because I don’t read man pages all the time.

Set the upstream branch

Git grew a --set-upstream option for branch in 1.7.0. Usage is simple:

git branch --set-upstream <local_branch> <remote_branch>

For example:

git branch --set-upstream master origin/master

Finding which tag contains a particular commit

git describe --contains <commit>

For example:

sh$ git describe --contains 189d3c4a94
v2.6.26-rc1~155

If you know an idea of which set of tags it’s in, then you can use --match to narrow down the search and make things go a bit faster:

sh$ git describe --contains --match 'v2.*' 189d3c4a94
v2.6.26-rc1~155

Investigating a conflicted merge

  # what does the result look if I said "commit -a" now?
sh$ git diff HEAD

  # I want to also see comparison with the original
sh$ git checkout --conflict=diff3 <conflicted paths>...
sh$ git diff

  # What did they do since they forked from my history?
sh$ git diff ...MERGE_HEAD

  # What did I do since I forked from them?
sh$ git diff MERGE_HEAD...

  # I want step-by-step explanation of how these paths were touched
sh$ git log -p --left-right --merge [<conflicted paths>...]

Greping through history

To search all history:

git grep <regexp> $(git rev-list --all)

To search part of the history:

git grep <regexp> $(git rev-list <rev1>..<rev2>)

Set the mtime to the last commit that touched a file

Use the following as a post-checkout hook:

#!/bin/sh

for f in `git ls-tree --name-only -r HEAD`; do
   mtime=`git log -n1 --date=iso --pretty=%ai -- $f`
   touch -m -d "$mtime" $f
done

Determining how far ahead/behind a branch is

git rev-list --left-right --count "@{upstream}"...HEAD 2>/dev/null

The first number is the number of commits behind upstream, and the second number is the number ahead of upstream. For instance:

2        3

would mean that you’re 2 commits behind upstream, but have 3 commits that are not upstream. In other words, this example shows a divergent branch.

History simplification

Git, by default, tries to simplify history whenever possible. The best description of this can be found here: http://thread.gmane.org/gmane.comp.version-control.git/89400/focus=90659. Thanks to Junio Hamano for the link.

How to write a commit message for Git

Not only will this help you when using various options in Git (oneline summaries, etc.), but it is sound advice on writing commit messages in general: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html. Thanks to GitHub for providing the link.

Relative commit pathspec syntax

Let’s say you wanted to see what path/to/somefile.py contained on master in the HEAD revision. You could use this:

git show master:path/to/somefile.py

from anywhere in the working tree. That’s kind of painful if you are already in the path/to directory though. Instead, use the relative version of the syntax:

git show master:./somefile.py