# Git Branching > Branches, merging strategies, rebasing, and history recovery. ## Branches ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 - `git` — core workflow, config, stash, remotes, tags - [Pro Git: Branching](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell)