I'm trying to understand how GitLab makes merge commit. Pure git has different behaviour and it's not so clear why merge commits are required in GitLab
Let's say we have empty repository and perform first commit named direct commit to branch
. Then we create a branch b-4
with two commits. Let's merge b-4
branch into main
.
Note: keep in mind we use Merge commit
method with squash option. Read more at Merge methods.
After merge is done we see the following history in GitLab web-interface (not a screenshot, sorry):
Merge branch 'b-4' into 'main' d08bf37f
Squashed commit ebc509c2
direct commit to branch 34b29e2b
I expect to see something like that in git tree when I run git log --graph --decorate
command:
* commit d08bf37ff7157d48354c001ac066a6a44aece33e (HEAD -> main, origin/main)
| Author: author_name <author_name@example.com>
| Date: Fri Jun 14 16:30:27 2024 +0300
|
| Merge branch 'b-4' into 'main'
|
| Squashed commit
|
| See merge request author_name/repo_name!1
|
* commit ebc509c25c945b63fbc3f387bb308a54b1006e90
| Author: author_name <author_name@example.com>
| Date: Fri Jun 14 16:30:27 2024 +0300
|
| Squashed commit
|
* commit 34b29e2b89d38439299feef0ac64b926ba9d5d38
Author: author_name <author_name@example.com>
Date: Fri Jun 14 16:29:09 2024 +0300
direct commit to branch
But actually I observe the following:
* commit d08bf37ff7157d48354c001ac066a6a44aece33e (HEAD -> main, origin/main)
|\ Merge: 34b29e2 ebc509c
| | Author: author_name <author_name@example.com>
| | Date: Fri Jun 14 16:30:27 2024 +0300
| |
| | Merge branch 'b-4' into 'main'
| |
| | Squashed commit
| |
| | See merge request author_name/repo_name!1
| |
| * commit ebc509c25c945b63fbc3f387bb308a54b1006e90
|/ Author: author_name <author_name@example.com>
| Date: Fri Jun 14 16:30:27 2024 +0300
|
| Squashed commit
|
* commit 34b29e2b89d38439299feef0ac64b926ba9d5d38
Author: author_name <author_name@example.com>
Date: Fri Jun 14 16:29:09 2024 +0300
direct commit to branch
Merge: 34b29e2 ebc509c
line?Article How does GitLab merge request with squash work under the hood? doesn't answer my question.
Creating a squash commit, and then another merge commit, barely makes sense, because the merge commit adds no informational value to the resulting graph. One possible way it does make sense though is for continuity with having the Merge Commit contain the MR number and branch names information, and presumably this is why GitLab offers this option.
In order for this to work, the merge commit, by definition, must have two parents. So the actual graph that you see in your repository is correct. I suspect the only reason you expected to see a linear graph is because the GitLab documentation is currently wrong. In this image the right most commit cannot be a merge commit:
I assume if someone notifies GitLab of the error they will fix it so that the resulting image would show the merge commit with two parents, E
and the squash commit. While they're fixing that, they might as well fix the sentence to clearly state this is the Merge commit option, combined with Squash commit.
Regarding how the squash and merge commit works behind the scenes, it's probably something like this:
# create a temp branch called feature-squash starting from main:
git switch -c feature-squash main
# Begin squash merge of the feature branch:
git merge feature --squash
# Complete squash merge of the feature branch
git commit -m "Squash feature branch into a single commit"
# Checkout main:
git switch main
# Force a merge commit on main for the squashed commit:
git merge feature-squash --no-ff -m "Force merge commit for Squash Merge"
Side Note: When squashing, you could choose the alternative method of Squash Merge, and then you simply get the single linear squashed commit, without the extra (unnecessary except maybe commit message meta-data) merge commit along with it. However, when you are not squashing and you have more than 1 commit, I personally recommend always forcing a merge commit even if fast-forward is possible, so that the entire history of that feature can be discerned from the commit history.