365Git

  1. Search
  2. About
  3. Subscribe
  4. Archive
  5. Random

365Git

Regular small snippets and workflows for Git

My original plan of a post everyday turned out to be unrealistic, but I'll carry on posting as regularly as I can.

Find me @abizern on twitter if you have anything you'd like me to cover.

  • 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:

    Git diff commands summary

    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.

    1. git diff --cached HEAD~ -- somefile.py
      This will show the difference between the version of somefile.py in the index and the version in HEAD~

    2. git diff HEAD~ -- somefile.py
      This will show the difference between the version of somefile.py in the working tree and the version in HEAD~.

    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 difftool command rather than git diff. The good news is that the options and parameters are the same so you can still get pretty diffs with the same control.

    Tagged: git diff working tree gitrevisions ranges files head index

    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.

    Simple Branching 1

    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

    Simple Branching 2

    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

    Simple Branching 3

    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.

    Simple Branching 4

    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.

    Simple Branching 5

    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.

    Simple Branching 6

    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 rebase on 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.

    Tagged: git branch HEAD merge commit day7

    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 diff and 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.

    Simple Git diff reminder

    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:

    1. git diff --cached This 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.

    2. git diff This 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.

    3. git diff head This 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 for git diff HEAD (because there is no difference) but you will get output for git diff --cached because 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.

    Tagged: git diff head index working tree day3

    Posted on March 26, 2010 with 1 note ()

Field Notes Theme. Designed by Manasto Jones. Powered by Tumblr.