DevOpsLesson
DevOpsLesson

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Stay Updated

Get notified about new tutorials and features.

Tutorials

  • What is DevOps?
  • Docker Tutorial
  • Terraform Tutorial
  • CI/CD Pipeline
  • All Tutorials

Roadmaps

  • DevOps Engineer
  • Cloud Engineer
  • SRE Path
  • All Roadmaps

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 DevOpsLesson. All rights reserved.

DOCKERKUBERNETESTERRAFORMAWSCI/CDLINUXGITDEVOPS ROADMAPCLOUD ROADMAPSRE ROADMAPGIT CHEATSHEETDOCKER CHEATSHEETK8S CHEATSHEETTF CHEATSHEETLINUX CHEATSHEETDOCKERFILE LINTERYAML VALIDATORCRON PARSERREGEX TESTER

Git Tutorial

Introduction to Git
Installing Git
Git Basics
Git Branching
Git Merging
Git Rebasing
Git Remote
Git Stash
Undoing Changes in Git
Git Tagging
GitHub Workflow with Git
Advanced Git
Git Hooks
Git Workflows
Git Aliases and Configuration
Git Submodules
Git Commit Messages

Git Merging

PreviousPrev
Next

Learn fast-forward merges, three-way merges, merge conflicts, and why teams sometimes use git merge --no-ff.

What Merging Does

Merging combines changes from one branch into another. It is how feature work eventually becomes part of main or another shared branch.

A common example is merging feature/login into main after the feature is complete and reviewed.

git switch main
git merge feature/login

Git tries to combine history automatically. When histories fit together cleanly, merging is easy. When the same lines changed in different ways, you may get a conflict that needs manual resolution.

Fast-Forward Merge

A fast-forward merge happens when the target branch has not moved since the feature branch was created. Git can simply move the branch pointer forward.

Imagine this sequence:

  • main at commit A
  • create feature/docs
  • add commits B and C on feature/docs
  • main still points at A

Merging can look like this:

git switch main
git merge feature/docs

Git may respond with a fast-forward update because there is no need to create a separate merge commit.

Why It Happens

The histories form a straight line. main can just “catch up” to the feature branch.

Benefits:

  • simple history
  • fewer merge commits
  • easy to understand for small projects

Three-Way Merge

A three-way merge happens when both branches moved forward independently.

For example:

  • main has commit D
  • feature/login has commits B and C
  • both branches share an earlier common ancestor A

Now Git must combine two lines of development. It creates a new merge commit that has two parents.

git switch main
git merge feature/login

This is called a three-way merge because Git compares:

  • the common ancestor
  • the current branch tip
  • the branch being merged

When Teams Use --no-ff

By default, Git may fast-forward when possible. Some teams prefer to always keep a visible merge commit for feature branches.

Use:

git switch main
git merge --no-ff feature/login

This forces a merge commit even if a fast-forward would work.

Why Use --no-ff?

It can make history easier to read because the branch integration remains visible as a single merge event. That can help when reviewing past work or reverting an entire feature.

Tip: Teams that rely heavily on pull requests often like explicit merge commits because they preserve the story of how a feature entered the main branch.

What a Merge Conflict Is

A merge conflict happens when Git cannot decide how to combine changes automatically.

This usually occurs when:

  • both branches changed the same lines
  • one branch deleted a file the other edited
  • file renames and edits overlap in confusing ways

Git will pause the merge and ask you to resolve the conflict manually.

Step-by-Step Conflict Resolution

Assume both branches edited the same line in app.conf.

Start the merge:

git switch main
git merge feature/config-update

Git may report a conflict. Check the status:

git status

Open the conflicted file. You may see markers like this:

<<<<<<< HEAD
port=8080
=======
port=9090
>>>>>>> feature/config-update

What the Markers Mean

  • <<<<<<< HEAD shows the version from the current branch
  • ======= separates the two versions
  • >>>>>>> feature/config-update shows the incoming version

Resolve the File

Choose the correct final content, for example:

port=9090

Or combine both ideas if needed. Then stage the resolved file:

git add app.conf

Complete the merge:

git commit

Git usually opens your editor with a default merge message.

Verifying the Merge

After merging, inspect the history:

git log --oneline --graph --decorate -10

This helps you confirm whether Git created a fast-forward result or a merge commit.

You can also test the application after resolving conflicts:

npm test

Or if it is a shell-based project:

./run-checks.sh

Validation matters because a “clean” merge is not automatically a correct merge.

Abort a Problematic Merge

If you start a merge and realize you are not ready, you can often stop and return to the pre-merge state:

git merge --abort

This is helpful if you accidentally merged the wrong branch or want to review changes before trying again.

Note: git merge --abort works best before you make extra manual changes beyond the merge conflict state.

Merge vs Rebase at a High Level

Merging preserves the true branch structure. Rebasing rewrites commits onto a new base to create a straighter history. Both are useful, but merge is often the safer beginner choice because it does not rewrite existing commits.

What You Should Remember

Merging is how Git combines branches. A fast-forward merge simply moves a pointer. A three-way merge creates a merge commit when histories diverged. Conflicts happen when Git cannot safely decide between competing changes, and resolving them means editing the affected files, staging the results, and finishing the merge.

Use --no-ff when your team wants feature integrations to remain clearly visible in history.

Test Your Understanding

Let's see how well you understood the concepts! These exercises will help reinforce what you just learned.

Exercise 1: Recognizing a fast-forward

Scenario: main is still at commit A, while feature/docs moved from A to B to C and nothing new was added to main.

Question: What kind of merge should Git usually be able to perform when you merge feature/docs into main?

Exercise

Exercise 1: Recognizing a fast-forward

Identify the merge type when the target branch has not moved since branching.

Exercise 2: Preserving feature history

Question: Why might a team choose git merge --no-ff feature/login even when a fast-forward merge is possible?

Exercise

Exercise 2: Preserving feature history

Pick the reason teams force a merge commit with --no-ff.

Exercise 3: Finishing conflict resolution

Scenario: A merge stopped with conflict markers in app.conf. You edited the file so the final content is correct.

Question: According to the tutorial, what should you do next to complete the merge workflow?

Exercise

Exercise 3: Finishing conflict resolution

Choose the next step after manually resolving merge conflict markers.

PreviousPrev
Next

Continue Learning

Installing Git

Install Git on macOS, Linux, and Windows, then configure your identity, editor, and default branch for a clean first setup.

10 min·Easy

Git Basics

Learn the everyday Git workflow with init, clone, status, add, commit, log, and diff using practical beginner-friendly examples.

15 min·Easy

Git Branching

Understand Git branches, HEAD, switching branches, deleting branches, and detached HEAD with practical beginner examples.

18 min·Easy

Explore Related Topics

CI

CI/CD Tutorials

Trigger automated pipelines from Git workflows

Li

Linux Tutorials

Use Git effectively on the Linux command line

On This Page

What Merging DoesFast-Forward MergeWhy It HappensThree-Way MergeWhen Teams Use `--no-ff`Why Use `--no-ff`?What a Merge Conflict IsStep-by-Step Conflict ResolutionWhat the Markers MeanResolve the FileVerifying the MergeAbort a Problematic MergeMerge vs Rebase at a High LevelWhat You Should RememberTest Your UnderstandingExercise 1: Recognizing a fast-forwardExercise 2: Preserving feature historyExercise 3: Finishing conflict resolution