-
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 ()
-
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 ()
-
The four buckets — how Git considers content.
A slightly longer post today but it’s important that the basics of git are covered.
My first suggestion is to think of git as tracking content, not files. In the coming days I’ll cover the way that Git stores information and this should become a lot clearer. But it helps to realise that the contents of a file and the name of that file are not kept in the same place. Secondly, Git only tracks changes files that you tell it to track.
I think of Git considering this content in 4 places. Here’s a simple diagram

This is a simple view of the four buckets. I’ve shown the simplified commands that move content between these buckets (leaving off the extra flags and parameters for simplicity).
Commit
This is the frozen state of the files that git is tracking at the time that it was created. These are the objects that are actually stored in a repository and are shared with other repositories
Index
This is the staging area for commits. This is the state of the tracked files that will be used to create the commit.
Working tree
This is the area where there are changes to tracked files, but these changes have not been added to the index and will not become part of the next commit. This needs some explanation.
When you create a new repository, and as you add and remove files from your project, you need to tell git about the files that it is supposed to track. But that doesn’t mean that these files’ changes will automatically become part of a commit. The changes need to be in the index for them to become part of the commit. Some people don’t like having two steps to commit a file.But you don’t need to because
git commit --allwill take all changes to tracked files and make a commit from them in one step.Because branching, merging and changing history are easy with git, it encourages you to make many small commits rather than one large commit. So, imagine the scenario where you are working on a feature and add those changes to the index with
git add. You can now make other changes to your files. If you think these changes are significant enough to go in their own commit, you can commit the changes that are staged in the index and then add the new changes to this index. Or, if you think you want to make all these changes one commit, just usegit commit --alland the new changes and the staged changes will all become a single commit.When starting out with git, it’s easy to forget that all changes are not automatically made into a commit. So remember yesterday’s post about amending commits which will help to fix these ommissions.
Untracked files
If you add new files to your project they are not tracked by git. If you run
git statusyou’ll see that these new files exist and that they are not tracked. This is a reminder that these may need to be added. Of course, there may be good reasons not to include a file, and if you don’t want to be constantly reminded to add the file, you can ask for it to be ignored. (I’ll cover this another day.)Summary
Git tracks content in 3 places and doesn’t worry about anything it doesn’t track. You can move files between these areas, and if you use
git statusnot only does it tell you what files belong to which area, but also how to move them out of those areas.