caduh

Git Explained with 5 Essential Commands — beyond add/commit/push

3 min read

Learn rebase, cherry-pick, undoing mistakes, and day-to-day flows with five commands that cover 90% of real-world Git.

TL;DR

  • Branch from main, make small commits, and keep your branch up to date with git fetch + git rebase.
  • Use git rebase -i to clean up history (squash/fixup/reword) before opening a PR.
  • Use git cherry-pick to move a specific commit onto another branch.
  • Use git reset (local undo) and git revert (public undo) appropriately.
  • When things go sideways, git reflog is your time machine to recover commits.

Mental model (1 minute)

Git is a DAG of commits. A branch is just a pointer to a commit; HEAD points to the commit you're on. Most “mistakes” are just pointers moving to the wrong place—and you can move them back.

main ──●──●──●─────►
            └─ feature ─●──●──► (HEAD)

The 5 essential commands

1) git switch — create & hop between branches

git fetch origin
git switch -c feature/login origin/main   # create from remote main
git switch -                               # jump back to previous branch
git switch main && git pull --ff-only      # update main safely

Why it matters: Keeps work isolated and lets you update/compare easily. Prefer switch over legacy checkout for clarity.


2) git rebase (incl. interactive) — keep history tidy

git fetch origin
git rebase origin/main                     # replay your work on latest main
git rebase -i HEAD~5                       # squash/fixup/reword last 5 commits
# In the editor:
# pick abc123 Add login form
# fixup def456 Typos
# squash 789abc Address review comments
# reword 456def Better message

Why it matters: Linear history, easier bisects, smaller PRs.
Rule: Don’t rebase shared branches that teammates already pulled.


3) git cherry-pick — move one commit to another branch

git switch hotfix/production
git cherry-pick a1b2c3d                    # apply that exact commit here
# resolving conflicts if needed, then:
git push origin hotfix/production

Use cases: backport a bugfix; pull a single feature commit without the rest of the branch.


4) Undoing mistakes: git reset vs git revert

Local undo (reset)

git reset --soft  HEAD~1   # keep changes staged
git reset --mixed HEAD~1   # keep changes in working tree (default)
git reset --hard  HEAD~1   # discard changes (DANGEROUS)
git restore --staged path/to/file   # unstage a file (modern way)
git restore path/to/file            # discard local changes to a file

Public/shared undo (revert)

git revert <bad_commit_sha>         # make a new commit that inverse-applies another
git revert -m 1 <merge_sha>         # revert a merge commit (pick the mainline parent)

Rule of thumb: If you’ve already pushed and others may have pulled, use revert, not history-rewriting resets.


5) git reflog — your panic button

git reflog                             # list where HEAD/branches have been
# ... find the commit you want, e.g., HEAD@{5}
git reset --hard HEAD@{5}              # jump the branch pointer back there

Why it matters: You can recover “lost” commits after a mistaken reset/rebase—as long as GC hasn’t pruned them.


Common mini-recipes

Update your feature branch with latest main (no merge commits):

git fetch origin
git switch feature/login
git rebase origin/main
# fix conflicts if any: edit files -> git add . -> git rebase --continue

Squash noisy commits before a PR:

git rebase -i HEAD~N

Move a fix from feature to a hotfix branch:

git switch -c hotfix/login-crash origin/main
git cherry-pick <fix_commit_sha>

Quick decision guide

| Situation | Use | |---|---| | “I want my branch on top of latest main” | git rebase origin/main | | “I need just that one commit over here” | git cherry-pick <sha> | | “I committed to the wrong branch (local)” | git reset --soft HEAD~1 then git switch and git commit | | “I pushed a bad commit to shared branch” | git revert <sha> (don’t rewrite history) | | “Help! I lost commits after a reset” | git refloggit reset --hard HEAD@{n} |


Safety tips

  • Set upstreams and use fast-forward only updates for main:
    git config --global pull.ff only
    
  • Name your branches clearly (feature/, fix/, hotfix/).
  • Write meaningful commit messages (imperative mood, explain why).
  • Rebase locally; never rebase a branch others are already using.

One-minute workflow (day to day)

git switch -c feature/x origin/main
# ... edit ...
git add -A && git commit -m "feat(x): do the thing"
git fetch origin && git rebase origin/main
# ... push and open PR ...