Lesson 02: Branching

A branch is an independent line of development within a repository. Branches let you work on a new feature, try an experiment, or fix a bug in isolation, without touching the main line of the project until you are ready. This lesson covers how to create, switch between, merge, and delete branches, and how to resolve conflicts when two branches have edited the same file.


What a branch is

Every repository starts with one branch, conventionally named main. Every commit you make on main extends its history forward in a straight line.

When you create a new branch, Git creates a new pointer starting at the current commit. From that point on, commits on the new branch do not affect main, and commits on main do not affect the new branch.

This separation is safe and cheap: creating a branch takes milliseconds and costs almost no disk space.


Creating and switching branches

Create a new branch and switch to it immediately:

git switch -c my-feature

List all branches (the current one is marked with *):

git branch

Switch to an existing branch:

git switch main

git switch vs. git checkout

Older tutorials use git checkout -b branch-name to create branches and git checkout branch-name to switch. Both work, but git switch (introduced in Git 2.23) is clearer about intent. Use git switch in new work.


Making commits on a branch

Once you are on the new branch, any commits you make are recorded there and do not appear on main.

git switch -c add-energy-loss

Edit files, stage, and commit as normal:

git add physics/energy_loss.py
git commit -m "Add energy loss calculation for iron nuclei"

Switch back to main and your working directory reverts to its state on main:

git switch main

Merging

When you are ready to bring your branch's work into main, merge it.

First, switch to the branch you want to merge into:

git switch main

Then merge your feature branch:

git merge add-energy-loss

If main has not changed since the branch was created, Git performs a fast-forward merge: it simply moves the main pointer forward to the tip of the feature branch. No merge commit is created.

If main has new commits that are not on the feature branch, Git creates a merge commit that combines both histories.


Resolving conflicts

A conflict occurs when both branches have edited the same lines of the same file. Git cannot decide which version to keep, so it asks you to resolve it manually.

During a merge with conflicts, git status shows which files are conflicted:

git status

Open each conflicted file. Git marks the conflict with:

<<<<<<< HEAD
code from your current branch
=======
code from the branch being merged
>>>>>>> add-energy-loss

Edit the file to keep the version you want (or a combination of both), removing all the conflict markers. Then stage the resolved file:

git add physics/energy_loss.py

Complete the merge:

git commit

Git opens your editor with a pre-written merge commit message. Save and close it to finish.

Prevent conflicts by merging frequently

Long-lived branches diverge more from main and accumulate harder conflicts. Merge your feature branch back into main as soon as the feature is complete. Regularly pulling changes from main into your branch (see Lesson 03) also helps.


Deleting a branch

Once a branch has been merged, it is safe to delete:

git branch -d add-energy-loss

Git warns you if the branch has not been merged, protecting you from accidentally discarding work.


Rebasing

This section is optional for now

Rebasing is useful but not essential when you are starting out. If you are new to Git, feel free to skip this section and come back once you are comfortable with branching and merging. Pull requests work perfectly well without it.

Rebasing is an alternative to merging for incorporating changes from one branch into another. Instead of creating a merge commit, rebase replays your commits one by one on top of the target branch, producing a linear history with no merge commits.

Rebase your feature branch onto the current tip of main:

git switch my-feature
git rebase main

Git replays each commit on my-feature as if you had started the branch from the current tip of main. The result is identical code, but with a cleaner, straight-line history.

If there are conflicts during replay, Git pauses and asks you to resolve them, one commit at a time. After resolving each conflict:

git add the-conflicted-file.py
git rebase --continue

To abort and return to the state before the rebase:

git rebase --abort

Never rebase a branch others have cloned

Rebase rewrites commit hashes. If someone else has cloned or checked out your branch, rebasing it leaves their copy pointing at commits that no longer exist in the shared history. Only rebase branches that only you are working on.

When to use rebase, when to use merge:

Situation Recommendation
Updating a private feature branch before a PR Rebase: keeps the history linear and clean
Merging a completed feature branch into main Merge: creates a clear record that the feature landed
Updating a shared branch that others have cloned Merge: never rebase shared branches

See Lesson 03 for the full pre-PR rebase workflow with remotes.


Stashing work in progress

If you need to switch branches but have uncommitted changes you are not ready to commit, use git stash to temporarily set them aside:

git stash

Switch to another branch, do your work, then return and restore the stashed changes:

git switch main
git switch add-energy-loss
git stash pop

Stash is a stack

You can stash multiple times; git stash pop restores the most recent stash. Use git stash list to see all stashed states.


When to branch

A useful rule of thumb for research code: branch whenever you want to try something that might not work.

Common cases:

  • Adding a new physical process or cross-section model.
  • Refactoring a module while keeping the working version on main.
  • Running a sensitivity study that changes the simulation parameters.
  • Fixing a bug that requires more than one commit.

For tiny, obvious fixes (correcting a typo, fixing a broken import), committing directly to main is fine.


Lesson 03 covers GitHub: how to push your local repository to a remote, open pull requests to propose merging a branch, and review other people's code.