Git Branches and Merging: Parallel Development Without Chaos

Git Branches and Merging: Parallel Development Without Chaos

8 min read
10 views

Support Free C++ Education

Help us create more high-quality C++ learning content. Your support enables us to build more interactive projects, write comprehensive tutorials, and keep all content free for everyone.

Become a Patron

Why Branches Matter

Imagine you're building a C++ game. The main game loop works perfectly. Now you want to:

  1. Add a new physics system
  2. Fix a bug in the audio system
  3. Experiment with a new rendering technique

Without branches, you'd have to do these one at a time. Work on physics until it's done, then work on audio, then rendering. If the physics work takes a week, the audio bug stays unfixed.

With branches, you can work on all three simultaneously. Each change lives in its own branch, isolated from the others. When something is ready, you merge it into the main codebase.

Branches let you experiment without risk. Break everything in your experiment branch; the main code is untouched.

What is a Branch?

A branch is a pointer to a commit. That's all.

When you create a branch, Git doesn't copy your code. It just creates a new pointer. This makes branches incredibly lightweight, practically free to create.

main:     A ← B ← C
                   ↑
feature:           D ← E

In this diagram:

  • main points to commit C
  • feature points to commit E
  • E's parent is D, D's parent is C
  • The branches share history up to C, then diverge

Creating Branches

See what branch you're on:

git branch

Output shows branches with an asterisk marking the current one:

* main

Create a new branch:

git branch feature/physics

This creates the branch but doesn't switch to it. You're still on main.

See all branches:

git branch
  feature/physics
* main

Switching Branches

Switch to the new branch:

git checkout feature/physics

Or use the newer command:

git switch feature/physics

Verify you switched:

git branch
* feature/physics
  main

Create and Switch in One Command

The common case is creating a branch and immediately switching to it:

git checkout -b feature/audio

# Or with switch
git switch -c feature/audio

Working on a Branch

When you're on a branch, commits are added to that branch only:

# On feature/physics branch
# Make changes to physics code
git add physics.cpp
git commit -m "Implement basic collision detection"

# Make more changes
git add physics.cpp
git commit -m "Add gravity simulation"

These commits exist only on feature/physics. The main branch is unchanged.

Switch back to main:

git checkout main

Your physics changes disappear from the working directory. They're safely stored in the feature/physics branch. Switch back and they reappear:

git checkout feature/physics

Branch Naming Conventions

Use descriptive names that indicate what the branch is for:

feature/player-movement
feature/inventory-system
bugfix/crash-on-startup
bugfix/memory-leak-particles
experiment/new-rendering
refactor/code-cleanup

Common prefixes:

  • feature/ - New functionality
  • bugfix/ or fix/ - Bug repairs
  • experiment/ - Trying something that might not work
  • refactor/ - Code reorganization without behavior change
  • docs/ - Documentation updates

Avoid spaces and special characters. Use hyphens or underscores.

Merging Branches

When your feature is complete, merge it into main:

# First, switch to the branch you want to merge INTO
git checkout main

# Then merge the feature branch
git merge feature/physics

Git combines the changes from feature/physics into main.

Fast-Forward Merge

If main hasn't changed since you created the branch, Git does a "fast-forward" merge. It simply moves the main pointer forward:

Before:

main: A ← B ← C
feature:      D ← E

After git merge feature:

main:    A ← B ← C ← D ← E
feature:              ↑

Both main and feature now point to E. No new commit is needed.

Three-Way Merge

If main has changed while you worked on your branch, Git creates a merge commit:

Before:

main:    A ← B ← C ← F
feature:      ↑
              D ← E

After merge:

main:    A ← B ← C ← F ← G (merge commit)
                 ↑       ↑
feature:         D ← E ──┘

The merge commit G has two parents: F (from main) and E (from feature). It combines both lines of development.

Handling Merge Conflicts

Sometimes Git can't automatically merge. This happens when both branches changed the same lines of code:

git merge feature/physics
Auto-merging game.cpp
CONFLICT (content): Merge conflict in game.cpp
Automatic merge failed; fix conflicts and then commit the result.

Check status to see conflicted files:

git status
Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   game.cpp

Resolving Conflicts

Open the conflicted file. Git marks the conflicts:

void update() {
<<<<<<< HEAD
    // This is from main branch
    physics.update(deltaTime);
    audio.update();
=======
    // This is from feature/physics
    physics.stepSimulation(deltaTime);
    collisions.resolve();
>>>>>>> feature/physics
}

The markers mean:

  • <<<<<<< HEAD to =======: Changes from current branch (main)
  • ======= to >>>>>>> feature/physics: Changes from merging branch

