Git Branches

Branch management and integration strategies.

Branch Fundamentals

# LIST BRANCHES
git branch                               # Local branches
git branch -a                            # All (local + remote)
git branch -r                            # Remote only
git branch -v                            # With last commit
git branch -vv                           # With tracking info

# BRANCH INFO
git branch --show-current                # Current branch name
git rev-parse --abbrev-ref HEAD          # Same, more portable
git symbolic-ref --short HEAD            # Another method

# CREATE BRANCH
git branch feature                       # Create (don't switch)
git branch feature main                  # Create from specific ref
git branch feature HEAD~3                # Create from 3 commits ago

# SWITCH BRANCHES (modern - prefer)
git switch feature                       # Switch to existing
git switch -c feature                    # Create and switch
git switch -c feature main               # Create from ref and switch
git switch -                             # Switch to previous branch

# CHECKOUT (older, still works)
git checkout feature                     # Switch to existing
git checkout -b feature                  # Create and switch
git checkout -b feature origin/feature   # Create tracking branch

# DELETE BRANCHES
git branch -d feature                    # Delete merged branch
git branch -D feature                    # Force delete (unmerged)
git branch -d -r origin/feature          # Delete remote-tracking ref

# RENAME BRANCH
git branch -m old-name new-name          # Rename any branch
git branch -m new-name                   # Rename current branch

# TRACKING BRANCHES
git branch -u origin/feature             # Set upstream for current
git branch --set-upstream-to=origin/feature  # Verbose same
git branch -u origin/main main           # Set upstream for specific branch

Merge Strategies

# BASIC MERGE
git checkout main
git merge feature                        # Merge feature into main

# MERGE OPTIONS
git merge --no-ff feature                # Force merge commit (no fast-forward)
git merge --ff-only feature              # Only fast-forward (fail if not possible)
git merge --squash feature               # Squash to single commit (no commit made)

# MERGE WITH MESSAGE
git merge feature -m "Merge feature: Add OAuth support"

# MERGE SPECIFIC COMMITS (cherry-pick style)
git merge feature~3..feature             # Last 3 commits from feature

# ABORT MERGE (during conflict)
git merge --abort                        # Cancel merge, restore state

# RESOLVE CONFLICTS
# After fixing conflicted files:
git add resolved-file.txt
git commit                               # Complete merge

# THREE-WAY MERGE UNDERSTANDING
#       A---B---C feature
#      /
# D---E---F---G main
#
# git merge feature creates:
#       A---B---C feature
#      /         \
# D---E---F---G---H main (H is merge commit)

# FAST-FORWARD MERGE
#       A---B---C feature
#      /
# D---E main
#
# git merge feature (fast-forward):
# D---E---A---B---C main+feature (just moves pointer)

# MERGE VS REBASE DECISION
# MERGE when:
# - Preserving complete branch history
# - Public/shared branches
# - Feature complete and ready
#
# REBASE when:
# - Cleaning up local commits
# - Linear history preferred
# - Before merging feature to main

# MERGE STRATEGIES (advanced)
git merge -s ours feature                # Keep ours, ignore theirs
git merge -s recursive -X ours feature   # Prefer ours on conflict
git merge -s recursive -X theirs feature # Prefer theirs on conflict

Rebase Patterns

# BASIC REBASE
git checkout feature
git rebase main                          # Replay feature commits on main

# REBASE RESULT
# Before:
#       A---B---C feature
#      /
# D---E---F---G main
#
# After git rebase main:
# D---E---F---G main
#              \
#               A'--B'--C' feature (new commits!)

# INTERACTIVE REBASE (most powerful)
git rebase -i HEAD~5                     # Edit last 5 commits
git rebase -i main                       # Edit commits since divergence

# INTERACTIVE COMMANDS
# pick   = keep commit as-is
# reword = keep commit, edit message
# edit   = pause at commit for changes
# squash = meld into previous commit
# fixup  = squash but discard message
# drop   = remove commit
# reorder = move lines to reorder commits

# EXAMPLE: Squash last 3 commits
git rebase -i HEAD~3
# Change:
#   pick abc1234 First commit
#   pick def5678 Second commit
#   pick ghi9012 Third commit
# To:
#   pick abc1234 First commit
#   squash def5678 Second commit
#   squash ghi9012 Third commit

# REBASE ONTO SPECIFIC BASE
git rebase --onto main feature~3 feature  # Replay last 3 of feature onto main

# REBASE PRESERVE MERGES
git rebase -p main                       # Deprecated
git rebase --rebase-merges main          # Modern: preserve merge structure

# ABORT REBASE
git rebase --abort                       # Cancel, restore original state

# CONTINUE REBASE (after fixing conflicts)
git add fixed-file.txt
git rebase --continue

# SKIP COMMIT (during rebase)
git rebase --skip                        # Skip problematic commit

# AUTOSQUASH WORKFLOW
git commit --fixup=abc1234               # Create fixup commit
git commit --squash=abc1234              # Create squash commit
git rebase -i --autosquash main          # Auto-order fixup/squash commits

