What is a linear git history

Tram Ho

If you’ve ever been into the protected branch installation of Github, you’ve probably seen it through this setting.

github-settings.png

You have to ask me what this is. In fact, most of git’s workflow discourages it, so no one should pay attention to it. But I’ve seen it anyway, so let’s find out.

Define

In my opinion, it is simply a commit history without a merge commit. Meaning each commit has only 1 parent and 1 child. It will look like a straight line.

For example like this

And this is not a linear history

How to get a linear history

First of all, when do we have the merge commit. Merge commit is generated when we merge 2 branches but can’t use the fast forward strategy, git will create a merge commit to merge 2 branches. For example we have 2 branches like this.

When testing is having the same history as the master , with only 2 more commits A and B , we can fast forward . Meaning that just apply changes of A and B is done.

But if we have 2 branches like this.

Then you will not be able to use fast forward, you must create one merge commit. Merge 2 branch will look like this.

If you use git merge with the --no-ff flag, even though the branch can be fast forward , a merge commit will still be created.

So to get a linear history, we need to make sure that every merge and branch merged must have an up-to-date history with the base branch so we can use the fast forward strategy. To update branch with base branch, we use git rebase . Rebase will reapply all commits of the current branch to the base branch.

The current branch example is this. Branch feature checked out from master at commit A

If you merge 2 branches now, you will create a merge commit. Now from the branch feature I use git rebase like this.

It will be like the feature will be checked out again from commit C , then commit D and E will be re-applied to the feature . Now branch will look like this.

The feature can now be merged into the master with the fast forward strategy.

Note that rebase will change history as you see above. So you only use rebase on the current branch you are doing (not pushed to the general repo) only. If you work with a large, time-consuming feature (working alone, don’t share a branch with anyone) then regularly rebasing with the base branch will help your code update with the latest code from the base branch and it’s time to merge. feature conflict as well as bugs not yet discovered.

Linear history for what

So why do people want a linear history. There are several advantages as follows

  • Easily determine the order of commits. You probably already know that merge commits actually combine two branches and each branch can have history independent of each other. When using git log , you see that the commits are organized as a straight line. But actually it is so easy to read. And actually it looks like the picture above. So it’s hard to determine which one is first, and it’s hard to know which commit actually caused an error.
  • Commit history more neat. There will be no merge commits that will confuse you anymore. And you try running git log --graph with a repo without a linear history, will understand this.
  • Easily revert commit. Because each commit has only 1 parent, unlike merge commits, revert commits or cherry-picks is a lot less headache.

Defect:

  • Need users to understand git. git rebase actually quite difficult to use and makes a commit history error easily.
  • Fix conflict with git rebase much harder than git merge . With merge , we only need to fix the conflict in a commit. Whereas with rebase , maybe every commit has conflict.
  • Actually, you may not need a beautiful history. Everyone is fine with git merge .

Require linear history on Github

If this feature is enabled on Github then you will not be able to merge pull requests by creating merge commits anymore.

github-merge-linear.png

You only have 2 options left: Squash and merge and Rebase and merge . Squash and merge will squash all commits in pull requests, rebase and merge. Rebase and merge is almost the rebase we see above. Both use the fast forward strategy so as not to create additional merge commits and keep the commit history linear.

If you merge with Rebase and merge, then when reverting to PR, Github will make every commit in PR a revert commit instead of just one commit as big as the merge commit.

github-revert-rebase.png

Share the news now

Source : Viblo