Files
howtos/topics/git-branching.md
user 60f9c85f3f docs: add git howto collection
Two reference files covering:
- git.md — config, daily workflow, diff, log, stash, remotes, tags
- git-branching.md — branches, merge, rebase, cherry-pick, bisect, reflog, reset, revert, worktrees
2026-02-21 20:48:58 +01:00

6.9 KiB

Git Branching

Branches, merging strategies, rebasing, and history recovery.

Branches

# List
git branch                             # local
git branch -r                          # remote
git branch -a                          # all
git branch -v                          # with last commit
git branch --merged                    # merged into current
git branch --no-merged                 # not yet merged

# Create
git branch feature-login
git checkout -b feature-login          # create + switch
git switch -c feature-login            # modern syntax

# Switch
git switch main
git checkout main                      # older syntax

# Rename
git branch -m old-name new-name
git branch -m new-name                 # rename current

# Delete
git branch -d feature-login           # safe (refuses if unmerged)
git branch -D feature-login           # force delete

# Cleanup stale remote tracking branches
git fetch --prune
git remote prune origin                # same effect

Merge

# Merge branch into current
git merge feature-login

# Merge with commit message
git merge feature-login -m "feat: integrate login"

# No fast-forward (always create merge commit)
git merge --no-ff feature-login

# Fast-forward only (fail if not possible)
git merge --ff-only feature-login

# Abort in-progress merge
git merge --abort

# Squash (combine all commits, don't auto-commit)
git merge --squash feature-login
git commit -m "feat: login feature"

Merge Strategies

Strategy When to use
Fast-forward Linear history, no divergence
--no-ff Preserve branch topology in history
--squash Collapse noisy branch into single commit
ours Keep our side entirely, discard theirs
recursive / ort Default for diverged branches

Conflict Resolution

# After merge conflict
git status                             # shows conflicted files

# Edit files, resolve markers:
#   <<<<<<< HEAD
#   our changes
#   =======
#   their changes
#   >>>>>>> feature-branch

# Mark resolved
git add resolved-file.txt
git merge --continue
# or
git commit

# Use theirs/ours for a file
git checkout --theirs path/to/file
git checkout --ours path/to/file

Rebase

# Rebase current branch onto main
git rebase main

# Interactive rebase (rewrite last N commits)
git rebase -i HEAD~5

# Continue after resolving conflicts
git rebase --continue

# Abort rebase
git rebase --abort

# Rebase onto specific base
git rebase --onto main feature-base feature-branch

# Auto-squash fixup commits
git commit --fixup abc123
git rebase -i --autosquash main

Interactive Rebase Commands

Command Effect
pick Keep commit as-is
reword Keep commit, edit message
edit Pause at commit for amending
squash Merge into previous commit, combine messages
fixup Merge into previous commit, discard message
drop Remove commit entirely
reorder Move lines to reorder commits

Rebase vs Merge

Merge Rebase
History Preserves branch topology Linear, clean
Conflicts Resolve once May resolve per commit
Shared branches Safe Dangerous (rewrites history)
Use case Integrating feature Cleaning up before merge

Cherry-Pick

# Apply specific commit to current branch
git cherry-pick abc123

# Multiple commits
git cherry-pick abc123 def456

# Range (exclusive start)
git cherry-pick abc123..def456

# Without committing (stage only)
git cherry-pick --no-commit abc123

# Abort
git cherry-pick --abort

Bisect

# Start binary search for a bug
git bisect start
git bisect bad                         # current commit is broken
git bisect good v1.0                   # this tag/commit was working

# Git checks out middle commit — test it, then:
git bisect good                        # if this commit works
git bisect bad                         # if this commit is broken

# Repeat until git finds the first bad commit

# Done
git bisect reset

# Automated bisect with a test script (exit 0 = good, exit 1 = bad)
git bisect start HEAD v1.0
git bisect run ./test-script.sh

Reflog — Recovery Safety Net

# Show reflog (all recent HEAD movements)
git reflog
git reflog show feature-branch         # specific branch

# Recover deleted branch
git reflog                             # find the commit hash
git branch recovered-branch abc123

# Undo a rebase
git reflog                             # find pre-rebase HEAD
git reset --hard abc123

# Recover amended commit
git reflog                             # find pre-amend HEAD
git branch pre-amend abc123

# Reflog expires after 90 days (default)

Reset

# Soft — undo commit, keep staged
git reset --soft HEAD~1

# Mixed (default) — undo commit, unstage, keep working tree
git reset HEAD~1

# Hard — undo commit, discard everything
git reset --hard HEAD~1

# Reset to specific commit
git reset --hard abc123

# Reset single file
git restore --staged file.txt          # preferred
git reset HEAD file.txt                # older syntax
Mode Commit Staging Working Tree
--soft Undo Keep Keep
--mixed Undo Undo Keep
--hard Undo Undo Undo

Revert

# Create a new commit that undoes a previous one (safe for shared history)
git revert abc123
git revert HEAD                        # undo last commit
git revert abc123..def456              # range

# Without auto-commit
git revert --no-commit abc123

Worktrees

# Work on multiple branches simultaneously
git worktree add ../hotfix hotfix-branch
git worktree add ../experiment -b experiment

# List
git worktree list

# Remove
git worktree remove ../hotfix

# Prune stale entries
git worktree prune

Gotchas

  • Never rebase commits already pushed to shared branches — it rewrites history
  • git reset --hard is permanent unless you know the reflog hash
  • git branch -D force-deletes — if unmerged, that work is only in reflog (90 days)
  • Cherry-pick creates a new commit with a different hash — it duplicates, not moves
  • Bisect requires a clean working tree — stash or commit first
  • Merge --squash does not record the branch as merged — git won't know it was integrated
  • Reflog is local only — it doesn't sync to remotes
  • revert of a merge commit needs -m 1 to specify which parent to keep

See Also