Why Branch Merging is Necessary?

Imagine you and a colleague are developing a project: you’re responsible for the “user login feature,” and your colleague is working on the “shopping cart feature.” To avoid interfering with each other, you can create separate branches in Git for independent development. Once completed, you merge your respective work back into the main project (typically the master branch). Merging branches is like integrating the “achievements” of both individuals to keep the project moving forward.

Fast-forward Merge: The Simplest “Fast-forward” Merge

What is Fast-forward?

When you create a new branch (e.g., feature/login) from the main branch (e.g., master) and complete your modifications on the new branch, the main branch has no new commits during this period. When merging the new branch into the main branch, Git will directly “fast-forward” the main branch’s pointer to the latest commit of the new branch. It’s like the timeline extending linearly without creating a new merge record.

Example:
1. Initial state: The master branch has only 1 commit (assumed to be the base code).
2. Create and switch to the feature/login branch, modify the code, and commit (the master branch remains unchanged).
3. Switch back to the master branch and execute git merge feature/login. Git detects that the histories of master and feature/login are “linear” (no divergence in master before feature/login), so it moves the master pointer directly to the latest commit of feature/login.

Characteristics of Fast-forward:

  • No new commit: The feature/login commit is directly “attached” to the main branch history, with no additional “merge commit.”
  • Simple operation: No conflict resolution is needed (since branches are not diverged), and the merge completes directly.

Ordinary Merge: “Divergent” Merge with a New Commit

What is Ordinary Merge?

If new code is committed to the master branch (e.g., fixing a bug) while the feature/login branch is being developed, the histories of master and feature/login will diverge. During merging, Git creates a new merge commit, “gluing” the histories of the two branches together. This new commit includes changes from both branches.

Example:
1. Initial state: The master branch has commit A (base code).
2. Create the feature/login branch, modify code, and commit (now master is still A).
3. Switch back to master, then commit a new change (e.g., commit B).
4. Switch back to feature/login, modify code, and commit (now master has A and B, feature/login has A and C).
5. Switch back to master and execute git merge feature/login. Git creates a new merge commit D, which includes the contents of A, B, and C. The history of master now becomes A→B→D.

Characteristics of Ordinary Merge:

  • New commit created: The main branch will have an additional “merge commit” (labeled Merge branch 'feature/login').
  • Conflict resolution may be required: If both branches modify the same line of the same file, Git cannot merge automatically and will prompt a “conflict,” requiring manual modification.

Step-by-Step: How to Implement Both Merge Types?

Prerequisite: Create a Repository and Base Branch

First, initialize a Git repository and create the base master branch:

# Initialize the repository (if not already done)
mkdir my_project && cd my_project
git init

# Create an initial file and commit to master
echo "Initial code" > README.md
git add README.md
git commit -m "Initial commit"

Scenario 1: Fast-forward Merge (Branches Not Diverged)

This is the simplest merge method, suitable for scenarios where branches are developed independently before merging.

Step 1: Create and Develop the Feature Branch

# Create and switch to the feature/login branch
git checkout -b feature/login

# Modify code (e.g., add login functionality)
echo "Login page" >> README.md
git add README.md
git commit -m "Add login page"

At this point, the master branch remains on the initial commit, while feature/login has 1 new commit.

Step 2: Merge to master (Fast-forward)

# Switch back to the master branch
git checkout master

# Merge feature/login into master (no divergence, so Fast-forward is triggered)
git merge feature/login

After running git log, you’ll notice that master’s commits directly include the contents of feature/login—no new merge commit is created (Fast-forward takes effect).

Scenario 2: Ordinary Merge (Branches Diverged)

This is a more common scenario in collaborative development, suitable for merging after parallel development.

Step 1: Add New Commits to master (Simulate Others’ Modifications)

# Switch back to master and modify the file
git checkout master
echo "Fix bug in homepage" >> README.md
git add README.md
git commit -m "Fix homepage bug"

Now, master has 2 commits: Initial commit → Fix homepage bug.

Step 2: Continue Development on the Feature Branch

# Switch back to feature/login to continue development
git checkout feature/login
echo "Add user profile" >> README.md
git add README.md
git commit -m "Add user profile"

At this point, feature/login has 2 commits: Add login → Add profile; master has 2 commits: Initial → Fix bug, and the branches have diverged.

Step 3: Merge to master (Ordinary Merge)

# Switch back to master and merge feature/login
git checkout master
git merge feature/login

Git will automatically create a new merge commit (labeled Merge branch 'feature/login'). If there are no conflicts, the merge completes; if conflicts exist, resolve them manually before committing.

Summary

Merge Type Occurrence Condition Merge Result Command Characteristic
Fast-forward Main branch has no new commits; linear branch extension Main branch pointer fast-forwards, no new commit git merge automatically performs fast-forward
Ordinary Merge Main branch has new commits; branch divergence occurs Generates a new merge commit, with a diverged history git merge requires conflict resolution or manual confirmation

Key Points:

  • Fast-forward is the “ideal state,” suitable for independent development merges with simple operations.
  • Ordinary merge is the “real-world state,” handling parallel development, with attention to conflict resolution.
  • Both methods use the git merge [branch-name] command. Git automatically selects the merge type based on branch history.

With these two merge methods, you can flexibly integrate code from different branches and keep the project progressing smoothly~

Xiaoye