Git Branching and Merging: Build Parallel Work Without Chaos

In the first post, you learned the core commit loop. Now it is time to work in parallel. Branching is where Git starts to feel powerful, because you can experiment safely without destabilizing your main line.

Table of Contents

This post covers the core branching workflow and conflict recovery patterns.

Branch Fundamentals

Merge Mechanics

Context Switching

Series Navigation

Branch fundamentals

What a branch really is

A Git branch is a movable pointer to a commit. When you commit on that branch, the pointer moves forward. That means branches are lightweight and cheap to create.

Common branch roles in small teams:

  • main: stable and releasable history
  • feature/<name>: isolated feature development
  • fix/<name>: targeted bug fix work

Create and switch branches

View branches:

git branch

Create a feature branch and switch in one step:

git switch -c feature/add-health-endpoint

Switch between existing branches:

git switch main
git switch feature/add-health-endpoint

If your Git version is older, git checkout can do this too, but git switch is usually clearer.

Merge mechanics

When you merge a branch back into main, one of two patterns usually happens.

Fast-forward merge

If main has not moved since your branch was created, Git can move main forward directly with no new merge commit.

git switch main
git merge feature/add-health-endpoint

This keeps history linear and simple.

Merge commit

If both branches have new commits, Git must create a merge commit to join both histories.

git switch main
git merge feature/add-health-endpoint

The command looks the same, but the graph is different because Git preserves both lines of development.

Conflict resolution flow

A conflict means Git found overlapping edits and needs a human decision.

Conflict cycle:

  1. Run merge command.
  2. Git reports conflicted files.
  3. Open each file and resolve conflict markers.
  4. Stage resolved files.
  5. Complete merge commit.

Example conflict markers:

<<<<<<< HEAD
return "v1";
=======
return "v2";
>>>>>>> feature/api-version

After editing to the final desired content:

git add src/api/version.js
git commit

If you need to back out and retry:

git merge --abort

Context switching

Using stash safely

git stash temporarily shelves local work when you need to switch tasks quickly.

git stash push -m "wip: validation for signup form"
git stash list
git switch main

Restore the latest stash and remove it from the stash stack:

git stash pop

Restore without removing:

git stash apply

Stash is useful, but do not let it become permanent storage. For meaningful progress, a regular commit on a feature branch is usually safer.

Tags vs branches

  • Branches move forward as you add commits
  • Tags point to a specific commit and stay fixed (often used for releases like v1.3.0)

Understanding that difference helps avoid confusion when navigating project history later.

Practical habits that prevent branch pain

  • Pull or fetch the latest main before starting a branch
  • Keep branches short-lived to reduce merge conflicts
  • Use focused commits so conflicts are easier to reason about
  • Merge often enough that divergence stays manageable

Next in this series

Next, we move to collaboration across machines and teammates: remotes, fetch/pull differences, upstream tracking, and pull request flow