DevOps Zone is brought to you in partnership with:

Mark is a graph advocate and field engineer for Neo Technology, the company behind the Neo4j graph database. As a field engineer, Mark helps customers embrace graph data and Neo4j building sophisticated solutions to challenging data problems. When he's not with customers Mark is a developer on Neo4j and writes his experiences of being a graphista on a popular blog at http://markhneedham.com/blog. He tweets at @markhneedham. Mark is a DZone MVB and is not an employee of DZone and has posted 524 posts at DZone. You can read more from them at their website. View Full User Profile

Git: Commit Squashing Made Even Easier

07.17.2013
| 5140 views |
  • submit to reddit

A few days ago I wrote a blog post describing how I wanted to squash a series of commits into one bigger one before making a pull request and in the comments Rob Hunter showed me an even easier way to do so.

To recap, by the end of the post I had the following git config:

$ cat .git/config
[remote "origin"]
	fetch = +refs/heads/*:refs/remotes/origin/*
	url = git@github.com:mneedham/neo4j-shell-tools.git
[branch "master"]
	remote = origin
	merge = refs/heads/master
[remote "base"]
	url = git@github.com:jexp/neo4j-shell-tools.git
	fetch = +refs/heads/*:refs/remotes/base/*
[branch "readme-pull"]
	remote = origin
	merge = refs/heads/readme-pull
[branch "readme"]
	remote = origin
	merge = refs/heads/readme

I was working against the remote ‘origin’ but the actual home of this repository is ‘base’.

I’d created a load of commits on ‘origin/readme’ and had then squashed them all into one commit on ‘origin/readme-pull’ by using the following command:

$ git rebase -i c4e94f668223d53f6c7364d19aa965d09ea7eb00

where ‘c4e94f668223d53f6c7364d19aa965d09ea7eb00′ is the hash of the last commit that was made in ‘base/master’.

Rob suggested that I should try using upstream tracking to simplify this even further. When we use upstream tracking we create a link between a local and remote repository which in this case is useful for working out where our commits start from.

I thought I’d try it out on another branch. We want to set the new branch to track ‘base/master’ since that’s the one we eventually want to have our commit applied against.

We’ll start from the ‘readme’ branch which has the list of commits that we want to squash

$ git branch
  master
* readme
  readme-pull

Now let’s create a new branch and then track it against ‘base/master’:

$ git checkout -b readme-pull-new
Switched to a new branch 'readme-pull-new'
$ git branch --set-upstream readme-pull-new base/master
Branch readme-pull-new set up to track remote branch master from base.

Squashing all our commits is now as simple as running the following command:

$ git rebase -i

And then choosing ‘squash’ against all commits except for the first one which can stay as ‘pick’. We then need to edit the commit message into shape which mostly involves deleting the commit messages from the commits we’ve squashed in this instance.

Thanks to Rob for the tip!

Published at DZone with permission of Mark Needham, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)