seeking git wisdom: to squash or not to squash

domm on 2009-04-25T19:21:23

I guess this question has no correct answer, but I'd still appreciate any feedback.

I'm currently trying to find my personal preferred git style. There are a few things I'm sure about:

  • master is the stable, i.e. what's running on live (and what could be released at any time)
  • bug fixes and features should be done in topic branches, which might or might not be pushed to public (depending mainly on how long it takes to implement them)
  • We're using gitosis

When I'm done with a topic branch and about to merge it back into master, I see two options: Just merge it. Or use git rebase --interactive to squash all commits I did into one, and than merge that.

The plain merge has the advantage that a lot of small commits are easier to merge (or so I've been told). Plus it's easier to revert/bisect later. The disadvantage is a lot of clutter in the history / git log.

If I squash all of my commits into one, I can avoid that clutter (and one can write beautiful commit messages after an rebase --interactive). But than this single big commit might be hard to merge. And a lot of fine grained information is lost.

So, can you offer any insights on this question? (hm, and maybe I should post this on some git list or on stackoverflow.com...)


do not squash

hdp on 2009-04-26T01:33:05

Once you throw away information, you can't get it back. Put the beautiful commit message into the merge commit if you must have it; I never find myself bothering. The "clutter" you mention is really a non-issue; git has powerful tools to browse/search history.

Re:do not squash

jdavidb on 2009-05-07T15:17:02

If you are like me, your topic branches are always rebased onto master frequently, and so when you merge into master you get a "fast-forward" commit: master (the pointer to the trunk of your tree) just suddenly points to the same commit as the branch you merged, and no new commit object is created.

This can be a little bit annoying, because there is no way to tell that the last $N commits were all merged from a branch and belong together as a set, and that the real previous state of your trunk (for certain points of view) is $N commits back.

To solve this, you can use the --no-ff option to git-merge, which prevents a fast-forward merge from occurring, thus creating a genuine commit object whose parent commits are the previous state of master and the state of the branch you are merging, which will happen to be the new state of master as well. This may facilitate better history browsing, although I'm not experienced enough to say for sure, yet. You might also like the --log option, which will add portions of all your commit messages to the merge commit message.

Re: seeking git wisdom: to squash or not to squash

daxim on 2009-04-27T08:39:11

squash only commits that should have been a single commit in the first place.

pick deadbee add frobnitzers to lib/*.pm
pick fab4cab switch tests to new scheme
pick b00b135 oops, forgot files in lib/ subdirs

pick deadbee add frobnitzers to lib/*.pm
s b00b135 oops, forgot files in lib/ subdirs
pick fab4cab switch tests to new scheme

Focussed commits are better

Aristotle on 2009-04-27T12:55:14

What daxim said.

Also, another option is, if no one else has worked on the branch but you, you could rebase it onto master to linearise the history, making it easier to read.

But don’t squash entire branches in order to merge them. Focussed commits are easier to understand. They are also far more useful to git bisect.

If you feel the need for good merge commit messages, just write them yourself, as hdp said.