Master Git branching to work on multiple features simultaneously. Learn to create, switch, and manage branches effectively for parallel development.
Branches are one of Git's most powerful features. They allow you to diverge from the main line of development to work on new features, fix bugs, or experiment - all without affecting the stable codebase.
Think of branches like parallel universes for your code. You can create a branch, make changes, and if those changes work out, merge them back. If they don't, simply delete the branch - your main code remains untouched.
Professional development teams use branches constantly. Understanding branching is essential for collaborating effectively and maintaining clean project history.
A branch in Git is simply a lightweight movable pointer to a commit. The default branch is called main (formerly master).
How Branches Work:
1 feature
2 │
3 ▼
4 ┌───┐ ┌───┐
5 │ C │───│ D │
6 └───┘ └───┘
7 /
8┌───┐ ┌───┐
9│ A │───│ B │───────────── main
10└───┘ └───┘ │
11 ▼
12 HEADKey Concepts:
Why Branches Are Lightweight:
Unlike other version control systems, Git branches are just 41-byte files containing a commit hash. Creating a branch is nearly instantaneous regardless of project size.
1# A branch is literally just a file containing a commit hash
2cat .git/refs/heads/main
3# Output: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0Branch Naming Conventions:
1# Feature branches
2feature/user-authentication
3feature/shopping-cart
4feat/dark-mode
5
6# Bug fix branches
7bugfix/login-validation
8fix/memory-leak
9hotfix/security-patch
10
11# Other common patterns
12release/v1.2.0
13experiment/new-algorithm
14docs/api-documentation
15refactor/database-layerCreating branches is fast and encouraged. Create branches freely for any distinct piece of work.
Create a New Branch:
1# Create a new branch (doesn't switch to it)
2git branch feature/new-feature
3
4# Create and switch to new branch in one command
5git checkout -b feature/new-feature
6
7# Modern alternative (Git 2.23+)
8git switch -c feature/new-featureCreate Branch from Specific Point:
1# Create branch from specific commit
2git branch feature/old-feature a1b2c3d
3
4# Create branch from another branch
5git branch feature/derived-feature develop
6
7# Create branch from tag
8git branch release/v1.0-patch v1.0.0What Happens When You Create a Branch:
1Before: After git branch feature:
2
3┌───┐ ┌───┐ ┌───┐ ┌───┐
4│ A │───│ B │── main │ A │───│ B │── main
5└───┘ └───┘ │ └───┘ └───┘ │
6 ▼ │── feature
7 HEAD ▼
8 HEADBranch Creation Best Practices:
feature/user-profile not new-stufffeature/JIRA-123-user-authmain or developSwitching branches changes the files in your working directory to match the branch you're switching to.
Switch to Existing Branch:
1# Traditional command
2git checkout feature/new-feature
3
4# Modern command (Git 2.23+, recommended)
5git switch feature/new-feature
6
7# Switch to previous branch (like cd -)
8git switch -
9git checkout -What Happens When You Switch:
1# On main branch
2$ cat config.js
3# version: "1.0.0"
4
5$ git switch feature/new-version
6# Switched to branch 'feature/new-version'
7
8$ cat config.js
9# version: "2.0.0-beta" # File contents changed!Handling Uncommitted Changes:
1# If you have uncommitted changes that conflict:
2$ git switch feature/other
3# error: Your local changes would be overwritten by checkout.
4# Please commit or stash them.
5
6# Option 1: Commit your changes
7git add .
8git commit -m "WIP: Save current work"
9git switch feature/other
10
11# Option 2: Stash your changes
12git stash
13git switch feature/other
14# Later, restore with: git stash pop
15
16# Option 3: Force switch (DANGEROUS - loses changes!)
17git switch -f feature/other # Don't do this!Quick Branch Operations:
1# See which branch you're on
2git branch --show-current
3
4# Switch to main
5git switch main
6
7# Create and switch in one command
8git switch -c feature/quick-fixKeep your branches organized by regularly reviewing and cleaning them up.
Listing Branches:
1# List local branches
2git branch
3# develop
4# * main <- asterisk shows current branch
5# feature/login
6
7# List all branches (including remote)
8git branch -a
9# develop
10# * main
11# feature/login
12# remotes/origin/main
13# remotes/origin/develop
14
15# List remote branches only
16git branch -r
17
18# List branches with last commit info
19git branch -v
20# develop a1b2c3d Add user model
21# * main d4e5f6g Merge pull request #42
22# feature e7f8g9h WIP: Login form
23
24# List branches with tracking info
25git branch -vv
26# * main d4e5f6g [origin/main] Merge PR #42
27# develop a1b2c3d [origin/develop: ahead 2] Add modelRenaming Branches:
1# Rename current branch
2git branch -m new-name
3
4# Rename a specific branch
5git branch -m old-name new-name
6
7# Rename on remote (delete old, push new)
8git push origin --delete old-name
9git push origin new-nameDeleting Branches:
1# Delete a merged branch
2git branch -d feature/completed
3
4# Force delete unmerged branch (loses commits!)
5git branch -D feature/abandoned
6
7# Delete remote branch
8git push origin --delete feature/old-feature
9
10# Clean up remote tracking branches that no longer exist
11git fetch --prune
12# or
13git remote prune originFinding Branches:
1# Find branches containing a commit
2git branch --contains a1b2c3d
3
4# Find branches merged into main
5git branch --merged main
6
7# Find branches NOT merged into main
8git branch --no-merged main
9
10# Find branches by pattern
11git branch --list "feature/*"Remote branches represent the state of branches on remote repositories. Understanding them is crucial for collaboration.
Remote Branch Concepts:
1Local Repository Remote Repository (origin)
2
3main ─────────────────────── origin/main
4 \
5 feature/login origin/feature/login
6
7origin/main is a "remote-tracking branch"
8It's a local reference to what main looked like on originViewing Remote Branches:
1# List remote branches
2git branch -r
3# origin/main
4# origin/develop
5# origin/feature/api
6
7# See remote branch details
8git remote show originCreating Tracking Branches:
1# Create local branch tracking remote branch
2git checkout -b feature/api origin/feature/api
3
4# Shorthand (if branch name matches)
5git checkout feature/api
6# Branch 'feature/api' set up to track 'origin/feature/api'
7
8# Modern syntax
9git switch -c feature/api --track origin/feature/apiSetting Upstream (Tracking):
1# Set upstream for current branch
2git branch -u origin/feature/login
3# or
4git branch --set-upstream-to=origin/feature/login
5
6# Push and set upstream in one command
7git push -u origin feature/new
8
9# Check tracking relationships
10git branch -vvSyncing with Remote:
1# Update remote-tracking branches
2git fetch origin
3
4# Fetch all remotes
5git fetch --all
6
7# Fetch and prune deleted branches
8git fetch --prune
9
10# See differences with remote
11git log main..origin/main --onelinePush Local Branch to Remote:
1# Push new branch to remote
2git push -u origin feature/new-feature
3
4# Push to differently named remote branch
5git push origin local-branch:remote-branchExplore Git branching visually. Create branches, switch between them, and see how commits relate to different branches.
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Git Branching Visualizer</title>
7 <style>
8 body {
9 font-family: 'Segoe UI', system-ui, sans-serif;
10 background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
11 min-height: 100vh;
12 color: #e0e0e0;
13 padding: 20px;
14 }
15 .container { max-width: 1100px; margin: 0 auto; }
16 h1 { text-align: center; color: #f97316; margin-bottom: 10px; }
17 .subtitle { text-align: center; color: #9ca3af; margin-bottom: 30px; }
18
19 .controls {
20 display: flex;
21 gap: 10px;
22 flex-wrap: wrap;
23 margin-bottom: 20px;
24 justify-content: center;
25 }
26 .btn {
27 padding: 10px 20px;
28 border: none;
29 border-radius: 8px;
30 cursor: pointer;
31 font-weight: 500;
32 transition: all 0.3s;
33 }
34 .btn:hover { transform: translateY(-2px); }
35 .btn-create { background: #22c55e; color: white; }
36 .btn-switch { background: #3b82f6; color: white; }
37 .btn-commit { background: #f97316; color: white; }
38 .btn-delete { background: #ef4444; color: white; }
39
40 .graph-container {
41 background: rgba(0, 0, 0, 0.3);
42 border-radius: 12px;
43 padding: 30px;
44 margin-bottom: 20px;
45 min-height: 300px;
46 position: relative;
47 overflow-x: auto;
48 }
49
50 .branch-row {
51 display: flex;
52 align-items: center;
53 margin-bottom: 30px;
54 position: relative;
55 }
56
57 .branch-label {
58 width: 120px;
59 padding: 8px 12px;
60 border-radius: 6px;
61 font-weight: 600;
62 font-size: 14px;
63 text-align: center;
64 margin-right: 20px;
65 }
66 .branch-label.main { background: #22c55e; color: white; }
67 .branch-label.feature { background: #3b82f6; color: white; }
68 .branch-label.current { box-shadow: 0 0 0 3px #fbbf24; }
69
70 .commits {
71 display: flex;
72 align-items: center;
73 gap: 30px;
74 }
75
76 .commit-node {
77 width: 50px;
78 height: 50px;
79 border-radius: 50%;
80 display: flex;
81 align-items: center;
82 justify-content: center;
83 font-weight: bold;
84 font-size: 12px;
85 position: relative;
86 cursor: pointer;
87 transition: transform 0.3s;
88 }
89 .commit-node:hover { transform: scale(1.1); }
90 .commit-node.main { background: linear-gradient(135deg, #22c55e, #16a34a); }
91 .commit-node.feature { background: linear-gradient(135deg, #3b82f6, #2563eb); }
92 .commit-node.head::after {
93 content: 'HEAD';
94 position: absolute;
95 top: -25px;
96 background: #fbbf24;
97 color: #1a1a2e;
98 padding: 2px 8px;
99 border-radius: 4px;
100 font-size: 10px;
101 }
102
103 .commit-line {
104 position: absolute;
105 height: 3px;
106 background: #4b5563;
107 top: 50%;
108 transform: translateY(-50%);
109 }
110
111 .branch-line {
112 position: absolute;
113 width: 3px;
114 background: #3b82f6;
115 left: 170px;
116 }
117
118 .info-panel {
119 background: rgba(255, 255, 255, 0.03);
120 border-radius: 12px;
121 padding: 20px;
122 display: grid;
123 grid-template-columns: 1fr 1fr;
124 gap: 20px;
125 }
126
127 .info-section h4 {
128 color: #f97316;
129 margin-bottom: 10px;
130 }
131
132 .branch-list {
133 list-style: none;
134 }
135 .branch-list li {
136 padding: 8px 12px;
137 margin-bottom: 5px;
138 background: rgba(255, 255, 255, 0.05);
139 border-radius: 6px;
140 display: flex;
141 justify-content: space-between;
142 align-items: center;
143 }
144 .branch-list li.active {
145 background: rgba(34, 197, 94, 0.2);
146 border-left: 3px solid #22c55e;
147 }
148
149 .terminal {
150 background: #0f172a;
151 border-radius: 8px;
152 padding: 15px;
153 font-family: monospace;
154 font-size: 13px;
155 max-height: 150px;
156 overflow-y: auto;
157 }
158 .cmd { color: #22c55e; }
159 .output { color: #9ca3af; }
160
161 .modal {
162 display: none;
163 position: fixed;
164 top: 0; left: 0;
165 width: 100%; height: 100%;
166 background: rgba(0,0,0,0.7);
167 justify-content: center;
168 align-items: center;
169 z-index: 100;
170 }
171 .modal-content {
172 background: #1e293b;
173 padding: 25px;
174 border-radius: 12px;
175 width: 350px;
176 }
177 .modal-content h3 { color: #f97316; margin-bottom: 15px; }
178 .modal-content input {
179 width: 100%;
180 padding: 10px;
181 border-radius: 6px;
182 border: 1px solid #4b5563;
183 background: #0f172a;
184 color: #e0e0e0;
185 margin-bottom: 15px;
186 }
187 .modal-buttons { display: flex; gap: 10px; justify-content: flex-end; }
188 </style>
189</head>
190<body>
191 <div class="container">
192 <h1>Git Branching Visualizer</h1>
193 <p class="subtitle">Create branches, make commits, and visualize the Git graph</p>
194
195 <div class="controls">
196 <button class="btn btn-create" onclick="showCreateModal()">+ Create Branch</button>
197 <button class="btn btn-commit" onclick="makeCommit()">Make Commit</button>
198 <button class="btn btn-switch" onclick="showSwitchModal()">Switch Branch</button>
199 <button class="btn btn-delete" onclick="deleteBranch()">Delete Branch</button>
200 </div>
201
202 <div class="graph-container" id="graph"></div>
203
204 <div class="info-panel">
205 <div class="info-section">
206 <h4>Branches</h4>
207 <ul class="branch-list" id="branch-list"></ul>
208 </div>
209 <div class="info-section">
210 <h4>Terminal Output</h4>
211 <div class="terminal" id="terminal"></div>
212 </div>
213 </div>
214
215 <!-- Create Branch Modal -->
216 <div class="modal" id="create-modal">
217 <div class="modal-content">
218 <h3>Create New Branch</h3>
219 <input type="text" id="branch-name" placeholder="feature/new-feature">
220 <div class="modal-buttons">
221 <button class="btn" style="background:#6b7280;color:white" onclick="hideModals()">Cancel</button>
222 <button class="btn btn-create" onclick="createBranch()">Create</button>
223 </div>
224 </div>
225 </div>
226
227 <!-- Switch Branch Modal -->
228 <div class="modal" id="switch-modal">
229 <div class="modal-content">
230 <h3>Switch Branch</h3>
231 <select id="switch-select" style="width:100%;padding:10px;border-radius:6px;background:#0f172a;color:#e0e0e0;border:1px solid #4b5563;margin-bottom:15px;"></select>
232 <div class="modal-buttons">
233 <button class="btn" style="background:#6b7280;color:white" onclick="hideModals()">Cancel</button>
234 <button class="btn btn-switch" onclick="switchBranch()">Switch</button>
235 </div>
236 </div>
237 </div>
238 </div>
239
240 <script>
241 let state = {
242 branches: {
243 'main': { commits: ['A', 'B', 'C'], color: 'main', parent: null }
244 },
245 currentBranch: 'main',
246 commitCounter: 3
247 };
248
249 const commitLabels = 'DEFGHIJKLMNOPQRSTUVWXYZ';
250
251 function render() {
252 renderGraph();
253 renderBranchList();
254 }
255
256 function renderGraph() {
257 const graph = document.getElementById('graph');
258 let html = '';
259
260 Object.entries(state.branches).forEach(([name, branch], index) => {
261 const isMain = name === 'main';
262 const isCurrent = name === state.currentBranch;
263 const labelClass = isMain ? 'main' : 'feature';
264
265 html += '<div class="branch-row">';
266 html += '<div class="branch-label ' + labelClass + (isCurrent ? ' current' : '') + '">' + name + '</div>';
267 html += '<div class="commits">';
268
269 branch.commits.forEach((commit, i) => {
270 const isHead = isCurrent && i === branch.commits.length - 1;
271 html += '<div class="commit-node ' + labelClass + (isHead ? ' head' : '') + '" title="Commit ' + commit + '">' + commit + '</div>';
272 });
273
274 html += '</div></div>';
275 });
276
277 graph.innerHTML = html;
278 }
279
280 function renderBranchList() {
281 const list = document.getElementById('branch-list');
282 list.innerHTML = Object.keys(state.branches).map(name => {
283 const isCurrent = name === state.currentBranch;
284 const commits = state.branches[name].commits.length;
285 return '<li class="' + (isCurrent ? 'active' : '') + '">' +
286 '<span>' + (isCurrent ? '* ' : '') + name + '</span>' +
287 '<span style="color:#9ca3af">' + commits + ' commits</span>' +
288 '</li>';
289 }).join('');
290 }
291
292 function addTerminalLine(text, isCmd = false) {
293 const terminal = document.getElementById('terminal');
294 const div = document.createElement('div');
295 div.className = isCmd ? 'cmd' : 'output';
296 div.textContent = (isCmd ? '$ ' : ' ') + text;
297 terminal.appendChild(div);
298 terminal.scrollTop = terminal.scrollHeight;
299 }
300
301 function showCreateModal() {
302 document.getElementById('create-modal').style.display = 'flex';
303 document.getElementById('branch-name').focus();
304 }
305
306 function showSwitchModal() {
307 const select = document.getElementById('switch-select');
308 select.innerHTML = Object.keys(state.branches)
309 .filter(b => b !== state.currentBranch)
310 .map(b => '<option value="' + b + '">' + b + '</option>')
311 .join('');
312 document.getElementById('switch-modal').style.display = 'flex';
313 }
314
315 function hideModals() {
316 document.getElementById('create-modal').style.display = 'none';
317 document.getElementById('switch-modal').style.display = 'none';
318 }
319
320 function createBranch() {
321 const name = document.getElementById('branch-name').value.trim();
322 if (!name) return alert('Please enter a branch name');
323 if (state.branches[name]) return alert('Branch already exists');
324
325 const currentCommits = [...state.branches[state.currentBranch].commits];
326 state.branches[name] = {
327 commits: currentCommits,
328 color: 'feature',
329 parent: state.currentBranch
330 };
331
332 addTerminalLine('git branch ' + name, true);
333 addTerminalLine('Created branch "' + name + '" from ' + state.currentBranch);
334
335 document.getElementById('branch-name').value = '';
336 hideModals();
337 render();
338 }
339
340 function switchBranch() {
341 const name = document.getElementById('switch-select').value;
342 if (!name) return;
343
344 addTerminalLine('git switch ' + name, true);
345 addTerminalLine('Switched to branch "' + name + '"');
346
347 state.currentBranch = name;
348 hideModals();
349 render();
350 }
351
352 function makeCommit() {
353 const label = commitLabels[state.commitCounter - 3] || 'X' + state.commitCounter;
354 state.branches[state.currentBranch].commits.push(label);
355 state.commitCounter++;
356
357 addTerminalLine('git commit -m "Commit ' + label + '"', true);
358 addTerminalLine('[' + state.currentBranch + ' ' + label.toLowerCase() + '] Commit ' + label);
359
360 render();
361 }
362
363 function deleteBranch() {
364 if (state.currentBranch === 'main') {
365 return alert('Cannot delete main branch');
366 }
367
368 const name = state.currentBranch;
369 addTerminalLine('git branch -d ' + name, true);
370
371 delete state.branches[name];
372 state.currentBranch = 'main';
373
374 addTerminalLine('Deleted branch ' + name);
375 render();
376 }
377
378 // Initialize
379 render();
380 </script>
381</body>
382</html>This interactive visualizer demonstrates Git branching concepts:
Features:
Key Observations:
Branching Best Practices:
Now that you understand branching, the next lesson covers merging - how to combine branches back together. You'll learn about different merge strategies, how to resolve merge conflicts, and best practices for keeping your git history clean.
Your progress is saved in this browser, on this device only.