The previous lesson was about what a branch is. This one is about the four things you'll actually do with one — create it, switch to it, rename or delete it. There are old commands (git checkout) and new ones (git switch) that do the same job; you'll meet both in any team because the old ones still work and people's muscle memory dies hard. By the end of this lesson, branching will feel like a five-second operation.
Creating a branch
The fundamental command:
git branch feature/login-testsThis creates a new branch called feature/login-tests pointing at the commit you're currently on. It does not switch to it — you're still on main.
git branch feature/login-tests
* main
The asterisk is still on main. The new branch exists but you're not standing on it yet.
Switching branches
Two commands do the same thing — modern Git split checkout into two narrower commands (switch for branches, restore for files) because checkout was overloaded.
Modern (preferred):
git switch feature/login-testsOld (still works everywhere):
git checkout feature/login-testsEither way:
Switched to branch 'feature/login-tests'
git branch* feature/login-tests
main
The asterisk moved. Your working directory now reflects the contents of feature/login-tests — same files for now (the branch was just created), but every commit you make from here lives on this branch, not on main.
Create AND switch in one step
The most common move: make a branch and immediately start working on it. Two equivalent shortcuts:
# Modern
git switch -c feature/login-tests
# Old, still in every example you'll read online
git checkout -b feature/login-testsThe -c (create) and -b (branch) flags say "make this branch and switch to it." Use whichever feels natural — they produce identical results.
Branch naming conventions
Branch names are visible to your whole team for the lifetime of a PR. Treat them like filenames in a shared folder. Most teams use a prefix/short-description pattern:
| Prefix | Used for | Example |
|---|---|---|
feature/ | New features or test suites | feature/checkout-regression-tests |
bugfix/ | Fixing a defect | bugfix/flaky-login-on-firefox |
test/ | Test-only work (fixtures, framework) | test/upgrade-cypress-to-13 |
chore/ | Maintenance, dependency bumps | chore/bump-node-to-20 |
hotfix/ | Urgent production fixes | hotfix/disable-broken-payment-test |
Mechanical rules:
- Lowercase, hyphens, no spaces.
feature/login-tests, notFeature/Login Testsorfeature_login_tests. - Short but specific.
feature/searchis too vague;feature/search-fuzzy-matching-testsreads itself. - No issue numbers buried mid-name.
feature/JIRA-1234-fix-searchis fine;feature/fix-JIRA-1234-searchputs the noise in the middle.
A complete walkthrough
Watch the asterisk move as you go. Starting on main:
git statusOn branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
Create and switch to a branch:
git switch -c feature/search-testsSwitched to a new branch 'feature/search-tests'
Confirm:
git branch* feature/search-tests
main
Do some work and commit:
echo "describe('search', () => {})" > tests/search.spec.js
git add tests/search.spec.js
git commit -m "Scaffold search test file"[feature/search-tests 3a7b2c1] Scaffold search test file
1 file changed, 1 insertion(+)
create mode 100644 tests/search.spec.js
Switch back to main:
git switch mainSwitched to branch 'main'
ls tests/search.spec.js is gone. It still exists — but only on the feature/search-tests branch. On main, it never existed. Switch back and it returns:
git switch feature/search-tests
ls tests/search.spec.js
That's the magic of branches: the file system reflects whichever branch you're on, instantly.
Deleting branches
Once a branch has been merged to main, delete it. Lingering branches clutter git branch -a and confuse new joiners.
Safe delete (refuses if there are unmerged commits):
git branch -d feature/search-testsDeleted branch feature/search-tests (was 3a7b2c1).
Force delete (discards unmerged work — use with care):
git branch -D feature/abandoned-experimentThe capital -D says "I know this has unmerged commits, throw them away anyway." Reserve it for genuine throwaways.
You can't delete the branch you're currently on — switch off it first.
Delete the branch on the remote too. Local delete only removes your local copy; the GitHub branch keeps existing.
git push origin --delete feature/search-testsTo github.com:acme/webapp-tests.git
- [deleted] feature/search-tests
Renaming a branch
If you misspelled the branch name or the scope changed:
git branch -m feature/serach-tests feature/search-tests-m means move. Drop the first argument to rename the current branch.
The full create-switch-delete cycle
Step 1 of 6
Start on main
git switch main && git pull — make sure you branch from the latest code, not yesterday's.
⚠️ Common mistakes
- Forgetting to switch after creating.
git branch foomakes the branch but leaves you on the old one. Your next commit lands where you didn't intend. Usegit switch -c foo(orgit checkout -b foo) unless you have a specific reason to create without switching. - Branching from a stale main. If you don't
git pullfirst, you branch from yesterday's code. Two days later your "fresh" branch is already behind. Makegit switch main && git pullthe first two commands every time you start new work. - Force-deleting (
-D) when you meant safe-delete (-d). Capital-Ddiscards unmerged commits forever. If you typo'd aDand the branch had unique work, that work is gone. Default to lowercase-dand only escalate when Git tells you the branch is unmerged and you're sure.
🎯 Practice task
Make and unmake several branches. 20-25 minutes. Use the qa-sandbox repo from Chapter 1, or any practice repo you don't mind churning.
- On main, create three branches in different ways:
git branch feature/login-tests(create only)git switch -c feature/search-tests(create + switch)git checkout -b feature/checkout-tests(create + switch, old syntax)
- Run
git branchafter each. Track which one has the asterisk. - On
feature/search-tests, create a filetests/search.spec.js, commit it, then switch tomain. Confirm the file disappears (ls tests/). Switch back — confirm it returns. - Switch to main and run
git branch -d feature/login-tests. Safe delete works because the branch had no unique commits. - Try
git branch -d feature/search-tests. Git refuses — that branch has unmerged work. Read the error carefully; it tells you to use-Dto force. - Force-delete it:
git branch -D feature/search-tests. The branch and its commit are gone. - Stretch: rename
feature/checkout-teststotest/checkout-suitewithgit branch -m feature/checkout-tests test/checkout-suite. Confirm withgit branch.
You can now create, switch between, and delete branches with confidence. The next lesson is the part where two branches need to come back together — merging.