summaryrefslogtreecommitdiff
path: root/doc/user/project/merge_requests/methods/index.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/user/project/merge_requests/methods/index.md')
-rw-r--r--doc/user/project/merge_requests/methods/index.md130
1 files changed, 98 insertions, 32 deletions
diff --git a/doc/user/project/merge_requests/methods/index.md b/doc/user/project/merge_requests/methods/index.md
index e72c927198e..249a98f1779 100644
--- a/doc/user/project/merge_requests/methods/index.md
+++ b/doc/user/project/merge_requests/methods/index.md
@@ -10,47 +10,107 @@ type: reference, concepts
The merge method you select for your project determines how the changes in your
merge requests are merged into an existing branch.
+The examples on this page assume a `main` branch with commits A, C, and E, and a
+`feature` branch with commits B and D:
+
+```mermaid
+gitGraph
+ commit id: "A"
+ branch feature
+ commit id: "B"
+ commit id: "D"
+ checkout main
+ commit id: "C"
+ commit id: "E"
+```
+
## Configure a project's merge method
1. On the top bar, select **Main menu > Projects** and find your project.
1. On the left sidebar, select **Settings > Merge requests**.
-1. In the **Merge method** section, select your desired merge method.
+1. Select your desired **Merge method** from these options:
+ - Merge commit
+ - Merge commit with semi-linear history
+ - Fast-forward merge
+1. In **Squash commits when merging**, select the default behavior for handling commits:
+ - **Do not allow**: Squashing is never performed, and the user cannot change the behavior.
+ - **Allow**: Squashing is off by default, but the user can change the behavior.
+ - **Encourage**: Squashing is on by default, but the user can change the behavior.
+ - **Require**: Squashing is always performed, and the user cannot change the behavior.
1. Select **Save changes**.
## Merge commit
-This setting is the default. It always creates a separate merge commit,
-even when using [squash](../squash_and_merge.md). An example commit graph generated using this merge method:
+By default, GitLab creates a merge commit when a branch is merged into `main`.
+A separate merge commit is always created, regardless of whether or not commits
+are [squashed when merging](../squash_and_merge.md). This strategy can result
+in both a squash commit and a merge commit being added to your `main` branch.
+
+These diagrams show how the `feature` branch merges into `main` if you use the
+**Merge commit** strategy. They are equivalent to the command `git merge --no-ff <feature>`,
+and selecting `Merge commit` as the **Merge method** in the GitLab UI:
+
+The merge strategy:
```mermaid
+%%{init: { 'gitGraph': {'logLevel': 'debug', 'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'main'}} }%%
gitGraph
- commit id: "Init"
- branch mr-branch-1
- commit
- checkout main
- commit
- branch mr-branch-2
- commit
- checkout mr-branch-1
- commit
- checkout main
- branch squash-mr
- commit id: "Squashed commits"
- checkout main
- merge squash-mr
- merge mr-branch-1
- commit
- merge mr-branch-2
+ commit id: "A"
+ branch feature
+ commit id: "B"
+ commit id: "D"
+ checkout main
+ commit id: "C"
+ commit id: "E"
+ merge feature
+```
+
+After a feature branch is merged with the **Merge commit** method, your `main` branch
+looks like this:
+
+```mermaid
+%%{init: { 'gitGraph': {'logLevel': 'debug', 'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'main'}} }%%
+gitGraph
+ commit id: "A"
+ commit id: "C"
+ commit id: "E"
+ commit id: "squash commit"
+ commit id: "merge commit"
```
-- For regular merges, it is equivalent to the command `git merge --no-ff <source-branch>`.
-- For squash merges, it squashes all commits in the source branch before merging it normally. It performs actions similar to:
+In comparison, a **squash merge** constructs a squash commit, a virtual copy of all commits
+from the `feature` branch. The original commits (B and D) remain unchanged
+on the `feature` branch, and the squash commit is placed on the `main` branch:
+
+```mermaid
+%%{init: { 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'main'}} }%%
+gitGraph
+ commit id:"A"
+ branch feature
+ checkout main
+ commit id:"C"
+ checkout feature
+ commit id:"B"
+ commit id:"D"
+ checkout main
+ commit id:"E"
+ commit id:"squash commit" type: HIGHLIGHT
+```
+
+The squash merge graph is equivalent to these settings in the GitLab UI:
+
+- **Merge method**: Merge commit.
+- **Squash commits when merging** should be set to either:
+ - Require.
+ - Either Allow or Encourage, and squashing must be selected on the merge request.
+
+The squash merge graph is also equivalent to these commands:
```shell
- git checkout `git merge-base <source-branch> <target-branch>`
- git merge --squash <source-branch>
+ git checkout `git merge-base feature main`
+ git merge --squash <feature>
SOURCE_SHA=`git rev-parse HEAD`
- git checkout <target-branch>
+ git checkout <main>
git merge --no-ff $SOURCE_SHA
```
@@ -58,7 +118,8 @@ gitGraph
A merge commit is created for every merge, but the branch is only merged if
a fast-forward merge is possible. This ensures that if the merge request build
-succeeded, the target branch build also succeeds after the merge. An example commit graph generated using this merge method:
+succeeded, the target branch build also succeeds after the merge. An example
+commit graph generated using this merge method:
```mermaid
gitGraph
@@ -113,8 +174,8 @@ This method is equivalent to `git merge --ff <source-branch>` for regular merges
When the fast-forward merge
([`--ff-only`](https://git-scm.com/docs/git-merge#git-merge---ff-only)) setting
-is enabled, no merge commits are created and all merges are fast-forwarded,
-which means that merging is only allowed if the branch can be fast-forwarded.
+is enabled, no merge commits are created and all merges are fast-forwarded.
+Merging is only allowed if the branch can be fast-forwarded.
When a fast-forward merge is not possible, the user is given the option to rebase, see
[Rebasing in (semi-)linear merge methods](#rebasing-in-semi-linear-merge-methods).
@@ -136,11 +197,16 @@ In these merge methods, you can merge only when your source branch is up-to-date
- Fast-forward merge.
If a fast-forward merge is not possible but a conflict-free rebase is possible,
-GitLab offers you the [`/rebase` quick action](../../../../topics/git/git_rebase.md#rebase-from-the-gitlab-ui),
-and the ability to select **Rebase** from the user interface.
+GitLab provides:
+
+- The [`/rebase` quick action](../../../../topics/git/git_rebase.md#rebase-from-the-gitlab-ui).
+- The option to select **Rebase** in the user interface.
+
+You must rebase the source branch locally before a fast-forward merge if both
+conditions are true:
-If the target branch is ahead of the source branch and a conflict-free rebase is
-not possible, you must rebase the source branch locally before you can do a fast-forward merge.
+- The target branch is ahead of the source branch.
+- A conflict-free rebase is not possible.
![Fast forward merge rebase locally](../img/ff_merge_rebase_locally.png)