Git Guide

This page provides some helpful tips for setting up Git for maximum productivity, helpful hints for daily use, and recipes for more complex tasks that are used less frequently (but are yet powerful and oftentimes hard to recall from memory).

Initial Git Setup

Install Git Autocomplete

The following provides for a Bash-like feature to auto-complete git commands with the Tab key. This is very helpful for quick branch switching, among other things:

marvin:~/Code/jasig/cas$ git checkout f[Tab]
feature-lppe-1               frett/CAS-984 
feature-new-authn-api        frett/defaultProperties 
feature-new-authn-api-ldap   frett/feature-cas4api 
frett/3.3.x                  frett/feature-lppe 
frett/3.4.x                  frett/master

Installation: - Download bash script:

curl https://raw.github.com/git/git/master/contrib/completion/git-completion.bash -o ~/.git-completion.bash
  • Add the following to ~/.bashrc or ~/.bash_profile:
if [ -f ~/.git-completion.bash ]; then
  . ~/.git-completion.bash
fi
  • Logout/login (~/.bash_profile) or launch a new terminal (~/.bashrc) for changes to take effect

Configure Global Options

It is very helpful to configure some global Git options in ~/.gitconfig. At a minimum you should specify name, email, and editor environment parameters. Git aliases provide a very powerful way to automate tasks. A sample .gitconfig for reference:

[user]
	name = Marvin S. Addison
	email = marvin.addison@gmail.com
[core]
	editor = vim
[merge]
	tool = gvimdiff
[alias]
	unstage = reset HEAD --
	discard = checkout --
	parents = rev-list --parents --oneline
[http]
        sslcainfo = /path/to/vt-global-cachain.pem

Global parameters may be configured on a per-project basis with a .gitconfig file that resides in the project root directory. For example, it is common to override name and email parameters on a per-project basis.

Git Recipes

Merge a Changeset Onto Another Branch

It is common to want to apply a set of commits on one branch (e.g. master) onto another branch (e.g. release branch) that do not share a common ancestor. While single commits are easily applied to another branch (e.g. via git cherry-pick), there is no single command to accomplish merging a range of commits. The following recipe leverages git rebasing to accomplish this task in a clean fashion. Before you begin, you need to know two pieces of information:

  • A - the commit BEFORE the start of the range you want to apply
  • B - the commit at the end of the range you want to apply

Typically B is easy to determine, and A can be easily determined with the following command:

git rev-list --parents --oneline B -n10

The command above displays the first 10 commits in the commit graph leading up to B.

# Start on the branch where changes are to be merged
git checkout rel_1

# Checkout a new temporary branch at the current location
git checkout -b tmp

# Move the rel_1 branch to the head of the new patchset
# B is the last commit in the range of commits to apply
git branch -f rel_1 B

# Rebase the patchset onto tmp, the old location of br
# A is the commit BEFORE the first in the range of
# commits to apply
git rebase --onto tmp A rel_1

# You are now on the rel_1 branch with patches applied.
# It is now safe to delete the temporary branch tmp
git branch -d tmp