-
Getting a diff between the working tree and other commits
I’ve previously written about how to get the diffs between your working tree, the index and the last commit. But you frequently need to see the difference between the code you’re working on and previous commits.
Here’s a diagram that summarises the commands:

If you’ve read the previous article then this should make sense I’ve used
HEAD~to represent the parent of the tip of the branch you’re working on, but this can be replaced with the any of the other methods of referring to commits specified in the gitrevisions documentation.However, when doing this, you usually only want to see changes between specific files. For this you can optionally pass in the paths that you want the diff between after a pair of dashes
--. If you leave out the paths you’ll get the complete diff.git diff --cached HEAD~ -- somefile.py
This will show the difference between the version ofsomefile.pyin the index and the version inHEAD~git diff HEAD~ -- somefile.py
This will show the difference between the version ofsomefile.pyin the working tree and the version inHEAD~.
If you are using an external viewer such as Changes or Kaleidoscope (for the Mac) or other tools for other platforms. These usually come with instructions for setting them up and calling them using the
git difftoolcommand rather thangit diff. The good news is that the options and parameters are the same so you can still get pretty diffs with the same control.Posted on February 23, 2011 with 14 notes ()
-
Branching out
Branching in git is fast and easy. Coupled with fast merging, and rebasing, it is very convenient to always work on a separate branch. Typically, you create a branch, make changes to your project on that branch, merge this working branch with one of the permanent branches and delete the temporary branch.
Let’s take an example. Assume you have a repository with a single branch; master with a few commits.

The single branch master is represented by a file in the repository. It only contains a 40 character string which is the ID that uniquely identifies the commit. (You’re probably getting sick of me saying this; but I will get around to explaining that another day). There is also another reference called HEAD. This is a special reference that points to the current commit. All changes in your project will be added on top of this commit. As we only have one branch, and it is checked out, HEAD points to master.
Let’s create a new branch called feature with the command
git branch feature
Another file is created in your repository called feature that contains the 40 character ID of the commit from which it was branched. Since this branch was just created, it points to the same commit as master. Since all we have done is created the branch, not checked it out, the HEAD reference still points at master. Check out the feature branch with
git checkout feature
Since all commits will now be on the feature branch, the HEAD reference now points at the feature reference. Now, imagine some commits have been made to the feature branch.

What has happened here is that every check-in has created a new commit (which references the previous commit; that’s why the arrows are pointing backwards) and the reference file for feature has the ID updated to that of the latest commit. The HEAD commit just points to the feature branch.
Imagine another jump forward in time. The master branch has been checked out and some changes applied to that. The repository situation now looks like this.

Because we are back on the master branch, that is where the HEAD reference is pointing. If the two branches are merged with
git merge feature, then the changes from feature are merged with the changes to master to form a new commit.
Again, feature and master both point to the same commit, and as we are still on the master branch, that is where the HEAD reference points to. Since we’re done with adding the feature, the feature branch can be deleted.
It might seem like a palaver to go through this branching and merging. You don’t have to create a branch, you can make the changes to the _master) branch directly, but there are advantages:
You can consider your master branch as the working, non-experimental state of your project. Since all the messing about is done in branches and then merged back in, you always have a correct state to your project.
Changes are chunked together. If you name your branches by what you are trying to do, it’s easy to see what work is being done in what branch.
If work is being shared with other developers, working in your own branch keeps things separate.
If you give up on the changes you are making, you can just delete the branch and not worry about trying to back out all the changes from the project.
Virtually no overhead to branching; It’s just a matter of updating a 40 character string in a file.
You can do nifty things with
git rebaseon a branch.Branches in git are not permanent. You can delete them without them showing up in the history.
If you’ve worked in other version control systems I’m sure that you can think of many more reasons.
Posted on March 30, 2010 with 3 notes ()
-
What’s the difference? Part 1
This is one that used to catch me out when I first started using Git. I’d make some changes, add things to the index and then try and get a diff by calling
git diffand nothing would come up.Of course, git wants to know what I want a diff between. If you remember yesterday’s post about the buckets there are three types of diff that you can get.

If you’re new to git you may be asking “What’s this HEAD thing?” HEAD (or head) is a reference to the tip of the branch that you are on. It’s the last commit that the code you’re working on will be changing.
So there are three types of diff you can ask for:
git diff --cachedThis is the difference between what is in the index and the last commit. It shows you that changes that will be in the next commit.git diffThis shows the difference in between the index and the working tree. These are the changes that you have made to files since you last added them to the index. This is why I wasn’t getting any results. I had no changes between the index and the working tree.git diff headThis shows the difference between the files in the working tree and the last commit. There is a gotcha here: if you’ve made changes, added them to the index, and then backed out these changes in the working tree, you’ll get no results forgit diff HEAD(because there is no difference) but you will get output forgit diff --cachedbecause there are still changes in the index.
The eagle-eyed amongst you will have noticed that in the third option I am diffing against a reference to a commit (HEAD). In this case it happens to be the the last commit. Can you use references to different commits to get a wider diff? Yes you can. But I’ve got 365 days to fill so I’m going to leave that to Part 2, some time in the future.
Posted on March 26, 2010 with 1 note ()