K2B-2-3
Pro Git Ch3 — Git Branching
Created 2020-06-02Updated 2026-05-19operating-system / git
- Description: Notes on Pro Git (2nd ed.) Chapter 3 — branches as movable pointers, branch + merge basics, merge strategies + conflicts, branch management, branching workflows (long-running, topic, trunk-based), remote branches (tracking, upstream, pruning), and rebasing (incl. the golden rule).
- My Notion Note ID: K2B-2-3
- Created: 2020-06-02
- Updated: 2026-05-19
- License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io
Table of Contents
- 1. Branches in a Nutshell
- 2. Basic Branching and Merging
- 3. Branch Management
- 4. Branching Workflows
- 5. Remote Branches
- 6. Rebasing
- 7. References
1. Branches in a Nutshell
- Branch = lightweight movable pointer to a commit.
- Commit object = SHA-1 + author + message + tree pointer + parent pointer(s).
HEAD= pointer to the branch currently checked out.- Creating a branch = creating a new pointer (cheap — no copies).
1.1 Parent notation
<ref>^n— n-th parent (only meaningful for merge commits, which have >1 parent).<ref>~n— first parent, n times (i.e.,~3=^^^).^alone =^1;~alone =~1.- Combinable:
HEAD~3^2= grandparent's grandparent's second parent. @{upstream}/@{u}— shorthand for the tracked upstream.@{n}— n-th prior position of HEAD (reflog index).
2. Basic Branching and Merging
2.1 git branch
git branch— list branches;*marks current.git branch <name>— create (doesn't switch).git branch -v/-vv— last commit per branch (-vvshows tracking).git branch --merged/--no-merged— relative to current HEAD.git branch -d <name>— delete (refuses if unmerged).git branch -D <name>— force delete.git branch -m <old> <new>— rename.
2.2 git checkout / git switch
git checkout <branch>— switch.git checkout -b <branch>— create + switch.git checkout -b <branch> <start>— branch off specific commit/tag.git checkout -b <local> <remote>/<branch>— create tracking branch.git checkout -- <file>— discard worktree changes (legacy; see Ch 2 § 4).- Modern split (Git 2.23+):
git switch <branch>— switch only.git switch -c <branch>— create + switch.git restore <file>— discard changes (no overloading).
2.3 git merge
git merge <branch>— merge<branch>into current.- Strategies:
- Fast-forward: target is an ancestor of source → just move pointer (no merge commit).
- Three-way merge (recursive): find common ancestor + diverging tips → new merge commit with two parents.
git merge --no-ff <branch>— always create merge commit (preserves topic branch history).git merge --ff-only— refuse non-fast-forward (CI safety).git merge --squash <branch>— apply changes as a single staged set (no merge commit).
2.4 Conflicts
- Markers in the working tree:
<<<<<<<...=======— current branch (HEAD).=======...>>>>>>>— incoming branch.
- Resolve manually →
git add <file>→git commit. git merge --abort— cancel mid-merge.git mergetool— open visual tool (configure:git config merge.tool <name>).git checkout --ours <file>/--theirs <file>— pick a side wholesale.
3. Branch Management
git branch -u <remote>/<branch>— set upstream.git branch -vv— show branch + upstream + ahead/behind.- Cleanup dead branches:
git fetch --prune
git branch --merged main | grep -v '^\* ' | xargs git branch -d
4. Branching Workflows
4.1 Long-running branches
- Pattern: multiple permanent branches at different stability levels.
- Classic GitFlow:
main(ormaster) — only stable release-ready code.develop(ornext) — integration; tested but not yet released.proposed/pu(optional) — bleeding-edge experimental.
- Commits "graduate" upward as they stabilize → merge develop → main on release.
- Mental model: branches as work silos where commits flow from unstable to stable.
4.2 Topic branches
- Short-lived branch per feature/bug.
- Cheap to create + discard (Git's killer feature).
- Enables:
- Context-switch without losing work.
- Per-topic code review (focused diff).
- Multiple parallel approaches → keep best, discard rest.
- Lifecycle:
git switch -c iss91
# work, commit
git switch main
git merge iss91 # or open a PR
git branch -d iss91
4.3 Integration vs trunk-based
- Integration (GitFlow): topic → develop → main with release branches. Heavyweight; suits long release cycles.
- Trunk-based: short topic branches merged frequently to main; release from main; favored for CI/CD shops. Uses feature flags for incomplete work.
- All branching happens locally → no server roundtrip required.
5. Remote Branches
<remote>/<branch>= remote-tracking branch: local read-only pointer to remote state at last sync.- Updated by
git fetch <remote>(orgit pull). - Local and remote can diverge silently between fetches.
- Example:
origin/mainmay lag behind actual remotemainif you haven't fetched.
5.1 Pushing
git push origin <branch>— push local<branch>toorigin/<branch>.- Refspec long form:
git push origin refs/heads/<branch>:refs/heads/<branch>. - Push to different name:
git push origin <local>:<remote-name>. - First push with tracking:
git push -u origin <branch>(sets upstream so futurepull/pushneed no args).
5.2 Tracking branches (= upstream)
- When set,
git pull/git pushoperate against upstream without specifying remote/branch. - Auto-created by:
git clone(setsorigin/main↔main).git checkout -b <local> <remote>/<branch>.git checkout --track <remote>/<branch>.git checkout <branch>when name uniquely matches a remote.
- Manual:
git branch -u <remote>/<branch>on existing local branch. - Inspect:
git branch -vv(shows tracking + ahead/behind).
5.3 Deleting remote branches
git push origin --delete <branch>(or legacy:refs/heads/<branch>).- Server keeps data until GC.
5.4 Pruning stale remote-tracking refs
- After someone deletes a remote branch, your local
origin/<branch>lingers. git fetch --prune→ cleans up.git remote prune origin→ same thing, explicit.
6. Rebasing
git rebase <base>— replay current branch's commits on top of<base>.- Produces linear history vs merge bubbles.
git rebase <base> <topic>— checkout topic then rebase.git rebase --onto <newbase> <upstream> <branch>— surgical: take commits from<upstream>..<branch>and replay on<newbase>(extract a sub-branch from a chain).- Interactive:
git rebase -i <base>— reorder/squash/edit/drop commits. - Conflicts during rebase: resolve →
git add→git rebase --continue(or--skip/--abort).
6.1 Golden rule
- Never rebase commits that exist outside your repository (i.e., that others may have based work on).
- Rebasing rewrites SHAs → collaborators get duplicate history.
6.2 Rebase vs merge
- Merge preserves topology (true history).
- Rebase produces clean linear history.
- Common team convention: rebase before pushing a topic branch, merge (or squash-merge) into main.