Appendix: Difference between git merge and git rebase

4 min

Context

In this example, we have a repository with a main branch main containing a base file fichier1.txt and a first initial commit. From main, we create two branches, branche1 and branche2, each intended to test rebase and merge respectively. Then two extra working branches are created, branche-rebase from branche1 and branche-merge from branche2, to add modifications there.

Initial history

The project starts with a repository containing a single commit on main, corresponding to the creation of the file fichier1.txt:

plaintext
(main)
A               # Initial commit with fichier1.txt

In commit A, we added the file fichier1.txt with initial content.

Then two new branches are created from main:

  1. branche1: intended to host branche-rebase to test git rebase.
  2. branche2: intended to host branche-merge to test git merge.

Work in each working branch

In each working branch (branche-rebase and branche-merge), we make three distinct commits. Here are the commits in detail for each branch:

plaintext
(main)
A

(branche-rebase)
       \
        D---E---F   # Commits added on branche-rebase

(branche-merge)
       \
        G---H---I   # Commits added on branche-merge
  1. Commits on branche-rebase:

    • Commit D: Creation of the file fichier-2-rebase.txt with the initial content "Modification 1 dans branche-rebase".
    • Commit E: Addition of "Modification 2 dans branche-rebase" in the same file fichier-2-rebase.txt.
    • Commit F: Addition of "Modification 3 dans branche-rebase" in the same file fichier-2-rebase.txt.
  2. Commits on branche-merge:

    • Commit G: Creation of the file fichier-2-merge.txt with the initial content "Modification 1 dans branche-merge".
    • Commit H: Addition of "Modification 2 dans branche-merge" in the same file fichier-2-merge.txt.
    • Commit I: Addition of "Modification 3 dans branche-merge" in the same file fichier-2-merge.txt.

These commits add identical content, but in different files (fichier-2-rebase.txt and fichier-2-merge.txt), to allow a clear comparison between merge and rebase.


Step 1: Merge of branche-merge into branche2 with git merge

To integrate the modifications of branche-merge into branche2, we use the git merge command on branche2. This operation creates a merge commit that keeps a complete history and includes the working-branch commits without reordering them.

The history after the merge:

plaintext
(branche2)
A-------J        # J is the merge commit
 \       |
  \      |
   G---H---I     # branche-merge keeps its distinct history
  • Explanation of the commits:
    • Commit J: Merge commit that combines the content of branche2 with the modifications of branche-merge (G, H, I) without moving them or changing their order.
  • Observation: With git merge, the history shows a "junction point" that visually indicates where branche-merge was merged into branche2. This keeps a complete and distinct history for each branch, which is often useful in collaborative projects.

Step 2: Integration of branche-rebase into branche1 with git rebase

To integrate the modifications of branche-rebase into branche1, we use the git rebase command. Unlike merge, rebase repositions the commits (D, E, F) of branche-rebase as if they had been created after the last commit of branche1 (A).

The history after the rebase:

plaintext
(branche1)
A---D'---E'---F'   # Commits of branche-rebase reapplied at the end of branche1
  • Explanation of the commits:
    • Commits D', E', F': Replayed commits of branche-rebase applied linearly after A on branche1.
  • Observation: With git rebase, the commits of branche-rebase are reorganized to form a linear history without a "junction point", as if they had been added directly after the initial commit A. This simplifies the history by making it cleaner, but it can hide the path of the original working branches.

Final comparison

The differences observed in the Git logs make it easier to understand the specific uses of merge and rebase.

  • git merge:

    • Effect: Keeps a complete history with a merge commit that marks the junction of the branches.
    • Benefit: Ideal for following a complete history in collaborative projects, because each junction is visible.
    • Drawback: The history can become complex with many junctions, especially in projects with several branches.
  • git rebase:

    • Effect: Reorganizes the commits to place them linearly at the end of the main branch, without creating a merge commit.
    • Benefit: Ideal for a linear, clean history, by minimizing junctions. This is often preferred in small projects or to clean up the history before sharing it.
    • Drawback: Can hide the path of the working branches, which can be a problem if several people work on the same branches.

Summary

CommandHistoryIdeal use case
git mergeComplete history with a junction pointCollaborative projects with several branches
git rebaseLinear history without junction pointsCleaning up the history before a shared merge

In summary:

plaintext
git merge   ->  Complete history with a merge commit
git rebase  ->  Linear history without a merge commit

This guide lets you understand and visualize the differences between git merge and git rebase, and choose the method best suited to your project context.