Branching & Merging
Branches let you experiment without breaking your main analysis. You can try a new normalization method, test a different statistical approach, or refactor your code. If it works, you merge it back. If not, you delete the branch and nothing was harmed.
What is a branch
Section titled “What is a branch”A branch is a parallel line of development. Think of it as a copy of your project where you can make changes independently. Your main branch stays safe while you try something new on a separate branch.
Every Git repository starts with a single branch called main. When you create a new branch, Git makes a pointer to the current commit. Changes on the new branch do not affect main until you explicitly merge them.
main: A --- B --- C \new-analysis: D --- EIn this diagram, commits D and E exist only on the new-analysis branch. The main branch still points to commit C.
Creating and switching branches
Section titled “Creating and switching branches”List all branches in your repository:
git branchOutput:
* mainThe asterisk shows which branch you are on.
Create a new branch:
git branch new-analysisSwitch to it:
git switch new-analysisOr create and switch in one command:
git switch -c new-analysisWhen to branch
Section titled “When to branch”Branch whenever you want to try something without risking your working code. Common scenarios in bioinformatics:
- Testing a different normalization method for your RNA-seq data
- Trying an alternative clustering resolution for single-cell analysis
- Refactoring a long script into smaller functions
- Adding a new analysis step that might not work out
- Experimenting with different filtering thresholds
The key idea is simple. If the experiment succeeds, merge the branch back into main. If it fails, delete the branch.
Working on a branch
Section titled “Working on a branch”Once you switch to a branch, all your normal Git commands work the same way. Edit files, stage them, and commit.
git switch -c try-combat-normalization
# Edit your scripts...git add normalize.pygit commit -m "Replace quantile normalization with ComBat"
# Make more changes...git add plot_pca.pygit commit -m "Update PCA plot to show batch correction results"These commits only exist on the try-combat-normalization branch. If you switch back to main, your files revert to their state before you branched.
git switch main# normalize.py is back to the original versionMerging branches
Section titled “Merging branches”When your experiment works and you want to keep the changes, merge the branch into main.
First, switch to the branch you want to merge into:
git switch mainThen merge:
git merge try-combat-normalizationIf nothing changed on main while you were working on your branch, Git performs a “fast-forward” merge. It simply moves the main pointer forward to include your new commits.
Before merge:main: A --- B --- C \try-combat: D --- E
After fast-forward merge:main: A --- B --- C --- D --- EIf main had new commits too, Git creates a merge commit that combines both lines of work.
Before merge:main: A --- B --- C --- F \try-combat: D --- E
After merge:main: A --- B --- C --- F --- M \ /try-combat: D --- ECommit M is the merge commit. It has two parents: F and E.
Merge conflicts
Section titled “Merge conflicts”Conflicts happen when two branches changed the same line in the same file. Git cannot decide which version to keep, so it asks you.
When a conflict occurs, Git marks the file like this:
<<<<<<< HEADresult = normalize_quantile(counts)=======result = normalize_combat(counts, batch)>>>>>>> try-combat-normalizationThe section between <<<<<<< HEAD and ======= is the version on your current branch. The section between ======= and >>>>>>> is the version from the branch you are merging.
To resolve the conflict:
- Open the file and decide which version to keep. Or write a new version that combines both.
- Remove the conflict markers (
<<<<<<<,=======,>>>>>>>). - Stage the resolved file and commit.
# After editing the file to resolve the conflictgit add normalize.pygit commit -m "Merge combat normalization, resolve conflict in normalize.py"Deleting branches
Section titled “Deleting branches”After merging, you no longer need the branch. Delete it to keep things tidy:
git branch -d try-combat-normalizationThe -d flag only works if the branch has been merged. This protects you from accidentally deleting unmerged work. If you are sure you want to delete an unmerged branch, use -D instead.
Git stash
Section titled “Git stash”Sometimes you need to switch branches but you have uncommitted changes. Git will not let you switch if the changes would conflict with the other branch.
git stash saves your uncommitted changes temporarily:
# You're in the middle of editing, but need to check something on maingit stash
# Switch branches freelygit switch main# ... do your work ...git switch try-combat-normalization
# Bring your changes backgit stash popgit stash works like a stack. You can stash multiple times. git stash list shows all stashed changes. git stash pop restores the most recent stash.
A simple workflow for scientists
Section titled “A simple workflow for scientists”You do not need a complex branching strategy. This workflow covers most bioinformatics projects:
- Keep
mainfor code that works. Every commit onmainshould be a version you could hand to a collaborator. - Create a branch for each new experiment or analysis variation.
- Commit frequently on your branch as you develop.
- When the analysis works, merge it back into
main. - Delete the branch after merging.
# Start a new experimentgit switch -c test-different-clustering
# Work on it...git add cluster_analysis.pygit commit -m "Try Leiden clustering with resolution 0.8"
git add cluster_analysis.pygit commit -m "Add cluster marker gene identification"
# It works! Merge it.git switch maingit merge test-different-clusteringgit branch -d test-different-clusteringThis keeps your main branch clean and your experiments organized. If you ever need to go back to a previous approach, the commit history shows you exactly what changed and when.
Summary
Section titled “Summary”- Branches let you experiment without affecting your main code.
- Use
git switch -c branch-nameto create and switch to a new branch. - Use
git merge branch-nameto bring changes back intomain. - Merge conflicts happen when two branches edit the same line. Resolve them manually, then commit.
- Use
git stashto temporarily save uncommitted changes when switching branches. - Keep it simple: one branch per experiment, merge when it works, delete when done.