Git cheat sheet: branching, merging & rebasing

A branch is just a movable pointer to a commit, and creating one costs nothing — which is why the feature-branch workflow (one branch per task, merged back when done) is the default everywhere. HEAD points to the branch you are on, and switching branches moves HEAD.

The three verbs you need: branch to create, switch to move, merge (or rebase) to bring changes back together. Everything below uses git switch, the focused replacement for the overloaded git checkout that shipped in Git 2.23.

Published

Create, switch and delete

The branch commands, modern and legacy spelling
# List local branches (current is starred)
git branch

# Create a branch (without switching to it)
git branch feature/login

# Create AND switch to a branch — modern
git switch -c feature/login

# Create AND switch — legacy spelling (same result)
git checkout -b feature/login

# Switch to an existing branch
git switch main

# Delete a merged branch (safe) vs delete an unmerged branch (force)
git branch -d feature/login
git branch -D feature/login
git switch and git checkout -b are equivalent for these cases; the difference is that checkout also restores files (now the job of git restore), so splitting the two commands removes ambiguity. -d refuses to delete a branch whose commits are not merged (a safety check); -D overrides it.

Merge vs rebase

Two ways to combine a branch — the difference is the shape of history

git merge <branch>
joins the branch into the current one with a merge commit, preserving the true history and both branches' timelines
git merge --ff-only
only fast-forwards (moves the pointer) and refuses to create a merge commit — keeps history linear when possible
git rebase main
replays your commits on top of main's tip, rewriting them to produce a linear history with no merge commits
git cherry-pick <sha>
copies a single commit from another branch onto the current one without merging the branch
The classic rule: rebase local, merge shared. Rebasing rewrites commit IDs, so it is safe for branches no one else has pulled, but rebasing a pushed branch forces everyone else to reconcile. Merge is always safe because it only adds commits. Fast-forwarding (the default when no extra commits exist on the base) simply moves the branch pointer forward with no new commit.
The feature-branch workflow, step by step
# Start from an up-to-date main
git switch main
git pull

# Create a branch for the work
git switch -c feature/login

# ...edit and commit several times...
git add .
git commit -m "Add login form"
git commit -am "Wire up validation"   # -a stages tracked files, -m sets the message

# Bring the feature back into main
git switch main
git merge feature/login
git push

# Clean up
git branch -d feature/login

Interactive rebase and cherry-pick

Rewrite your own unpublished history
# Interactively rewrite the last 3 commits (pick, squash, reword, drop...)
git rebase -i HEAD~3

# Squash all commits since main into one clean commit
git rebase -i main

# Copy one specific commit from another branch
git cherry-pick a1b2c3d

# Copy a range (a..b], excluding a
git cherry-pick a1b2c3d..e4f5g6h
Interactive rebase opens an editor listing each commit with a command: pick (keep as-is), reword (edit the message), squash (fold into the previous commit) and drop (remove). This is how you tidy up a branch before sharing it — and another reason to rebase only unpushed work.

Resolving conflicts

A merge conflict, then resolving it
# Merge stops with a conflict:
git merge feature/login
# CONFLICT (content): Merge conflict in src/app.js

# See only the conflicted files
git status

# After editing the file to keep what you want, mark it resolved:
git add src/app.js

# Finish the merge
git commit

# Abort instead, if you want to walk away:
git merge --abort
Conflict markers inside a conflicted file are <<<<<<< (your version), ======= (the separator) and >>>>>>> (the incoming version). Remove all three markers and keep the lines you want, then git add the file — Git treats a staged file as resolved. git merge --abort (or git rebase --abort mid-rebase) restores the pre-merge state.

References

FAQ

What is the difference between git merge and git rebase?

git merge joins a branch into the current one, creating a merge commit that records both timelines — history stays exactly as it happened. git rebase re-applies your branch's commits one by one on top of the target branch, producing a straight, linear history but rewriting those commits' IDs. Merge is always safe; rebase is for tidying local, unpublished work.

Should I rebase or merge a feature branch?

Merge is the safe default, especially for shared or long-lived branches, because it never rewrites history. Rebase is a good choice for a short-lived, unpushed feature branch when you want a clean linear history on main. The widely used rule of thumb: rebase local work, merge shared work.

How do I rename a branch?

git branch -m renames the branch, or git branch -m renames the current branch. If the branch was pushed, delete the old remote branch with git push origin --delete and push the new one with git push -u origin .

How do I abort a merge or rebase that went wrong?

git merge --abort returns to the state before the merge started, and git rebase --abort does the same mid-rebase. Both are safe because they discard only the in-progress operation, not your existing commits.

What does git cherry-pick do?

It copies the changes of a single commit from another branch onto your current branch, creating a new commit with a different hash. Use it to move one fix across branches without merging the whole branch. The command is git cherry-pick .