Git offers different approaches to integrating changes from one branch into another. Two of the most common methods are merge and rebase. In this article, we’ll explore their differences, use cases, and impact on your development workflow.

Initial Scenario

Let’s start with a common development situation:

Where:

  • A, B, C represent commits on the master branch
  • D, E represent commits on the feature branch

Method 1: Git Merge

When we merge a feature branch into master, Git creates a new commit that combines the histories of both branches.

Result:

Effects of Merge:

  • Creates a new merge commit (M)
  • Preserves complete history
  • Maintains original timeline
  • Easy to revert
  • Can lead to a “messy” git graph

Method 2: Git Rebase

Rebasing rewrites the feature branch history by creating new commits on top of the target branch.

Result:

Effects of Rebase:

  • Rewrites commits D and E (becoming D’ and E’)
  • Creates linear history
  • Changes original commit timestamps
  • Cleaner git graph
  • More complex to revert

Impact on Pipeline and Workflow

Merge Advantages
  • ? Safe for public branches
  • ? Preserves complete history
  • ? No conflicts with other developers
  • ? Clear indication of where feature branches were integrated
Merge Disadvantages
  • ? Can lead to a cluttered git graph
  • ? Merge commits can “pollute” history
  • ? Can make it harder to understand project history
Rebase Advantages
  • ? Clean, linear history
  • ? Easier to understand
  • ? No additional merge commits
  • ? Makes following the project history simpler
Rebase Disadvantages
  • ? Dangerous for public branches
  • ? Can cause issues if others have cloned the repository
  • ? Conflict resolution can be more complex
  • ? Loss of context about when features were integrated

Best Practices

Use Merge When:
  1. Working on a public branch
  2. Feature branch history is important
  3. Collaborating with multiple developers on the same feature
  4. You want to preserve the context of when features were integrated
Use Rebase When:
  1. Working on a local, private branch
  2. You prefer a clean, linear history
  3. You want to ensure your feature branch is up-to-date
  4. You’re working alone on a feature
Important Note on Force Push

When using rebase on an already pushed branch, we’ll need to force push:

git push --force-with-lease

?? Warning: Use force push with caution as it rewrites history for other developers.

Code Examples in Practice

Merge Workflow
# Start feature branch
git checkout -b feature/new-feature master

# Make changes and commit
git add .
git commit -m "Add new feature"

# Later, merge back to master
git checkout master
git merge feature/new-feature
Rebase Workflow
# Start feature branch
git checkout -b feature/new-feature master

# Make changes and commit
git add .
git commit -m "Add new feature"

# Keep feature branch up to date
git checkout feature/new-feature
git rebase master

# When ready to merge
git checkout master
git merge feature/new-feature # Will be a fast-forward merge

A Practical Example with Real Commit History

Let’s look at a concrete example showing exactly what happens during merge and rebase operations.

# On master branch
$ git log --oneline
7890abc Fix navbar responsiveness    # C
456def2 Update user authentication   # B
123abcd Initial commit              # A

# On feature/auth branch
$ git log --oneline
ef98765 Add OAuth integration       # E
cd45678 Add login form             # D
456def2 Update user authentication  # B
123abcd Initial commit             # A

Visual representation:

Scenario 1: Merge Process
$ git checkout master
$ git merge feature/auth
Result after merge:
$ git log --oneline
9876543 Merge branch 'feature/auth' into master  # Merge commit (M)
7890abc Fix navbar responsiveness                # C
ef98765 Add OAuth integration                    # E
cd45678 Add login form                          # D
456def2 Update user authentication              # B
123abcd Initial commit                          # A
Visual representation:
Scenario 2: Rebase Process
$ git checkout feature/auth
$ git rebase master
During rebase:
# Git internally performs these steps:
1. Temporarily stores changes from D and E
2. Moves feature branch pointer to master's HEAD (7890abc)
3. Replays commits D and E one by one
Result after rebase:
$ git log --oneline
ab12345 Add OAuth integration       # E' (new hash)
de34567 Add login form             # D' (new hash)
7890abc Fix navbar responsiveness   # C
456def2 Update user authentication  # B
123abcd Initial commit             # A
Visual representation:
Detailed Analysis of Changes
Original Commits (Before Rebase):
# Commit D details
$ git show cd45678
commit cd45678...
Author: John Doe
Date:   Mon Feb 10 10:00:00 2025 +0100
    Add login form
    
    - Added login form component
    - Added form validation
    ...

# Commit E details
$ git show ef98765
commit ef98765...
Author: John Doe
Date:   Mon Feb 10 11:00:00 2025 +0100
    Add OAuth integration
    
    - Implemented OAuth2 flow
    - Added social login buttons
    ...
New Commits After Rebase (D’ and E’):
# New Commit D' details
$ git show de34567
commit de34567...
Author: John Doe
Date:   Mon Feb 11 14:30:00 2025 +0100  # Note the new timestamp
    Add login form
    
    - Added login form component
    - Added form validation
    ...

# New Commit E' details
$ git show ab12345
commit ab12345...
Author: John Doe
Date:   Mon Feb 11 14:30:01 2025 +0100  # Note the new timestamp
    Add OAuth integration
    
    - Implemented OAuth2 flow
    - Added social login buttons
    ...
Key Observations
  1. Commit Hash Changes:
    • Original feature commits: cd45678 and ef98765
    • New rebased commits: de34567 and ab12345
  2. Timestamp Changes:
    • Original commits: Feb 10, 2025
    • Rebased commits: Feb 11, 2025 (current rebase time)
  3. Content Changes:
    • The commit messages and changes remain the same
    • Only the metadata (commit hash, timestamp) changes
  4. Branch Structure:
    • Before: Branching history visible
    • After: Linear history

Common Commands to View These Changes

# View complete graph
$ git log --graph --oneline --all

# View detailed commit information
$ git show <commit-hash>

# View branch structure
$ git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
Conclusion

Both merge and rebase have their place in Git workflows. The choice between them depends on our specific needs:

  • Choose merge for maintaining history and working with public branches
  • Choose rebase for a clean, linear history and private feature development

Remember that these aren’t mutually exclusive – many teams use both approaches depending on the situation. The key is understanding the implications of each method and choosing the right tool for our specific scenario.

By Shabazz

Software Engineer, MCSD, Web developer & Angular specialist

Leave a Reply

Your email address will not be published. Required fields are marked *