Git Notes: Branching & Merging

Mohamad's interest is in Programming (Mobile, Web, Database and Machine Learning). He is studying at the Center For Artificial Intelligence Technology (CAIT), Universiti Kebangsaan Malaysia (UKM).
Mental model
A branch is just a movable pointer to a commit. You create commits on a branch, then combine branches with merge or rebase. Keep your integration branch (main or develop) clean; do new work on short-lived feature branches.
o---o---o (main)
\
o---o (feature)
1) git branch — manage branches
Common tasks
git branch # list local branches; * marks current
git branch -vv # with upstream & last commit
git branch -a # local + remote-tracking
git branch feature/login # create branch at current HEAD
git branch -d feature/x # delete merged branch
git branch -D feature/x # force delete (even if unmerged)
git branch --merged # branches safe to delete
git branch --contains <commit> # which branches include a commit
Rename / set upstream
git branch -m old-name new-name
git branch --set-upstream-to origin/feature/login
2) Switching branches — git switch (preferred) vs git checkout (legacy)
git switch (Git ≥ 2.23)
git switch main # switch existing
git switch -c feature/login # create and switch (like checkout -b)
git switch - # jump back to previous branch
git checkout (older, still works)
git checkout main
git checkout -b feature/login
Note: git checkout also checks out files (not just branches). git switch is clearer for branch changes.
3) git merge — combine histories
Fast-forward (no merge commit when possible):
git switch main git merge feature/login # fast-forwards if main had no new commitsThree-way merge (creates a merge commit):
# main and feature both advanced git switch main git merge feature/login # may create a merge commitControl behavior
git merge --no-ff feature/x # force a merge commit (preserve branch “bubble”) git merge --squash feature/x # squash all feature commits into staged changes git merge --abort # abort a conflicted merge
Resolve conflicts
# after conflicts appear:
git status # see conflicted files
# edit files, decide correct content
git add <fixed-files>
git merge --continue
4) git rebase — reapply commits on a new base
Use case: Keep a linear history by placing your work on top of updated main.
git switch feature/login
git fetch origin
git rebase origin/main # move feature commits onto newest main
# fix conflicts -> edit -> git add -> git rebase --continue
# give up:
git rebase --abort
Interactive rebase (squash, reword, reorder):
git rebase -i HEAD~5 # edit last 5 commits
Safety rule: Don’t rebase shared branches that others already pulled. Rebasing rewrites history; use on personal feature branches before merging.
Pull with rebase (optional default)
git config pull.rebase true
git pull # now does fetch + rebase
5) git cherry-pick — copy specific commits
Apply one commit (or a range) onto current branch
git switch hotfix/urgent
git cherry-pick <commit-sha> # apply a single commit
git cherry-pick A..B # apply commits after A up to B (exclusive A, inclusive B)
git cherry-pick --no-commit <sha> # stage changes without committing
git cherry-pick --abort # cancel if conflicted
Tip: Use -x to record the source SHA in the message:
git cherry-pick -x <sha>
6) git stash — save work in progress
Quick save / restore
git stash push -m "WIP login UI" # save modified/unstaged changes
git stash list # see stashes (stash@{0}, stash@{1}, …)
git stash show -p stash@{0} # preview patch
git stash pop # apply latest and remove it from stash
git stash apply stash@{2} # apply a specific stash (keep it)
git stash drop stash@{2} # delete a specific stash
Keep untracked files too
git stash push -u -m "WIP incl untracked"
Resume into a new branch
git stash branch feature/wip stash@{0}
7) Merge vs Rebase — quick guidance
| Goal | Prefer |
| Preserve true merge history (feature “bubble”) | merge (optionally --no-ff) |
| Keep linear history for readability | rebase on latest main before merging |
| One clean commit for a noisy feature | merge --squash (then single commit) or rebase -i to squash |
| Bring just one fix across branches | cherry-pick |
Team rule of thumb
On personal feature branches: rebase freely to keep tidy.
On shared branches: avoid history rewrites; merge or revert instead.
8) Typical workflows
Feature development (linear)
git switch -c feature/auth
# commits …
git fetch origin
git rebase origin/main
git switch main
git merge --ff-only feature/auth # or squash merge via PR
git branch -d feature/auth
Hotfix from main + backport
git switch -c hotfix/calc-bug main
# fix & commit
git push -u origin hotfix/calc-bug
# merge to main (and tag a release)
# backport to previous release branch:
git switch release/1.2
git cherry-pick <hotfix-commit-sha>
9) Remote tracking & cleanup
git push -u origin feature/payments # set upstream
git branch -vv # see upstream for each branch
git push origin --delete feature/x # remove remote branch
git fetch -p # prune deleted remote branches
10) Quick reference (copy/paste)
# Create & switch
git switch -c feature/x
git switch main # (or: git checkout main)
git switch - # toggle back
# Merge
git switch main
git merge feature/x
git merge --no-ff feature/x
git merge --squash feature/x
git merge --abort
# Rebase
git switch feature/x
git fetch origin
git rebase origin/main
git rebase -i HEAD~N
git rebase --continue
git rebase --abort
# Cherry-pick
git switch target-branch
git cherry-pick <sha> # or A..B
git cherry-pick --abort
# Stash
git stash push -m "WIP"
git stash push -u -m "WIP incl untracked"
git stash list
git stash pop
git stash apply stash@{1}
git stash branch feature/wip stash@{0}
# Branch maintenance
git branch -a
git branch -vv
git branch --merged
git branch -d feature/x
git push origin --delete feature/x
.