Photo from Chile

Comparing Files from Different Branches with Git Difftool

As a relative newcomer to Git one of the things I've struggled most with is how to compare files from different branches. The challenge comes from the fact that, from the perspective of the file system, two branches cannot exist at the same time. When you switch from one branch to another the new branch replaces the old branch, so you cannot use a native file compare tool to compare two sets of files, as there really is only one set of files at any point in time. Now I admit that I might be totally wrong about this, and I'm sure that there are other, perhaps better, solutions to the issue, but the one that works for me currently is git difftool.

What is Git Difftool?

According to the man page for git-difftool,

git difftool is a git command that allows you to compare and edit files between revisions using common diff tools. git difftool is a frontend to git diff and accepts the same options and arguments.

I've tried using git diff in the past and, after spending years working with a wonderful tool like Subclipse's Synchronize with Repository, I just did not enjoy the output of git diff at all. Luckily, git difftool works with a file compare tool on your system, making the output much easier (for me at least) to deal with. On my system, which is OS X, because I have the Apple Developer Tools installed, when I issue the git difftool the output is sent to opendiff, which in turn uses FileMerge which is a nice, graphical file compare and merge tool. Other than installing the developer tools, which I did long before I started using Git, I didn't have to do any other setup. I honestly have no idea how easy it is to set up a graphical compare tool to work with git difftool on a Windows or Linux box, but I'm guessing it cannot be that difficult.

Using Git Difftool

To start a compare, you simply issue the git difftool command and pass it paths to two sets of files. The paths look like branchName:path. So if I wanted to compare the file ValidationFactory.cfc from the master branch to the same file in the newStuff branch, I'd type:

git difftool master:ValidationFactory.cfc newBranch:ValidationFactory.cfc

I'd see a prompt that says something like:

merge tool candidates: opendiff kdiff3 tkdiff xxdiff meld kompare gvimdiff diffuse ecmerge araxis emerge vimdiff
Viewing: 'master:ValidationFactory.cfc'
Hit return to launch 'opendiff':

And when I hit return FileMerge would open up with both files displayed. If I want to compare an entire folder, I can just type

git difftool master:ValidateThis/core/ newBranch:ValidateThis/core/

And then I receive that prompt for each individual file in turn.

I still don't think this is anywhere near as good as what I had with Subclipse, and I'm guessing there are ways to configure it to make it even friendlier, but for now it's much better than git diff.

Using Git Rebase to Squash Commits

A Git command that can be very useful, yet is often overlooked by beginners (such as myself) is the rebase command. I admit to not fully understanding all of its uses, but there is one simple use for it that I have found myself taking advantage of lately. Here's the scenario:

You have a remote Git repository, perhaps hosted at GitHub. You want to work on a new feature, so you create a local branch on your machine:

git checkout -b newBranch

You make some changes and commit them to the local branch:

git commit -a -m"My first set of changes"

You make some more changes and commit them to the local branch:

git commit -a -m"My second set of changes"

You make some more changes and commit them to the local branch:

git commit -a -m"My third set of changes"

You now have three separate commits that relate to one feature, and the feature is complete. You could simply push the changes to your remote, but then you'd end up with three commits on the remote that are not particularly meaningful. The only reason you have three commits in your local repo is that you completed the work in three steps. Perhaps you'd rather have just one commit reported in the remote repo for this feature. Thankfully git rebase allows you to do that very simply.

[More]

Using TextMate as the Default Editor for Git on OS X

There are a number of Git commands which pop open a text editor which you then use to provide information. For example, if you issue the command:

git commit

The editor will appear allowing you to type your commit message. The default editor that appears for me, on OS X, is vi which is a strange beast to work with if you've never encountered it before (which I hadn't, prior to using Git). I found a helpful cheat sheet, which allowed me to use the editor, but I still find it cumbersome. Thankfully it's a pretty simple matter to use a different text editor with Git. There are a number of ways of doing this, and I'm going to discuss two of them. To start, let's look at how Git decides what editor to use.

Which editor will Git use?

According to the man page for git-commit:

The editor used to edit the commit log message will be chosen from the GIT_EDITOR environment variable, the core.editor configuration variable, the VISUAL environment variable, or the EDITOR environment variable (in that order).

We're going to look at changing the EDITOR environment variable and the core.editor configuration variable.

Change the EDITOR environment variable

Simply add the following line to your .bash_profile:

export EDITOR="/usr/bin/mate -w"

This will cause Git to use TextMate, and may also allow other command line tools to use it as well.

Change the core.editor configuration variable

Issue the following command:

git config --global core.editor "mate -w"

This is useful if you only want to change the behaviour of Git, and not affect the rest of your environment.

Git Cheat Sheet

I've been using Git for awhile, but I still use Subversion for most of my projects, so I seem to always come back to Git after a long break. Of course, by that time I've forgotten how to do certain things, so I thought I'd throw together a quick cheat sheet that I, and anyone else, can use as a reference. I will continually update this post as I come up with new questions and answers.

[More]

Using Git and GitHub to Sync Config Files between Machines

This post is a follow-up to my earlier post about Placing Config Files Under Version Control with Git and GitHub. In that post I discussed how one can use Git and GitHub to place your config files under version control (via Git), and to maintain a backup of them (via GitHub). In this post I'm going to discuss a set up that will allow another machine's config files to stay in sync with the originals. The scenario I'm discussing involves config files, but one could use this approach for any set of files that one wants to keep in sync between two machines.

[More]

Placing Config Files Under Version Control with Git and GitHub

Working with Git, I've become aware of the fact that there are certain config files on my machine which require customization and therefore would be nice to have under version control. These files are often referred to as dot files, or dotfiles, as their names all start with a dot. The three files that I currently have under version control are .bash_profile, .gitconfig and .gitignore. The first two of those files expect to reside in my home directory, but the way Git works, in order to place them under version control they need to reside in a folder that is also a Git repository.

For obvious reasons I don't want to make my home directory a Git repo, but there's a simple solution to this problem. Using symbolic links, a topic that I discussed in an earlier blog post, I can keep my dotfiles in a Git repo, and also continue to use them as live config files. Here is a step-by-step guide to getting your dotfiles under version control with Git:

[More]

OS X Command Line Interface Tips - Customizing the Bash Shell

I've been working on a Mac for around four months now, and never really had much reason to open up Terminal and use the command line interface (CLI), other than for starting and stopping Tomcat. Now that I've started trying to learn about Git, I'm using the command line more and more, and finding out new stuff daily, so I'm going to write the occasional post to share some of this info.

About Bash

The operating system that most of us run on Macs is called OS X, and it's based on Unix. The way that one interacts with Unix is via a command shell, and the default shell for OS X is called Bash. It allows us to interact with our operating system without going through the graphical user interface (GUI) that sits on top of the OS. According to Wikipedia Bash stands for Bourne-again shell as it is a successor to the Bourne shell. So, when you open up Terminal, or iTerm which is an enhanced Terminal alternative, you are interacting with the Bash shell.

[More]

More Entries