# PULL WITH REBASE
git pull --rebase                        # Rebase instead of merge
git config pull.rebase true              # Make default behavior

Branch Workflows

# FEATURE BRANCH WORKFLOW
# 1. Create feature branch from main
git checkout main
git pull origin main
git checkout -b feature/add-oauth

# 2. Work on feature
# ... make changes ...
git add -A && git commit -m "feat(auth): implement OAuth flow"
# ... more changes ...
git add -A && git commit -m "feat(auth): add token refresh"

# 3. Update from main (optional, keeps history clean)
git fetch origin
git rebase origin/main

# 4. Push and create PR
git push -u origin feature/add-oauth
gh pr create --title "Add OAuth support" --body "..."

# 5. After PR merged, cleanup
git checkout main
git pull origin main
git branch -d feature/add-oauth
git push origin --delete feature/add-oauth

# TRUNK-BASED DEVELOPMENT (short-lived branches)
git checkout -b fix/typo-readme
# Make small change
git add -A && git commit -m "fix: correct typo in README"
git push -u origin fix/typo-readme
gh pr create --title "Fix README typo"
# Merge quickly, delete branch

# RELEASE BRANCH WORKFLOW
git checkout main
git checkout -b release/v1.2.0
# Only bugfixes on release branch
git cherry-pick abc1234                  # Apply specific fix
git tag v1.2.0
git push origin release/v1.2.0 --tags

# HOTFIX WORKFLOW
git checkout main
git checkout -b hotfix/critical-bug
# Fix the issue
git add -A && git commit -m "fix: resolve critical auth bypass"
git checkout main && git merge hotfix/critical-bug
git tag v1.1.1
git push origin main --tags

# ENVIRONMENT BRANCHES
# main -> staging -> production
git checkout staging
git merge main
git push origin staging                  # Triggers staging deploy

git checkout production
git merge staging
git push origin production               # Triggers production deploy

Remote Branch Operations

# LIST REMOTE BRANCHES
git branch -r                            # Remote-tracking branches
git ls-remote --heads origin             # Actual remote branches

# FETCH REMOTE BRANCHES
git fetch origin                         # Fetch all from origin
git fetch --all                          # Fetch from all remotes
git fetch origin feature                 # Fetch specific branch
git fetch --prune                        # Remove deleted remote refs

# CHECKOUT REMOTE BRANCH
git checkout -b feature origin/feature   # Create local tracking branch
git checkout --track origin/feature      # Same, shorter
git checkout feature                     # Auto-creates if unique remote exists

# PUSH BRANCH TO REMOTE
git push origin feature                  # Push to origin
git push -u origin feature               # Push and set upstream
git push --set-upstream origin feature   # Same, verbose

# DELETE REMOTE BRANCH
git push origin --delete feature         # Delete remote branch
git push origin :feature                 # Same, older syntax

# PRUNE STALE REFERENCES
git remote prune origin                  # Remove stale remote-tracking
git fetch --prune                        # Fetch and prune together

# COMPARE WITH REMOTE
git log origin/main..HEAD                # Local commits not on remote
git log HEAD..origin/main                # Remote commits not local
git log origin/main...HEAD               # Divergent commits
git rev-list --count origin/main..HEAD   # Count commits ahead

# FORCE UPDATE REMOTE BRANCH (careful!)
git push --force-with-lease origin feature  # Safe force push
# --force-with-lease fails if remote changed since last fetch
# Prevents overwriting others' work

# TRACK DIFFERENT REMOTE
git branch -u upstream/main              # Track upstream's main
git push -u upstream feature             # Push to different remote

Conflict Resolution

# CONFLICT MARKERS
# When git can't auto-merge:
# <<<<<<< HEAD
# your changes
# =======
# their changes
# >>>>>>> feature

# IDENTIFY CONFLICTS
git status                               # Lists conflicted files
git diff --name-only --diff-filter=U     # Just conflicted filenames

# RESOLUTION WORKFLOW
# 1. Open conflicted file
# 2. Find <<<<<<< markers
# 3. Edit to desired result
# 4. Remove markers
# 5. Stage and commit:
git add resolved-file.txt
git commit                               # Completes merge

# USE MERGE TOOL
git mergetool                            # Opens configured tool
git mergetool -t vimdiff                 # Use specific tool

# CHECKOUT SPECIFIC VERSION
git checkout --ours file.txt             # Keep our version
git checkout --theirs file.txt           # Keep their version

# ABORT OPERATIONS
git merge --abort                        # Cancel merge
git rebase --abort                       # Cancel rebase
git cherry-pick --abort                  # Cancel cherry-pick

# THREE-WAY COMPARISON
git diff HEAD                            # Current state vs last commit
git diff MERGE_HEAD                      # Current state vs merge target
git log --merge --left-right -p          # Both sides with patches

# RERERE (Reuse Recorded Resolution)
git config rerere.enabled true           # Enable rerere
# Git remembers how you resolved conflicts
# Applies same resolution automatically next time

# CONFLICT PREVENTION
# 1. Rebase frequently: git fetch && git rebase origin/main
# 2. Small, focused commits
# 3. Communicate about shared files
# 4. Use feature flags for parallel work

