Git 2.23+ · Modern Workflow

Modern Git
A Practical Guide

Using git branch, git switch, and git restore — the way Git was meant to work

01 Why git switch and git restore?

For years, git checkout did two completely different things depending on what arguments you gave it. It could switch branches or discard changes to a file — two operations that have nothing to do with each other. This confused beginners and experts alike.

Git 2.23 (released August 2019) introduced two focused commands to replace checkout:

What you want to do Old (confusing) New (clear)
Switch to a branch git checkout main git switch main
Create and switch to new branch git checkout -b feature git switch --create feature
Discard changes to a file git checkout -- hello.c git restore hello.c
Unstage a file git reset HEAD hello.c git restore --staged hello.c
Why it matters

One command, one job. git switch only ever touches branches. git restore only ever touches file content. You can reason about them without juggling mental state.

02 Branches — your best friend

A branch is just a lightweight pointer to a commit. Creating one takes milliseconds and costs almost nothing. This matters because it means you should be using branches constantly — not just for big features.

Encouragement

Create branches freely. Make one to try a risky refactor. Make one to test a different approach. Make one just to experiment with an idea you're not sure about. Local branches are free. If the experiment fails, delete it with one command and nothing is lost. If it succeeds, merge it in.

The only branch you need to protect is main. Everything else is fair game.

Here's what a healthy branching workflow looks like visually:

main ●───●───●───────────────● ← stable, shippable \ / feature ●───●───● ← your playground main ●───●───●───────────────────────● \ / experiment ●───● (abandoned, just delete it)

Creating and listing branches

terminal
# See all local branches
git branch

# Create a branch (does NOT switch to it)
git branch feature/user-login

# Create AND switch in one step (preferred)
git switch --create feature/user-login

# Delete a branch you're done with
git branch --delete feature/user-login
Branch naming

Use a short, descriptive lowercase name with hyphens. Prefixes like feature/, fix/, or experiment/ help organize many branches at a glance. Examples: feature/add-dark-mode, fix/login-redirect, experiment/new-parser.

03 Core workflow

Here's a full cycle from starting work to merging it back:

Step 1 — Start from main

terminal
# Make sure main is up to date
git switch main
git pull

Step 2 — Create your branch and switch to it

terminal
git switch --create feature/better-search
# You are now on the new branch

Step 3 — Do your work, then stage and commit

terminal
# Stage specific files (preferred over staging everything)
git add search.js search.test.js

# Or stage everything in current directory
git add --all

# Commit with a proper message (see Section 4)
git commit --message "Add fuzzy search to reduce zero-result queries"

Step 4 — Made a mistake? Restore, don't panic

terminal
# Discard unstaged changes to a file
git restore search.js

# Unstage a file you accidentally staged
git restore --staged search.js

# Restore a file to its state 3 commits ago
git restore --source HEAD~3 search.js

Step 5 — Merge back when done

terminal
# Switch back to main
git switch main

# Merge your branch in
git merge feature/better-search

# Clean up — delete the branch
git branch --delete feature/better-search

04 Writing proper commit messages

A commit message is a letter to your future self (and your teammates). A bad message like fix stuff is useless in six months. A good message tells you what changed and — more importantly — why.

The format

Three rules, always:

A good commit message

commit message
Add fuzzy search to reduce zero-result queries ← present tense, short, specific Users frequently search with slight misspellings or partial words and get zero results, which causes drop-off. Fuzzy matching with a Levenshtein distance of 2 catches most typos without returning irrelevant results. Tested against our top 500 queries — zero-result rate drops from 18% to 4%. ← explains WHY, includes evidence
Bad commit messages (avoid these)

fix bug · update · wip · changes · asdfgh

These tell you nothing. When you run git log to find when something broke, these messages are useless.

Present tense — why?

Write as if the commit is a command: "Add fuzzy search", not "Added fuzzy search". This matches how Git itself describes things ("Merge branch 'feature'") and reads naturally as a log: each commit does something.

Committing with a full message

terminal
# Opens your editor — write the full message there
git commit

# For a one-liner (when the subject line is enough)
git commit --message "Remove deprecated payment gateway"
Tip

Set your editor to something you like: git config --global core.editor "nano". Then git commit without --message opens it and gives you space to write a proper multi-line message.

05 Quick reference

Branches

git branch
git branch                               # list branches
git branch my-branch                     # create (don't switch)
git branch --delete my-branch           # delete branch
git branch --move old-name new-name    # rename branch

Switching

git switch
git switch main                          # switch to existing branch
git switch --create feature/thing       # create + switch
git switch --detach HEAD~3              # inspect old commit (read-only)

Restoring files

git restore
git restore file.js                      # discard unstaged changes
git restore --staged file.js            # unstage file
git restore --source HEAD~2 file.js    # restore from 2 commits ago

Status and log

seeing what's happening
git status                               # what changed?
git log --oneline                        # compact commit history
git log --oneline --graph               # history with branch diagram
git diff                                 # unstaged changes
git diff --staged                        # staged changes
Remember

Local branches are free. Experiment without fear. The worst outcome is running git branch --delete and losing nothing but some keystrokes. Branch early, branch often.