Monday, August 24, 2009

Git Tips

Last updated: March 15, 2010

A flurry of excellent documentation and great blog posts has been published about Git. But who doesn't need some additional tips on how to better use your source code management tool of choice? So here are a few that I found useful:

Table of contents

Ignoring files
Getting rid of the warnings when pushing
Finding when and why that code was changed
Mac OS X: colors for your terminal
Handling pull requests
Avoid "Merge Branch..." in the commit history

Ignoring files

I always have a number of files in my projects that I have no intention of checking in, such as a TextMate project file (orbeon-forms.tmproj) or scratch files I use for testing (gaga.xhtml). Those files pollute the output of your git status. Sure, you are smart enough to ignore them, but why not let Git do the ignoring for you? Do so by listing the files you want Git to ignore for this current repository in .git/info/exclude.

Getting rid of the warnings when pushing

When running a git push without specifying what branch to push, you'll get the warning message You did not specify any refspecs to push. By default git pushes all the local branches for which there is a remote branch with the same name. It does so, but still tells you that this may not be what you want. To have git push only the current branch (and also get rid of the error message every time you do a push), run:
git config --global push.default tracking
You could use current instead of tracking, but it won't have the desired effect when the name of your local branch doesn't match the name of the remote branch you want to push to. Really, this should be the default.


Finding when and why that code was changed

Run the following command and locate the piece of code you are interested in:
git blame your-file.ext
Copy the revision number (rev) showing at the beginning of the line and run:
git log -1 -p rev
The -1 tells Git you're only interested in that particular commit, and none of the previous commits. The -p as in patch gives you the changes to the code done in that commit.

Mac OS X: colors for your terminal

First, for you terminal to support colors, add the following two lines to your .bash_profile:
export CLICOLOR=1
export LSCOLORS=ExFxCxDxBxegedabagacad
Then enable colors in diff and status with:
git config --global color.diff true
git config --global color.status true

Handling pull requests

(This is based on the GitHub documentation and example.) Start by adding the remote repository. The first defunkt is the local name you give to the repository at the URL that directly follows. The -f is to immediately fetch that repository (fetching retrieves the data from the remote repository to your local repository):
git remote add -f defunkt git://github.com/defunkt/grit.git
Checkout the code from your local repository to your working directory and at the same time create a branch named defunkt:
git checkout -b defunkt
Now that your working directory is in the branch defunkt, pull the latest code from the master branch of the repository defunkt to the working directory (if you just did the git remote add -f, most likely there will be nothing new to pull):
git pull defunkt master
To avoid having to specify defunkt master on the command line every time you do a pull (of course you want to pull from the same repository and branch you originally got the data from!), run the two following commands. The first one defines defunkt as the default repository for the your branch defunkt. The second one defines the remote master branch as the one you want to merge with the current branch. (It is a config for merge because pull runs a fetch and a merge.)
git config branch.defunkt.remote defunkt
git config branch.defunkt.merge refs/heads/master
Switch to your master branch:
git checkout master
Merge the branch defunkt into your current branch (master). The merged commits from defunkt will go to your local repository.
git merge defunkt
Before you push the changes, you'll want to review and test them. You can see what you would send to the remote repository if you were to do a push now with:
git diff origin/master..master
If you make changes to the files in your working directory (say, to amend the changes made by the developer who sent you the pull request), you can see a diff between your working directory and the remote repository (which will include the changes your pulled plus your changes) with:
git diff origin/master
To only view a summary of what was changed (the diffstat showing files names and how much was removed/added), add the --stat parameter:
git diff --stat origin/master

Avoid Merge Branch... in the commit history

You do this by rewriting your local commits to be applied to the new state of your local branch as it will be after the changes you pulled from a remote source have been applied. You can do this in a single command:
git pull --rebase
You always want the rebase to be done when pulling changes, and would like to avoid having to put that --rebase every time you do a pull? No problem, run the following just once (assuming you want to enable this for the master branch):
git config branch.master.rebase true
Also see Rebasing is Editing Commits, which provides background information on the subject.