16

I'm currently working on implementing guidelines for git usage in a fairly complex development environment, and while I think I have the basics set up pretty well, there is one question in particular I would like some input on if that's at all possible. This isn't so much a purely technical question, as in that it's more about which of the available options is most appropriate.

Basically, I'm leaning towards a system that closely mirrors the common "git flow" structure (http://nvie.com/posts/a-successful-git-branching-model/), with some exceptions to adapt it to our development environment. In short:

  • A project will have at least a 'develop' and 'master' branch
  • 'master' will contain the latest production ready code
  • 'develop' will contain the latest merged code
  • Anything else will be in either a 'feature/ticket{number}' or 'hotfix/ticket{number}' branch
  • Feature branches will be made from 'develop', hotfix branches from 'master'
  • The number in the branch name will always correspond with the ticket number in our own change/bug system
  • Features can be tested individually, but also in combination, by building the appropriate branch or merging it to 'develop' first

So far, it's really helped us streamline our development and prevent conflicts between projects. The one detail that's spawned some debate here is; should we merge feature/ticket branches back into their respective origins with the '--squash' option? I'm somewhat of a fan of this, and what I like about it:

  • The git log for develop remains clean and readable, all commits will simply state the original branch name (which tells us if it was a hotfix or a feature, and the ticket number)
  • Even after clearing out the original feature or hotfix branch, the merge can cause no confusion afterwards

Maybe these reasons won't turn out to be good enough, and maybe there's good reasons not to use '--squash' in this scenario. Any thoughts?

mephisto
  • 481
  • 1
  • 4
  • 13

2 Answers2

19

[S]hould we merge feature/ticket branches back into their respective origins with the --squash option?

It all depends how fine-grained you want the history of your repo to be. Keep in mind that version control, via commit messages, is a form of code documentation. Squashing willy-nilly is certainly not good practice. It may be fine for a hotfix branch, but rarely is for a substantial feature branch.

As an analogy, imagine if you asked me for a lend of my Lost DVD boxset (i.e. you cloned my repo), and I just gave you the box, no DVDs, and told you

Here, just read the summary of the series on the backcover. That should tell you enough about the plot.

So, by all means, squash your commits when you want to get rid of intermediate steps that are needlessly detailed or not self-contained enough, but not to the point that it obscures the evolution of your repository.


(I discuss this matter further in this Twitter thread.)

jub0bs
  • 54,300
  • 24
  • 162
  • 166
  • 1
    That makes sense. I'm not talking about squashing just any branch blindly, of course. This would specifically be about what we consider "ticket branches". My main consideration is that it allows me to ensure that every commit that makes it into the "main" code will have a commit message that clearly specifies what ticket number it's about. Also, since most tickets I've seen here generally don't require a very large number of commits to fix, I haven't seen much reason to preserve every intermediate step once it's been tested, verified, and merged back. – mephisto Nov 19 '14 at 13:29
  • I think we're on the same page. I can see the appeal of having a commit message clearly specifying the associated ticket number; and you're right that most tickets don't require that many commits, so not so much detail would get lost in the squashing. I guess the answer to your question very much depends on the situation. In summary, squash, but with discernment. – jub0bs Nov 19 '14 at 14:01
  • Or don’t squash at all and make sure you put a ticket number into each commit message. Or change your tooling so that it can infer the ticket number from somewhere else. – Marnen Laibow-Koser Nov 09 '19 at 16:21
  • @jub0bs what if you squash with lets say a nice detailed commit message and at the footer you leave a reference from the branch you have squashed from ? this way you could have an good ordered history in your develop and if you want to check more details you could check the history of the feature branch – Yordan Kanchelov Jan 13 '20 at 14:50
  • 1
    @JordanKanchelov This would still prevent me from reversing atomic changes. That's why I prefer not to squash. – jub0bs Jan 16 '20 at 06:16
  • To eliminate quick-WIP-save commits in a local branch, you can `git rebase -i HEAD~N` (see [here](https://stackoverflow.com/q/12522565/4710226)). – ebk Nov 27 '20 at 00:40
  • @jub0bs I realize this answer is happily almost 10 years ago BUT what do you think about squashing all PR's to dev while keeping work branch history in full detail? Imo this keeps dev history short yet you can find full detail about the project in hindsight - I'm curious as to your thoughts (and potential gotchas) – Jacksonkr Mar 18 '22 at 12:44
7

Don’t squash: the small commits are useful especially for later tracking down of bugs with git bisect, and anyway you don’t want to change the history much. Just use a merge commit (git merge --no-ff) to keep the history organized.

Marnen Laibow-Koser
  • 5,585
  • 1
  • 26
  • 30
  • 11
    Tracking down bugs become harder not easier when there are a lot of noisy meaningless intermediate commits. You want to make a cohesive commit that represent chunks of changes that would make sense to cherry pick from one branch to another. The project should build and be in a sensible state after applying each individual commit. – Sámal Rasmussen Mar 24 '20 at 17:17
  • 5
    @Sammi: “The project should build and be in a sensible state after applying each individual commit.” Agreed. • “ Tracking down bugs become harder not easier when there are a lot of noisy meaningless intermediate commits.” I’m not advocating meaningless commits, but I am advocating smaller ones. Since `git bisect` uses the commit as its unit of granularity, smaller (meaningful) commits make tracking down bugs *easier*. I agree that each commit should be a cohesive known-good state, but sometimes that means only changing 3 lines of code. – Marnen Laibow-Koser Mar 25 '20 at 18:57