Lesson 4 — Branches and History
Learning Objectives
Section titled “Learning Objectives”- Explain what a branch is and why branches are useful.
- Create and switch between branches with
git branchandgit switch. - Merge a branch back into
mainwithgit merge. - Resolve a simple merge conflict.
- Inspect history with
git log,git show, andgit diff. - Undo mistakes with
git restoreand understand when to use it.
Conceptual Overview
Section titled “Conceptual Overview”What is a branch?
Section titled “What is a branch?”A branch is an independent line of development. Think of the main branch as the stable, working version of your project. When you want to add a new feature or try something experimental, you create a branch. Changes on that branch do not affect main until you deliberately merge them.
This is extremely useful in bioinformatics:
- Try a different trimming parameter without breaking your current pipeline.
- Add a new analysis step while keeping the original script intact.
- Collaborate: two people work on different branches and merge when ready.
How branches work internally
Section titled “How branches work internally”A branch is simply a pointer to a commit. When you commit on a branch, the pointer moves forward. When you merge, Git combines the two lines of commits.
main: A ── B ── C ── F (merge) \ /new-feature: D ── EHEAD is a special pointer that shows which commit you are currently looking at. Normally it points to the tip of your current branch.
Worked Examples
Section titled “Worked Examples”1) See existing branches
Section titled “1) See existing branches”cd ~/projects/my_analysisgit branchOutput:
* mainThe * marks the currently active branch. Right now there is only main.
2) Create a new branch
Section titled “2) Create a new branch”git branch with a name creates a new branch without switching to it.
git branch add-trimming-scriptgit branchOutput:
add-trimming-script* mainThe * is still on main — you have not switched yet.
3) Switch to the new branch
Section titled “3) Switch to the new branch”git switch changes your active branch.
git switch add-trimming-scriptOutput:
Switched to branch 'add-trimming-script'Confirm:
git branchOutput:
* add-trimming-script main4) Create a shortcut: create and switch in one command
Section titled “4) Create a shortcut: create and switch in one command”You can combine the last two steps:
git switch -c some-other-branchThe -c flag means “create”. For now, delete this extra branch and stay on add-trimming-script:
git switch add-trimming-scriptgit branch -d some-other-branchOutput:
Deleted branch some-other-branch (was f4a52b1).5) Add a file on the new branch
Section titled “5) Add a file on the new branch”Create a trimming script:
nano run_trimmomatic.shType the following, then save and exit:
#!/usr/bin/env bash# Trim adapters from paired-end reads using Trimmomatic
SAMPLE="SRR1553607"THREADS=4
trimmomatic PE \ Training/short_reads/paired/${SAMPLE}_1.fastq \ Training/short_reads/paired/${SAMPLE}_2.fastq \ trimmed/${SAMPLE}_1_paired.fastq \ trimmed/${SAMPLE}_1_unpaired.fastq \ trimmed/${SAMPLE}_2_paired.fastq \ trimmed/${SAMPLE}_2_unpaired.fastq \ ILLUMINACLIP:TruSeq3-PE.fa:2:30:10 \ LEADING:3 TRAILING:3 SLIDINGWINDOW:4:15 MINLEN:36 \ -threads ${THREADS}Stage and commit:
git add run_trimmomatic.shgit commit -m "Add Trimmomatic script for paired-end trimming"Output:
[add-trimming-script a1b2c3d] Add Trimmomatic script for paired-end trimming 1 file changed, 18 insertions(+) create mode 100755 run_trimmomatic.sh6) Compare branches
Section titled “6) Compare branches”Switch back to main and notice that run_trimmomatic.sh does not exist there yet:
git switch mainlsOutput:
README.md environment.md methods.md notes.md run_fastqc.sh sample_list.txtrun_trimmomatic.sh only exists on add-trimming-script. Switch back:
git switch add-trimming-scriptlsOutput:
README.md environment.md methods.md notes.md run_fastqc.sh run_trimmomatic.sh sample_list.txt7) Merge the branch into main
Section titled “7) Merge the branch into main”When you are satisfied with the work on a branch, merge it into main. First switch to main, then merge:
git switch maingit merge add-trimming-scriptOutput:
Updating f4a52b1..a1b2c3dFast-forward run_trimmomatic.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 run_trimmomatic.sh“Fast-forward” means main simply moved its pointer forward to the new commit — no conflict to resolve. Now run_trimmomatic.sh exists on main:
lsOutput:
README.md environment.md methods.md notes.md run_fastqc.sh run_trimmomatic.sh sample_list.txtPush the merged main to GitHub:
git push8) Delete the merged branch
Section titled “8) Delete the merged branch”After merging, the branch is no longer needed:
git branch -d add-trimming-scriptOutput:
Deleted branch add-trimming-script (was a1b2c3d).9) Simulate and resolve a merge conflict
Section titled “9) Simulate and resolve a merge conflict”Conflicts happen when two branches edit the same part of the same file. Let us simulate one.
Create a branch and edit the first line of notes.md:
git switch -c edit-notes-branchnano notes.mdChange the first line from ## Session notes to ## Analysis notes. Save and exit.
git add notes.mdgit commit -m "Rename notes header to Analysis notes"Now switch back to main and make a different edit to the same line:
git switch mainnano notes.mdChange the first line to ## Lab notes. Save and exit.
git add notes.mdgit commit -m "Rename notes header to Lab notes"Try to merge:
git merge edit-notes-branchOutput:
Auto-merging notes.mdCONFLICT (content): Merge conflict in notes.mdAutomatic merge failed; fix conflicts then commit the result.Open the file to see the conflict markers:
cat notes.mdOutput:
<<<<<<< HEAD## Lab notes=======## Analysis notes>>>>>>> edit-notes-branch
- Installed FastQC- Downloaded SRR1553607 dataset- FastQC completed successfully on all samples- Pushed repository to GitHub successfullyThe section between <<<<<<< HEAD and ======= is what main has. The section between ======= and >>>>>>> edit-notes-branch is what the other branch has. You must decide which version to keep.
Edit the file to remove the conflict markers and keep your chosen version:
nano notes.mdDelete the three conflict marker lines and keep only:
## Session notes
- Installed FastQC...Save and exit. Then stage and commit to complete the merge:
git add notes.mdgit commit -m "Merge edit-notes-branch — keep original header"Output:
[main e9f3a1c] Merge edit-notes-branch — keep original headerDelete the merged branch:
git branch -d edit-notes-branch10) Inspect a specific commit
Section titled “10) Inspect a specific commit”git show prints the full details and diff of a single commit. Use the hash from git log --oneline:
git log --onelineOutput (abbreviated):
e9f3a1c (HEAD -> main) Merge edit-notes-branch — keep original headera1b2c3d Add Trimmomatic script for paired-end trimming...git show a1b2c3dOutput:
commit a1b2c3d...Author: Your Name <you@example.com>Date: Thu Jun 26 10:00:00 2025 +0000
Add Trimmomatic script for paired-end trimming
diff --git a/run_trimmomatic.sh b/run_trimmomatic.shnew file mode 100755...11) Undo changes before staging
Section titled “11) Undo changes before staging”You edited README.md but realise the change was a mistake and you have not staged it yet:
nano README.mdAdd an accidental line: THIS IS A MISTAKE. Save and exit.
Check the diff:
git diff README.mdOutput shows the accidental line with a +. Discard the change:
git restore README.mdNo output is expected. Verify:
git diff README.mdNo output — the file is back to its last committed state.
12) Undo a staged change
Section titled “12) Undo a staged change”Stage the accidental change first to simulate the scenario:
nano README.mdAdd THIS IS A MISTAKE again. Save and exit.
git add README.mdgit statusOutput:
On branch mainChanges to be committed: (use "git restore --staged <file>..." to unstage) modified: README.mdUnstage it (moves the file back to the working directory without discarding changes):
git restore --staged README.mdgit statusOutput:
On branch mainChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: README.mdNow discard the change entirely:
git restore README.mdExercises
Section titled “Exercises”-
Create a branch called
add-alignment-script. On that branch, create a file calledrun_bwa.shwith a short BWA alignment command. Commit it and then merge it intomain. -
After merging, run
git log --oneline. Notice the new commit appears. Pushmainto GitHub and check the GitHub commits page. -
Run
git branch. How many branches do you have now? Delete any merged branches. -
Use
git showon the commit that addedrun_fastqc.sh. What files changed? -
Challenge: Make two branches that both edit different lines of
methods.md. Merge them both intomainwithout a conflict. Explain why there was no conflict.
Solutions
Section titled “Solutions”Solution 1
Section titled “Solution 1”git switch -c add-alignment-scriptnano run_bwa.shFile content:
#!/usr/bin/env bash# Align paired-end reads to a reference genome using BWA-MEM
bwa mem reference.fa \ trimmed/SRR1553607_1_paired.fastq \ trimmed/SRR1553607_2_paired.fastq \ > aligned/SRR1553607.samgit add run_bwa.shgit commit -m "Add BWA-MEM alignment script"git switch maingit merge add-alignment-scriptSolution 2
Section titled “Solution 2”git pushOn GitHub, the commits page shows the merge and the new commit from the branch.
Solution 3
Section titled “Solution 3”git branchOutput:
* mainAfter deleting merged branches only main remains.
Solution 4
Section titled “Solution 4”Find the hash of the commit that added run_fastqc.sh:
git log --onelineFind the line Add sample list and FastQC script, note the hash (e.g. c1e20f3), then:
git show c1e20f3Output shows that run_fastqc.sh and sample_list.txt were created.
Solution 5
Section titled “Solution 5”Two branches editing different lines of the same file produce no conflict because Git can combine non-overlapping edits automatically. A conflict only occurs when two branches change the same lines.