Infrastructure Repository Branching

# DOMUS-* REPO CONVENTIONS
# Most domus-* repos use trunk-based (main only)
# Changes pushed directly to main after review

# CHECK BRANCH STATUS ACROSS REPOS
for repo in domus-docs domus-infra-ops domus-captures domus-ise-linux; do
  branch=$(git -C ~/atelier/_bibliotheca/$repo branch --show-current)
  ahead=$(git -C ~/atelier/_bibliotheca/$repo rev-list --count origin/main..HEAD 2>/dev/null || echo "?")
  echo "$repo: $branch (+$ahead)"
done

# FEATURE BRANCH FOR MAJOR CHANGES
# Use when change spans multiple sessions or needs review
cd ~/atelier/_bibliotheca/domus-infra-ops
git checkout -b feature/k3s-ha-deployment

# ... work over multiple days ...
git push -u origin feature/k3s-ha-deployment
gh pr create --title "k3s HA deployment runbook"

# After merge
git checkout main
git pull
git branch -d feature/k3s-ha-deployment

# SYNC ACROSS BRANCHES
# Update feature branch from main
git checkout feature/k3s-ha-deployment
git fetch origin
git rebase origin/main
# Fix any conflicts
git push --force-with-lease

# DOCUMENTATION RELEASE PATTERN
# Tag documentation versions (optional)
git tag -a v2026-02 -m "February 2026 documentation snapshot"
git push origin --tags

# EMERGENCY ROLLBACK BRANCH
# Create branch at known-good state
git branch rollback-point
# If things break:
git checkout rollback-point
# Or reset main to it:
git checkout main
git reset --hard rollback-point

# COMPARE REPOS FOR DIVERGENCE
for repo in domus-infra-ops domus-ise-linux; do
  echo "=== $repo ==="
  git -C ~/atelier/_bibliotheca/$repo log --oneline origin/main..HEAD
  git -C ~/atelier/_bibliotheca/$repo log --oneline HEAD..origin/main
done

Branch Gotchas

# WRONG: Rebasing public branches
git checkout main
git rebase feature
# Rewrites main history! Others' work broken!

# CORRECT: Merge public branches, rebase private
git checkout main
git merge feature                        # Preserves history

# WRONG: Force pushing without --force-with-lease
git push --force origin main
# May overwrite others' commits!

# CORRECT: Use --force-with-lease
git push --force-with-lease origin main
# Fails if remote changed since your last fetch

# WRONG: Deleting branch with unmerged commits
git branch -d feature
# Error: not fully merged

# CORRECT: Check what's unmerged first
git log main..feature --oneline
# Then force delete if OK:
git branch -D feature

# WRONG: Checking out with uncommitted changes
git checkout main
# Error: Your local changes would be overwritten

# CORRECT: Stash or commit first
git stash
git checkout main
git stash pop

# WRONG: Creating branch from wrong base
git checkout feature                     # Was on feature, not main!
git checkout -b new-feature              # Based on feature, not main!

# CORRECT: Be explicit about base
git checkout -b new-feature main
# Or: git checkout main && git checkout -b new-feature

# WRONG: Assuming local branch tracks remote
git push
# Error: no upstream branch

# CORRECT: Set upstream explicitly
git push -u origin feature
# Or: git branch -u origin/feature

# WRONG: Merge conflicts from stale branch
git checkout feature                     # Haven't updated in weeks
git checkout main && git merge feature   # Lots of conflicts!

# CORRECT: Update feature before merge
git checkout feature
git fetch origin && git rebase origin/main
git checkout main && git merge feature   # Clean merge

Quick Reference

# BRANCH MANAGEMENT
git branch                               # List local
git branch -a                            # List all
git branch -vv                           # With tracking info
git switch -c feature                    # Create and switch (modern)
git checkout -b feature                  # Create and switch (classic)
git branch -d feature                    # Delete merged
git branch -D feature                    # Force delete
git branch -m old new                    # Rename

# SWITCH BRANCHES
git switch feature                       # Modern
git checkout feature                     # Classic
git switch -                             # Previous branch

# MERGE
git merge feature                        # Basic merge
git merge --no-ff feature                # Force merge commit
git merge --squash feature               # Squash to one commit
git merge --abort                        # Cancel

# REBASE
git rebase main                          # Replay on main
git rebase -i HEAD~5                     # Interactive edit
git rebase --abort                       # Cancel
git rebase --continue                    # After fixing conflict

# REMOTE BRANCHES
git fetch --all --prune                  # Update refs
git checkout -b feat origin/feat         # Track remote
git push -u origin feature               # Push + set upstream
git push origin --delete feature         # Delete remote

# CONFLICT RESOLUTION
git checkout --ours file.txt             # Keep our version
git checkout --theirs file.txt           # Keep their version
git add file.txt && git commit           # Complete merge

See Also

  • History — blame, bisect, log search

  • Rewriting — interactive rebase, cherry-pick

  • Stash — save work before switching branches

  • Worktrees — work on branches simultaneously