Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Semi linear merge

I just noticed in Azure DevOps, there's this option called semi-linear merge. I was wondering what it does? Does it come between the merge strategy & rebase strategy (from the name semi-linear)? If so, what are the pros/cons?

enter image description here

Edit: From Microsoft Devblog I believe this option consist of 2 points:

  1. Rebase the feature branch from the master/dev branch
  2. Then merge the feature branch in the master/dev branch

But isn't that the merge strategy?

like image 710
Melchia Avatar asked Jan 13 '20 10:01

Melchia


People also ask

What is a semi-linear merge?

Semi-linear merge This strategy is the most exotic – it's a mix of rebase and a merge. First, the commits in the pull request are rebased on top of the master branch. Then those rebased pull requests are merged into master branch.

What is a fast forward merge?

Fast-forward merges literally move your main branch's tip forward to the end of your feature branch. This keeps all commits created in your feature branch sequential while integrating it neatly back into your main branch.

What is git 3 way merge?

3-way merges use a dedicated commit to tie together the two histories. The nomenclature comes from the fact that Git uses three commits to generate the merge commit: the two branch tips and their common ancestor.

What is git rebase vs merge?

Git Merge Vs Git Rebase:Git merge is a command that allows you to merge branches from Git. Git rebase is a command that allows developers to integrate changes from one branch to another. In Git Merge logs will be showing the complete history of the merging of commits.


2 Answers

Semi-linear merge
This strategy is the most exotic – it’s a mix of rebase and a merge. First, the commits in the pull request are rebased on top of the master branch. Then those rebased pull requests are merged into master branch. It emulates running git rebase master on the pull request branch, followed by git merge pr --no-ff on the master branch.

enter image description here

Some people think of this as the best of both worlds: individual commits are retained, so that you can see how the work evolved, but instead of just being rebased, a “merge bubble” is shown so that you can immediately see the work in each individual pull request.

Taken from Pull Requests with Rebase

like image 119
rickvdbosch Avatar answered Sep 22 '22 23:09

rickvdbosch


Semi-linear merge just adds a rebase to get your branch up to date before completing the merge. If you are PR'ing my-branch into target-branch, it is identical to the following commands:

git fetch git checkout my-branch git rebase origin/target-branch git branch -D target-branch # just in case you have an old version of it locally git checkout target-branch git merge --no-ff my-branch 

Some Pros and Cons are as follows:

Pros:

  1. The rebase first makes each merge cleaner and easier to trace visually. It also puts all of the changes into the commits themselves, rather than having to track down undesirable side effects in a merge commit, which is usually difficult. Note it's still recommended that developers do a rebase themselves prior to creating their PR, so they can witness any changes that are occurring at that time, and also run their unit tests against the latest version to make sure nothing funky happened. (This is akin to testing a merge commit and running tests before you create a PR, just to make sure the regular merge is still going to work as intended.)
  2. The merge (with --no-ff) forces a merge commit, and this is helpful because each PR contains the list of commits associated with just that PR, enabling you to view the first-parent history which shows all merges into the branch, and easily compare them. Another benefit of forcing the merge commit is that it's easy to revert an entire PR by simply reverting the merge commit, rather than individually reverting every commit that was in the original PR.

Cons:

  • There are some scenarios where you just don't want to use semi-linear merge. A good example is if your source branch has new merge commits in it that you want to retain. In Git Flow, when you merge release into master, or master back into develop you need to retain any of the merge commits from PRs on those branches. The rebase portion of semi-linear merge will rewrite those merge commits, and not only will the "bubbles" be popped, but worse, the commit IDs will be rewritten. This means you won't know for sure if everything in master is currently in develop. There could be IDs that are missing, despite the code being identical. As a rule of thumb, simply don't do a semi-linear merge if the source branch contains new merge commits.
  • After a semi-linear merge, when deleting your local branches you might have to use git branch -D my-branch (instead of lowercase -d) because the commit IDs may have changed. This is barely an inconvenience unless you generally don't remove your local branches right away; if you wait you'll need to confirm that you can really delete it.
  • If your workflow is for developers to rebase onto the target branch before creating their PR, having this option available might make them lazy, since they know it's going to do it for them. Most of the time it isn't a problem, but every once in a while both an automatic merge or rebase will break something, and it's better that they get used to rebasing first to detect it prior to PR completion. Otherwise, in this (admittedly rare) scenario the conflict is automatically resolved and something breaks in your integration branch.
  • If you use signed commits, if a rebase is needed during semi-linear merge the signatures would not be retained (because the commits are re-written). Depending on why you are signing your commits, this may not be an acceptable choice.

Side Note: other tools provide this feature as well:

  • Bitbucket offers the identical merge strategy, and calls it, appropriately, "Rebase, merge".
  • GitLab has used to have a setting for forcing a "merge commit with semi-linear history" however, at the time of this writing AFAIK it is was just a gate on the MR. (Note GitLab calls Pull Requests "Merge Requests". They are the same thing.) With this setting on you have had to rebase it yourself first (which you can do in the UI) and then you complete the MR. Basically it's 2 button clicks instead of 1. Update: This may no longer be possible. Now GitLab has an option for fast-forward only, but I don't know that you can require the check that the branch is up to date and still do a --no-ff merge.
  • GitHub does not support this yet, though people have been requesting it since 2017.

Additional Note: I can't find this documented anywhere, but I have tested and confirmed, that when completing a PR in Azure DevOps, if you choose either "Rebase and fast-forward" or "Semi-linear merge", your PR source branch is re-written before the PR is completed. Normally you would tick the box to delete your source branch after merging and wouldn't care about this, but if you elect to leave that setting unchecked, then it is important to realize your remote branch will appear as "(forced update)" at your next local fetch, if a rebase was required. This could be a Pro or a Con depending on your use case; I would lean towards preferring this most of the time.

Regarding the other tools, with this strategy GitLab forces you to update your branch with a button click, and Bitbucket specifically does not modify the PR branch in its equivalent "Rebase, merge" strategy.

like image 38
TTT Avatar answered Sep 23 '22 23:09

TTT