Merge and Rebase

8 min

Table of contents


1 — Bringing two branches together: the need

You have worked on a feature branch, the code is ready. You now need to reintegrate it into main. Git offers two mechanisms for that: the merge and the rebase.

Both reach the same goal — reunite the work — but with a different history shape. That is the whole point of this lesson.

MechanismIdea in one sentence
MergeYou create a commit that joins the two branches, keeping their history as it is.
RebaseYou replay the commits of one branch on top of another, as if you had started later.

Before any integration, you make sure you have the latest version:

bash
git switch main
git pull origin main

↑ Back to top


2 — The merge

The git merge command reunites one branch into another. There are two cases.

Case 1 — Fast-forward merge: if main has not moved since the branch was created, Git simply advances the pointer. No merge commit is created.

Case 2 — Three-way merge: if main has received new commits in the meantime, Git creates a merge commit that has two parents.

bash
# Switch to the target branch, then merge
git switch main
git merge feature/panier

# Force a merge commit even if a fast-forward is possible
git merge --no-ff feature/panier
OptionEffect
git merge featureMerge (fast-forward if possible)
git merge --no-ff featureAlways create a merge commit (traces the branch)
git merge --abortCancel a merge that is stuck on a conflict

Merge preserves the real history: you see when and how the branches came together. It is honest, but the history can become bushy with many merge commits.

🔧 Mini-exercise — You want to merge feature/panier into main while forcing the creation of a merge commit, even if a fast-forward would be possible. Write the command.

✅ See a solution

git merge --no-ff feature/panier--no-ff keeps an explicit trace of the merged branch.

↑ Back to top


3 — The rebase

git rebase moves the commits of your branch to replay them on top of the tip of another branch. Result: a linear history, as if you had started your work after the latest commits of main.

Before the rebase:

After git rebase main (commits B and C are replayed after D):

bash
# On the feature branch, replay on top of main
git switch feature/panier
git rebase main

# Then a clean fast-forward merge into main
git switch main
git merge feature/panier
Advantage of rebasePrecaution
Linear and readable historyRewrites the commits (new SHAs)
No parasitic merge commitsNever rebase a branch already pushed and shared
Ideal before a pull requestConflicts to settle commit by commit

Golden rule of rebase: never rebase commits already published and used by others. You rewrite history, which would break their repositories. Rebase is for your unshared local work.

🔧 Mini-exercise — You are on your feature/panier branch. Write the command to replay your commits on top of the tip of main (linear history).

✅ See a solution

git rebase main (while you are on feature/panier).

↑ Back to top


4 — Resolve conflicts

A conflict occurs when Git cannot decide automatically: two branches have modified the same line of the same file. Git stops and asks you to decide.

Git inserts conflict markers into the file:

text
<<<<<<< HEAD
prix = 10   # main version
=======
prix = 12   # feature version
>>>>>>> feature/panier

Resolution step by step:

  1. Open the file and choose (or combine) the right version.
  2. Delete the <<<<<<<, =======, >>>>>>> markers.
  3. Mark the file as resolved with git add.
  4. Finish the operation.
bash
# See the files in conflict
git status

# After manual editing
git add fichier-en-conflit.py

# Finish a merge
git commit

# Finish a rebase
git rebase --continue

# In case of panic: cancel everything
git merge --abort      # or: git rebase --abort
HelperUsage
git statusList the files in conflict
git diffSee the conflicting differences
git mergetoolLaunch a graphical resolution tool
VS CodeAccept Current / Incoming / Both buttons

A conflict is not an error: Git is honestly telling you “I do not know which one to keep, it is your decision”. Staying calm and reading the markers is enough in 99 % of cases.

🔧 Mini-exercise — You have edited the file app.py to resolve a conflict that occurred during a rebase. Which two commands finish the operation?

✅ See a solution
bash
git add app.py
git rebase --continue

(For a merge, it would be git add app.py then git commit.)

↑ Back to top


5 — Merge or rebase: which to choose?

Both reunite the work, but they produce a different history. The choice is often a team convention.

AspectMergeRebase
HistoryFaithful, branchedLinear, clean
Merge commitYes (if not fast-forward)No
Rewrites historyNoYes (new SHAs)
Safe on a shared branchYesNo
Readability of logDenserClearer

