Branches are the reason Git won: they are cheap and instant. A branch lets you work on a task in isolation — commit and experiment as much as you like without touching the working version — and then merge the result back in a single action. The entire team process (tasks, reviews, releases) is built on this mechanism.
A branch is a pointer
The mental model: history is a chain of commits, and a branch is a movable bookmark pointing at one of them. A new commit on a branch simply moves the bookmark forward. Creating a branch = placing another bookmark — an instant operation, nothing is copied.
git branch # list branches, * marks the current one
git switch -c fix-cart-total # create a branch and switch to it
git switch main # go back to main
A special bookmark, HEAD, marks where you are right now. Switching branches replaces the files in the working directory with that branch's snapshot — which is why Git asks you to clean up uncommitted changes before switching (or stash them with git stash — a pocket for unfinished work).
The working rhythm: each task gets its own branch off a fresh main (fix-cart-total, feature-export-csv), commits go there, and after merging the branch is deleted. Branches are consumables, not long-term residents.
Merging: fast-forward and the merge commit
Merging a branch into main:
git switch main
git merge fix-cart-total
Two scenarios are possible:
- Fast-forward. While you were working, main did not move. Then there is nothing to merge — Git simply moves the main bookmark forward onto your commits. History remains a straight line.
- Merge commit. Main has moved ahead (colleagues merged their work). Git creates a special commit with two parents, joining both lines. The history shows a diamond: diverged — converged.
Both outcomes are normal. Which to prefer and why some teams forbid merge commits is a question of the branching model and rebase; for now it is enough to understand what is happening.
Conflicts: not an accident, but a question
A conflict arises when both branches changed the same lines in different ways. Git does not guess whose edit is correct — it stops and asks you:
<<<<<<< HEAD
price = total * 0.9; // your version (current branch)
=======
price = total * 0.85; // the version from the branch being merged
>>>>>>> fix-discount
The no-panic procedure:
git statusshows the conflicting files.- Open the file, find the
<<<<<<</>>>>>>>markers, decide by meaning: keep one version, the other, or write a combined one. Delete the markers. git add file— mark the conflict as resolved.git commit— complete the merge. Changed your mind —git merge --abortputs everything back as it was.
Two grown-up rules. A conflict is resolved by the meaning of the task, not mechanically: "keep mine" is not a strategy — you may wipe out someone's bugfix; in doubt, ask the author of the other edit (blame will show who). And prevention beats cure: short-lived branches and regularly pulling main into your branch keep conflicts small and rare.
Where this helps a backend engineer
Branches are also navigation. See what the code looked like in production — git switch v2.3.1 (by the release tag); check a colleague's work before the review — switch to their branch; an urgent fix in the middle of a big task — stash, a branch off main, the fix, and back. Being able to move freely between branches turns Git from "handing in code" into the project's time machine.
In short
- A branch is a movable pointer to a commit; creation is instant. Task = branch, merged = deleted.
- HEAD is where you are; switching changes the files; uncommitted work goes into stash.
- Merge: fast-forward (main did not move — a straight line) or a merge commit with two parents (a diamond).
- A conflict is a question, not an accident: markers in the file → decide by meaning → add → commit;
--abortcancels. - Conflict prevention: short-lived branches, pull main regularly.
What to read next
- Remote repositories — push, pull, and working with the server.
- Rebase and cherry-pick — the alternative to merge and moving individual commits.
- Branching models — how teams organize branches: git flow, GitHub flow, trunk-based.