You must decide what the final code should be. Options:

  • Keep one version
  • Keep both versions
  • Write something new that combines both

Edit the file to remove the conflict markers and create the correct code:

void update() {
    physics.stepSimulation(deltaTime);
    collisions.resolve();
    audio.update();
}

Mark the conflict as resolved:

git add game.cpp

Complete the merge:

git commit -m "Merge feature/physics into main"

If you open the file in an editor, Git may have opened an editor for the commit message. Save and close to complete.

Aborting a Merge

If conflicts are overwhelming and you want to start over:

git merge --abort

This returns you to the state before the merge attempt.

Deleting Branches

After merging, you might want to delete the feature branch:

git branch -d feature/physics

The -d flag only deletes if the branch has been merged. To force delete an unmerged branch:

git branch -D experiment/failed-idea

Visualizing Branches

See branches graphically:

git log --oneline --graph --all

Example output:

*   a1b2c3d (HEAD -> main) Merge feature/audio
|\
| * d4e5f6g Add volume controls
| * a7b8c9d Implement audio system
|/
* f1g2h3i Add player movement
* j4k5l6m Initial commit

This shows the branch diverging and merging back.

Branch Workflow Example

Here's a realistic workflow:

# Start on main with latest code
git checkout main
git pull  # (if working with remotes)

# Create a feature branch
git checkout -b feature/particle-effects

# Work on the feature
# ... edit files ...
git add .
git commit -m "Add basic particle emitter"

# ... more work ...
git add .
git commit -m "Implement smoke particles"

# ... more work ...
git add .
git commit -m "Add fire particle effects"

# Feature complete, merge into main
git checkout main
git merge feature/particle-effects

# Delete the feature branch
git branch -d feature/particle-effects

Working on Multiple Branches

You can have multiple branches active:

# Create several branches from main
git checkout main
git checkout -b feature/ui-redesign

git checkout main
git checkout -b bugfix/memory-leak

git checkout main
git checkout -b feature/multiplayer

Switch between them as needed:

git checkout feature/ui-redesign
# Work on UI...

git checkout bugfix/memory-leak
# Fix the bug...

git checkout feature/ui-redesign
# Back to UI work...

Each branch maintains its own state independently.

Stashing Changes

What if you're in the middle of work and need to switch branches? Uncommitted changes might conflict with the other branch.

Stash your changes temporarily:

git stash

This saves your uncommitted changes and reverts to a clean state. Now you can switch branches safely:

git checkout other-branch
# Do something
git checkout original-branch
git stash pop  # Restore your changes

View stashed changes:

git stash list

Best Practices

Keep Main Stable

The main branch should always work. Don't commit broken code directly to main. Use feature branches, verify everything works, then merge.

Branch Early and Often

Creating a branch costs nothing. If you're about to try something uncertain, create a branch first. You can always merge it later or delete it if the experiment fails.

Merge Frequently

Long-lived branches that diverge far from main become hard to merge. Merge main into your feature branch periodically to stay current:

git checkout feature/big-feature
git merge main

This keeps your branch up-to-date and makes the final merge into main easier.

Keep Branches Focused

One branch should do one thing. If you're implementing a feature and notice an unrelated bug, create a separate bugfix branch rather than mixing concerns.

Practice Exercise

  1. Create a new repository or use an existing one

  2. Create three branches:

    • feature/greetings - Add different greeting messages
    • feature/farewells - Add farewell messages
    • experiment/colors - Try adding color output
  3. Make commits on each branch

  4. Merge feature/greetings into main

  5. Merge feature/farewells into main (notice the merge commit)

  6. Try deleting experiment/colors without merging (use -D)

  7. Run git log --oneline --graph --all to see the history

What's Next

Branches shine when working with others or syncing code between computers. The next article covers remote repositories and GitHub.

Next article: Working with GitHub - Push your code to the cloud, collaborate with others, and contribute to open source.

With branches and remotes, you'll have the full Git toolkit for professional development.

Part of the Git Fundamentals series.

Understanding Commits | Working with GitHub

Support Free C++ Education

Help us create more high-quality C++ learning content. Your support enables us to build more interactive projects, write comprehensive tutorials, and keep all content free for everyone.

Become a Patron

About the Author

Imran Bajerai

Software engineer and C++ educator passionate about making programming accessible to beginners. With years of experience in software development and teaching, Imran creates practical, hands-on lessons that help students master C++ fundamentals.

Article Discussion

Share your thoughts and questions

💬

No comments yet. Be the first to share your thoughts!