The most common recommended practice:

  • Rebase your local branch onto main before opening a pull request → clean history.
  • Merge the pull request into main → a clear trace of the integration.
bash
# 1. Clean your local branch before the PR
git switch feature/x
git rebase main

# 2. Once the PR is approved, GitHub does the merge

Mnemonic: “Rebase in private, merge in public.” You rebase what is yours, you merge what is shared.

↑ Back to top


6 — Quiz — Merge and rebase

Question 1: What does git merge feature from main do when main also has new commits?

a) It deletes the feature branch

b) It creates a merge commit with two parents

c) It erases the history

d) It always refuses to merge

See the solution

Answer: b) — This is a three-way merge: Git creates a merge commit that reunites the two histories.


Question 2: What is the main effect of git rebase main?

a) Replay the branch commits on top of main for a linear history

b) Clone the repository

c) Delete main

d) Create a remote backup

See the solution

Answer: a) — Rebase moves and replays your commits on top of main, producing a linear history.


Question 3: Why must you not rebase a branch already pushed and shared?

a) Because GitHub forbids it

b) Because it rewrites the commits and breaks other people's repositories

c) Because rebase is slower

d) Because it erases main

See the solution

Answer: b) — Rebase creates new SHAs. If others already have those commits, their history becomes inconsistent.


Question 4: What do the <<<<<<<, =======, >>>>>>> markers represent?

a) Code comments

b) A Python syntax error

c) The zones of a conflict to resolve by hand

d) The end of a file

See the solution

Answer: c) — These are conflict markers: above, the current version (HEAD); below, the incoming version. You choose and you delete them.


Question 5: How do you cleanly cancel a merge blocked by conflicts?

a) git delete

b) git merge --abort

c) git reset --cloud

d) Delete the .git folder

See the solution

Answer: b)git merge --abort (or git rebase --abort) returns the repository to its state before the operation.

↑ Back to top


7 — Practice — Resolve a merge conflict

Instructions

Two branches modify the same line of a file config.txt. Reproduce the conflict, then resolve it by keeping both pieces of information combined.

  1. On main, the file contains port = 8080.
  2. A feature/ssl branch changes this line to port = 443.
  3. Meanwhile, main changes the same line to port = 9090.
  4. Merge feature/ssl into main, resolve the conflict by keeping port = 443 (HTTPS), then finish.

Correction

bash
# Preparation: create the conflict
echo "port = 8080" > config.txt
git add config.txt
git commit -m "Initial config"

git switch -c feature/ssl
echo "port = 443" > config.txt
git commit -am "Switch to HTTPS (port 443)"

git switch main
echo "port = 9090" > config.txt
git commit -am "Change port to 9090"

# Merge attempt → conflict
git merge feature/ssl

Git then displays:

text
Auto-merging config.txt
CONFLICT (content): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.

The file config.txt contains:

text
<<<<<<< HEAD
port = 9090
=======
port = 443
>>>>>>> feature/ssl

You edit to keep only the right value:

bash
echo "port = 443" > config.txt   # you decide in favor of HTTPS

git add config.txt
git commit -m "Merge feature/ssl: keep port 443"

Expected result:

CheckCommandOutput
Conflict resolvedgit status“nothing to commit, working tree clean”
Final contentcat config.txtport = 443
Merge commitgit log --oneline -1“Merge feature/ssl: keep port 443”

Tip: if you make a mistake in the middle of a conflict, git merge --abort returns your repository intact. No risk in experimenting.

↑ Back to top


8 — Summary

Key takeaways

  1. Merge and rebase reunite two branches, but produce a different history.
  2. Merge preserves the real history; it creates a two-parent merge commit (except fast-forward).
  3. Rebase replays the commits for a linear and clean history.
  4. Golden rule: rebase in private, merge in public — never rebase shared code.
  5. A conflict appears when the same line is modified on both sides: you edit, you add, you finish.
  6. Good practice: rebase your branch before the PR, then merge the PR into main.

What's next

You know how to integrate the code technically. Lesson 03 — Pull requests shows how to have this work reviewed before integrating it, at the heart of GitHub collaboration.

↑ Back to top


All rights reserved. Any reproduction, distribution, use or adaptation of this course, in whole or in part, is strictly prohibited without the prior written authorization of Dr. Haythem REHOUMA.

Course created by Dr. Haythem REHOUMA — Development and Deployment of Data Solutions