17

In the announcement of Linux 5.15-rc1 Linus said:

At only just over 10k non-merge commits, this is in fact the smallest rc1 we have had in the 5.x series.

What is a non-merge commit? What's the opposite of a non-merge commit?

Thomas Owens
  • 79,623
  • 18
  • 192
  • 283
robertspierre
  • 313
  • 2
  • 5
  • 9
    `git merge` creates merge commits. `git commit` creates the usual (non-merge) commit. Merge commits have more than 1 parent commits. – Stanislav Bashkyrtsev Sep 13 '21 at 11:06
  • 5
    A "non-merge commit" - IOW a _typical normal_ commit - is where the _work_ is done. A "merge" commit is just software engineering overhead where you combine the work you've just done with all the known "good" work you've done before to hopefully produce a "new and improved" piece of software . – davidbak Sep 13 '21 at 15:21
  • 3
    @davidbak et al., please write answers as answers and not comments... – Pablo H Sep 14 '21 at 16:11

3 Answers3

33

If you're working in a feature branch, that branch might have a significant lifespan. By that I mean that the originating branch (master or develop usually) receives many commits while the feature branch is off on its own. This could be because the feature is unexpectedly delayed, was expected to take a long time, or if there's lot of concurrent development happening (e.g. large dev teams). For whatever reason, the situation I'm focusing on is one where a lot of things happen to master between the start and end of your specific feature branch.

Eventually, the feature branch needs to merge back into master. However, if master has significantly changed since then, there may be conflicts because the feature was written against an outdated codebase which is no longer the same as today's master code.

It is generally considered to be better to have multiple small issues instead of one big one at the end.

To avoid having such a big break event, it is advised to regularly merge master back into your feature branch. This means that you introduce the new changes that have been made to master in your feature branch, so that you can quickly spot and fix any conflicts that may arise.

Those merges from master into the feature branch, when they are not rebase actions, generate a commit message to the feature branch history. Something along the lines of:

2021-01-01   Started feature branch
2021-01-01   Added FOO
2021-01-02   Merged from master
2021-01-02   Refactored FOO
2021-01-02   Added BAR
2021-01-03   Merged from master
2021-01-04   Merged from master
2021-01-05   Added BAZ

But really, those merge commits don't indicate how much work has happened on this branch. They only indicate how much changes have occurred on other branches during the lifespan of this branch. In reality, there have been 4 commits on this feature branch that are indicative of work that has happened on this feature.

Therefore, if you're trying to express the amount of work that went into a specific branch, you should measure the commits except merge commits, since they are not a measure of development on the actual branch.

Hence why Linus is expressing the amount of non-merge commits to indicate the relative size of rc1.

Flater
  • 44,596
  • 8
  • 88
  • 122
  • 6
    Back-merging master into a feature branch is not the only option, it’s just the one used by the Linux development cycle and most other projects with a traditional development model. Some projects instead prefer rebasing feature branches when they need to review and/or test them, and even if the project does not do so globally it’s generally a better approach for private branches since it makes it easier to move the branch around if you need to. – Austin Hemmelgarn Sep 13 '21 at 21:49
  • 5
    The trouble with rebasing is that if someone pulls a branch then git will try and merge their local branch with the rebased branch and make a mess. Some say you should never rebase a branch that has been pushed publically, I wouldn't go that far myself but I would never want to rebase a branch that has lots of people interacting/collaborating with it. – Peter Green Sep 14 '21 at 03:25
  • My understanding is that Linux uses patch series for the bottom tier of development which serve a similar purpose to rebased branches (indeed they may be generated from private rebased branches). – Peter Green Sep 14 '21 at 03:39
  • @PeterGreen: While I like the idea of rebasing, the risk of things going ugly puts me off it. That being said though, most feature branches in everyday development don't have many developers working in conjunction with one another so it is _relatively_ safe. But e.g. for Linux, it makes a lot of sense to not rebase due to what I presume to be a much higher concurrent dev count. – Flater Sep 14 '21 at 07:55
  • @PeterGreen Oh, absolutely agreed. Rebasing is only reasonable for private branches or cases of branches with few, if any, developers collaborating on them. The general rule I use is to not rebase if anybody other than me has added commits to the branch. My only point was to indicate that back-merging the parent branch is not the _only_ option for dealing with branch divergence (because there are a surprising number of people out there who act like it’s the only option). – Austin Hemmelgarn Sep 14 '21 at 11:48
  • @austin I wonder if anyone does both. You take your branch rooted at A, rebase it into branch' rooted at B Then you merge the original branch to branch' by simply accepting the branch' tree in toto. This new branch'' has both the original history (going back to A) and the rebased history (going back to B) and a merge node that says both are valid histories of this change. Anyone with the local based off A branch who pulls gets a sensible conflict resolution. – Yakk Sep 14 '21 at 18:52
8

In git each commit is a specific version of the code, and it includes information about which previous version(s) it was based on - those commits are known as its parents.

A merge commit is a commit that has two or more parents, i.e. it is bringing together multiple lines of development. Usually it is bringing a line of development of a feature into the main general line of development of the entire product. It doesn't normally include any original development work other than bringing things together.

A non-merge commit is a commit with less than two parents. (Normally exactly one parent). The majority of commits in a project are usually non-merge commits, where a programmer has done some work on top of one specific previous version.

bdsl
  • 2,365
  • 1
  • 14
  • 14
3

A "non-merge" commit is a commit that introduces an actual code change. A merge commit just moves around changes that were already introduced by non-merge commits.

That's why non-merge commits can be a measure of productivity or change, assuming every commit introduces, on average, a similar "amount" of change.

AndreKR
  • 577
  • 3
  • 11
  • 1
    Merge commits also include the changes needed to resolve any conflicts. If there *aren't* any conflicts, then there is no change needed but that is not always the case. Therefore, I don't think we can say that merge commits never contain work. Following good commit and branching etiquette does minimise them, though. – VLAZ Sep 14 '21 at 10:31