Search code examples
gitmergecommitrebasebisect

What git commit practice is better?


I truly believe that to have one commit on one issue is a good practice. I'm sure I read it somewhere in an article like “Best practices”.

As such, my workflow has been the following:

  • For a new issue, I create a new local branch with git checkout -b new-issue.
  • Commit all changes into it. Sometimes this involves lots of commits.
  • When done, I squash the commits and rebase them into current thematic branch.
  • If something goes wrong, I can git revert the commit, find the bug, fix it, and commit new patch into the thematic branch. I won't change the remote repository’s history.

But today, I was surprised to hear the following workflow:

  • Create new branch for the new issue.
  • Commit everything into it.
  • Use merge --no-ff to merge the issue branch with thematic branch (so we’ll have “merge-commit” that we can revert).
  • If something goes wrong, we can use git bisect to find the bug.

According to the 1st approach, we’ll have a clean git history, and no idea about overhead branches used during development.

According to the 2nd approach, we’ll have a very messy history, with a lot of ugly, unnecessary merges and commits for just one issue. However, we can use git bisect to find bugs. (Perhaps this is better for refactoring?)


  • What pros and cons do you see for both approaches?

  • Which approach do you use, and why?

  • In practice, have you actually used git bisect to find bugs? (I haven't…)


Solution

  • In the end, it is largely a personal taste issue... can only explain my taste (and give a bit of justification for it).

    I tend to keep the individual commits around, even when they are just "Fix dumb typos". Any "history rewriting" creates commits that never before existed, so are guaranteed never to have been tested. Besides, minimal commits make git bisect immensely useful when a bug surfaces later. Better to be able to narrow it down to a few changed lines than to a week's work, squashed together.

    If a development branch gets a mess of a history, I clean it up (minimally, i.e., reverted commits just never happened, general fixes like whitespace or variable renamings might get applied earlier, some reordering to place related changes together). Commits still stay small, are rarely squashed. This cleanup I do incrementally mostly. Then I merge (or rebase) the cleaned up branch with the "official" one.