{"id":"l-git-2-1","courseId":"git-github","lang":"en","kind":"lesson","summary":"Create, switch, rename and delete branches knowing that each is a movable pointer to a commit, and recover cleanly from a detached HEAD.","html":"<p>In older version control systems a branch was a full copy of the project, slow to make and painful to combine, so people avoided them. In Git a branch costs almost nothing. That changes how you work: every idea, fix or experiment on your portfolio can get its own branch, and throwing one away is as cheap as making it.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">A branch is a sticky note</h2>\n<p>Look inside your repository:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">cat</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> .git/refs/heads/main</span></span></code></pre></div>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Text</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>c39be1142d6f0a8e7b1c5d93e2f4a0b6c8d7e912</code></pre></div>\n<p>That’s the whole <code dir=\"ltr\">main</code> branch: a file containing one commit ID. A <strong>branch</strong> is a named, movable pointer to a commit. The history behind it isn’t stored in the branch; it’s found by following parent links from that commit, as you did in the last lesson.</p>\n<p>So how does Git know which branch you’re on? Another small file:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">cat</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> .git/HEAD</span></span></code></pre></div>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Text</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>ref: refs/heads/main</code></pre></div>\n<p><strong>HEAD</strong> is a pointer to a pointer. It normally names a branch, and that branch names a commit. When you commit, Git creates the new commit with the current one as its parent, then moves the branch HEAD names to the new commit. HEAD itself doesn’t change; it’s still “on <code dir=\"ltr\">main</code>”, and <code dir=\"ltr\">main</code> has moved forward.</p>\n<p>You don’t need to read these files day to day (in older or busier repositories, branch IDs may be packed into <code dir=\"ltr\">.git/packed-refs</code> instead), but seeing them once removes the mystery. Everything in this section is about moving these sticky notes around a graph.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">Making and moving between branches</h2>\n<p>Your next portfolio change is a site footer. Give it a branch:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> switch</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -c</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> footer</span></span></code></pre></div>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"5\"><div class=\"code-head\"><span class=\"code-title\">Text</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>Switched to a new branch 'footer'</code></pre></div>\n<p><code dir=\"ltr\">-c</code> creates the branch at your current commit and switches to it. The two-step version is <code dir=\"ltr\">git branch footer</code> followed by <code dir=\"ltr\">git switch footer</code>. Now commit some work:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"6\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> add</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> index.html</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> styles.css</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> commit</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -m</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Add site footer with contact links\"</span></span></code></pre></div>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 260\" role=\"img\" aria-labelledby=\"l-git-2-1-t1\"><defs><marker id=\"arrow-l-git-2-1-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-git-2-1-t1\">Before: commits a1c9, b2e0, c39b in a row; main and footer both point at c39b; HEAD points at footer. After committing: a new commit f1a3 follows c39b; footer and HEAD moved to f1a3; main stayed on c39b.</title>\n  <text class=\"d-label-strong\" x=\"20\" y=\"30\">Before</text>\n  <circle class=\"d-box\" cx=\"60\" cy=\"90\" r=\"24\"/>\n  <text class=\"d-code\" x=\"60\" y=\"95\" text-anchor=\"middle\">a1c9</text>\n  <circle class=\"d-box\" cx=\"150\" cy=\"90\" r=\"24\"/>\n  <text class=\"d-code\" x=\"150\" y=\"95\" text-anchor=\"middle\">b2e0</text>\n  <circle class=\"d-box\" cx=\"240\" cy=\"90\" r=\"24\"/>\n  <text class=\"d-code\" x=\"240\" y=\"95\" text-anchor=\"middle\">c39b</text>\n  <path class=\"d-line\" d=\"M126 90 L84 90\"/>\n  <path class=\"d-line\" d=\"M216 90 L174 90\"/>\n  <rect class=\"d-box-accent\" x=\"200\" y=\"130\" width=\"80\" height=\"30\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"240\" y=\"150\" text-anchor=\"middle\">main</text>\n  <rect class=\"d-box-accent\" x=\"200\" y=\"170\" width=\"80\" height=\"30\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"240\" y=\"190\" text-anchor=\"middle\">footer</text>\n  <rect class=\"d-box-warn\" x=\"200\" y=\"210\" width=\"80\" height=\"30\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"240\" y=\"230\" text-anchor=\"middle\">HEAD</text>\n  <path class=\"d-line\" d=\"M240 114 L240 130\"/>\n  <text class=\"d-label-strong\" x=\"370\" y=\"30\">After git commit</text>\n  <circle class=\"d-box\" cx=\"400\" cy=\"90\" r=\"24\"/>\n  <text class=\"d-code\" x=\"400\" y=\"95\" text-anchor=\"middle\">a1c9</text>\n  <circle class=\"d-box\" cx=\"490\" cy=\"90\" r=\"24\"/>\n  <text class=\"d-code\" x=\"490\" y=\"95\" text-anchor=\"middle\">b2e0</text>\n  <circle class=\"d-box\" cx=\"580\" cy=\"90\" r=\"24\"/>\n  <text class=\"d-code\" x=\"580\" y=\"95\" text-anchor=\"middle\">c39b</text>\n  <circle class=\"d-box-primary\" cx=\"660\" cy=\"90\" r=\"24\"/>\n  <text class=\"d-code\" x=\"660\" y=\"95\" text-anchor=\"middle\">f1a3</text>\n  <path class=\"d-line\" d=\"M466 90 L424 90\"/>\n  <path class=\"d-line\" d=\"M556 90 L514 90\"/>\n  <path class=\"d-line\" d=\"M636 90 L604 90\"/>\n  <rect class=\"d-box-accent\" x=\"540\" y=\"130\" width=\"80\" height=\"30\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"580\" y=\"150\" text-anchor=\"middle\">main</text>\n  <path class=\"d-line\" d=\"M580 114 L580 130\"/>\n  <rect class=\"d-box-accent\" x=\"620\" y=\"170\" width=\"80\" height=\"30\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"660\" y=\"190\" text-anchor=\"middle\">footer</text>\n  <rect class=\"d-box-warn\" x=\"620\" y=\"210\" width=\"80\" height=\"30\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"660\" y=\"230\" text-anchor=\"middle\">HEAD</text>\n  <path class=\"d-line\" d=\"M660 114 L660 170\"/>\n</svg><figcaption>Committing moves the branch that HEAD is attached to</figcaption></figure>\n<p><code dir=\"ltr\">main</code> is untouched. Switch back and the footer disappears from your files; switch to <code dir=\"ltr\">footer</code> again and it returns:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"7\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> switch</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> main</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">      # working tree now matches main's snapshot</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> switch</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> footer</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">    # and now footer's</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> switch</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> -</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">         # back to whichever branch you were on before</span></span></code></pre></div>\n<p>Switching rewrites the files in your working tree to match the target snapshot. Uncommitted changes come along if they don’t clash with the target. If they would be overwritten, Git refuses to switch and tells you to commit or stash first. That refusal is protecting you; don’t look for a way around it. Commit the work, or wait for the stash lesson in section 4.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">Tip</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Branch even when you work alone</span></p>\n<p>It’s tempting to commit straight to <code dir=\"ltr\">main</code> on a solo project. A branch per change keeps <code dir=\"ltr\">main</code> always deployable: if the footer turns out badly, you delete the branch and nothing on <code dir=\"ltr\">main</code> ever knew about it. It’s also the exact habit pull requests need in section 3, so practise it now while the stakes are low.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">Housekeeping</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"8\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> branch</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">                 # list local branches; * marks the current one</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> branch</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -v</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">              # with the commit each points to</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> branch</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -m</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> footer</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> site-footer</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">   # rename</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> branch</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -d</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> site-footer</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">  # delete, only if its work is merged</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> branch</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -D</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> experiment</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">   # force-delete, merged or not</span></span></code></pre></div>\n<p><code dir=\"ltr\">-d</code> refuses to delete a branch whose commits aren’t merged into your current branch (or into the branch’s upstream, once it has one), which is a useful safety net. <code dir=\"ltr\">-D</code> skips the check. Use it only when you’re sure the work is unwanted.</p>\n<p>Name branches for what they do: <code dir=\"ltr\">footer</code>, <code dir=\"ltr\">fix-mobile-nav</code>, <code dir=\"ltr\">projects-grid</code>. Many teams add a prefix such as <code dir=\"ltr\">feat/</code> or <code dir=\"ltr\">fix/</code>; slashes are allowed in branch names.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">Borrowing one file from another branch</h2>\n<p>Sometimes you want one file from another branch without the rest of its work. <code dir=\"ltr\">git restore</code> can read from any commit:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"9\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> restore</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --source=dark-mode</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> styles.css</span></span></code></pre></div>\n<p>That overwrites <code dir=\"ltr\">styles.css</code> in your working tree with the version on <code dir=\"ltr\">dark-mode</code>. Check it with <code dir=\"ltr\">git diff</code>, then stage and commit it on your current branch. You’ll still see older tutorials use <code dir=\"ltr\">git checkout</code> for both switching and restoring; Git 2.23 split those two jobs into <code dir=\"ltr\">git switch</code> and <code dir=\"ltr\">git restore</code>, which are harder to confuse.</p>\n<h2 id=\"sec-5\" tabindex=\"-1\">Detached HEAD</h2>\n<p>You can point HEAD straight at a commit instead of a branch, to look at an old version of the site:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"10\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> switch</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --detach</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> a1c9d72</span></span></code></pre></div>\n<p>Git warns you’re in <strong>detached HEAD</strong> state. Looking around is perfectly safe. The risk is committing there: new commits belong to no branch, so when you switch away, nothing points at them and they quietly drop out of <code dir=\"ltr\">git log</code>.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">Common mistake</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Committing in detached HEAD, then switching away</span></p>\n<p>You check out an old commit, fix something, commit, run <code dir=\"ltr\">git switch main</code>, and the fix seems gone. Before switching away, run <code dir=\"ltr\">git switch -c old-fix</code> to put a branch on your new commit. If you already switched, Git printed the lost commit’s ID as a warning; <code dir=\"ltr\">git switch -c old-fix &lt;that-id&gt;</code> rescues it. The reflog in section 4 finds it even if you missed the warning.</p>\n</aside>\n<p>Your <code dir=\"ltr\">footer</code> branch is ready and <code dir=\"ltr\">main</code> hasn’t moved. Next you’ll bring the two together with a merge.</p>\n","toc":[{"id":"sec-1","text":"A branch is a sticky note","level":2},{"id":"sec-2","text":"Making and moving between branches","level":2},{"id":"sec-3","text":"Housekeeping","level":2},{"id":"sec-4","text":"Borrowing one file from another branch","level":2},{"id":"sec-5","text":"Detached HEAD","level":2}],"takeaways":["A branch is a tiny file holding one commit ID; creating one copies nothing and takes milliseconds.","HEAD names the branch you’re on, and each new commit moves that branch forward while HEAD comes along.","<code dir=\"ltr\">git switch -c &lt;name&gt;</code> creates a branch at the current commit and switches to it in one step.","A detached HEAD points straight at a commit; save any work made there with <code dir=\"ltr\">git switch -c &lt;name&gt;</code> before leaving.","<code dir=\"ltr\">git restore --source=&lt;branch&gt; &lt;file&gt;</code> copies one file from another branch without switching to it."],"further":[{"title":"Branches in a Nutshell (Pro Git)","url":"https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell"},{"title":"git switch reference","url":"https://git-scm.com/docs/git-switch"},{"title":"git branch reference","url":"https://git-scm.com/docs/git-branch"}],"quiz":[{"q":"<p>You’re on <code dir=\"ltr\">main</code> at commit <code dir=\"ltr\">b2e0</code> and run <code dir=\"ltr\">git switch -c footer</code>, then commit <code dir=\"ltr\">f1a3</code>. Where do <code dir=\"ltr\">main</code> and <code dir=\"ltr\">footer</code> point now?</p>","options":[{"text":"Both point at <code dir=\"ltr\">f1a3</code>, because they were created from the same commit.","why":"Branches don’t stay linked. Only the branch HEAD is attached to moves when you commit."},{"text":"<code dir=\"ltr\">main</code> points at <code dir=\"ltr\">f1a3</code> and <code dir=\"ltr\">footer</code> at <code dir=\"ltr\">b2e0</code>.","why":"That’s reversed. You switched to <code dir=\"ltr\">footer</code>, so <code dir=\"ltr\">footer</code> is the one that moves."},{"text":"Neither moved; branches only move when you push.","why":"Committing moves the current branch immediately. Pushing is about copying commits to a remote."},{"text":"<code dir=\"ltr\">main</code> still points at <code dir=\"ltr\">b2e0</code>; <code dir=\"ltr\">footer</code> moved to <code dir=\"ltr\">f1a3</code>.","why":"Correct. HEAD was attached to <code dir=\"ltr\">footer</code>, so the new commit advanced <code dir=\"ltr\">footer</code> and left <code dir=\"ltr\">main</code> where it was."}],"answer":3},{"q":"<p>What does the file <code dir=\"ltr\">.git/HEAD</code> contain while you’re on the <code dir=\"ltr\">footer</code> branch?</p>","options":[{"text":"<code dir=\"ltr\">ref: refs/heads/footer</code>","why":"Correct. HEAD normally holds the name of a branch, not a commit ID. That indirection is what lets commits move the branch."},{"text":"The 40-character ID of the latest commit on <code dir=\"ltr\">footer</code>.","why":"That’s what the branch file <code dir=\"ltr\">.git/refs/heads/footer</code> holds. HEAD points at the branch, and the branch points at the commit."},{"text":"A list of every branch in the repository.","why":"<code dir=\"ltr\">git branch</code> builds that list by reading the branch files. HEAD stores only where you are."}],"answer":0},{"q":"<p>You checked out an old commit to look around, made a quick fix and committed it. Git says you’re in “detached HEAD” state. How do you keep that commit?</p>","options":[{"text":"Run <code dir=\"ltr\">git switch main</code>; the commit comes with you.","why":"Switching away leaves the commit behind with no branch pointing at it. It becomes easy to lose and is eventually garbage-collected."},{"text":"Nothing to do; every commit is kept on <code dir=\"ltr\">main</code> automatically.","why":"In detached HEAD, new commits belong to no branch at all, which is exactly the risk."},{"text":"Run <code dir=\"ltr\">git switch -c old-fix</code> to put a branch on it.","why":"Correct. A branch pointing at the commit makes it reachable, so it’s safe. You can merge it later."},{"text":"Run <code dir=\"ltr\">git commit --attach</code>.","why":"There’s no <code dir=\"ltr\">--attach</code> option. Attaching work to history means creating a branch at it."}],"answer":2},{"q":"<p>Your <code dir=\"ltr\">dark-mode</code> branch has a finished <code dir=\"ltr\">styles.css</code> you want on <code dir=\"ltr\">footer</code> too, without merging the rest of <code dir=\"ltr\">dark-mode</code>. You’re on <code dir=\"ltr\">footer</code>. Which command does it?</p>","options":[{"text":"<code dir=\"ltr\">git switch dark-mode styles.css</code>","why":"<code dir=\"ltr\">git switch</code> changes branches. It doesn’t take file paths."},{"text":"<code dir=\"ltr\">git restore --source=dark-mode styles.css</code>","why":"Correct. It writes <code dir=\"ltr\">styles.css</code> from the <code dir=\"ltr\">dark-mode</code> snapshot into your working tree; then you review, stage and commit it on <code dir=\"ltr\">footer</code>."},{"text":"<code dir=\"ltr\">git branch dark-mode styles.css</code>","why":"That form tries to create a branch named <code dir=\"ltr\">dark-mode</code> starting at a commit called <code dir=\"ltr\">styles.css</code>, which fails."},{"text":"<code dir=\"ltr\">git merge dark-mode -- styles.css</code>","why":"Merges always combine whole commits. There’s no way to merge a single file."}],"answer":1}],"exercise":{"kind":"fill","language":"bash","template":"git switch {{0}} footer          # create the branch and move onto it\ngit add index.html styles.css\ngit commit -m \"Add site footer with contact links\"\ngit switch {{1}}                 # back to main to check it's untouched\ngit branch -m footer {{2}}       # rename to site-footer","blanks":[{"answers":["-c","--create"]},{"answers":["main","-"]},{"answers":["site-footer"]}],"title":"Branch for the footer","prompt":"<p>Fill in the blanks: create a <code dir=\"ltr\">footer</code> branch and switch to it in one command, commit the footer, go back to <code dir=\"ltr\">main</code> to confirm it hasn’t changed, then rename the branch to <code dir=\"ltr\">site-footer</code>.</p>\n","hints":["<code dir=\"ltr\">git switch</code> takes a flag that creates the branch first. It’s short for create.","You can name the branch you want to go back to, or use the shortcut for the previous branch.","<code dir=\"ltr\">git branch -m &lt;old&gt; &lt;new&gt;</code> renames a branch."],"explanation":"<p><code dir=\"ltr\">git switch -c footer</code> creates <code dir=\"ltr\">footer</code> at the current commit and attaches HEAD to it, so the commit moves <code dir=\"ltr\">footer</code> and leaves <code dir=\"ltr\">main</code> alone. <code dir=\"ltr\">git switch main</code> (or <code dir=\"ltr\">git switch -</code>, which means the previous branch) rewrites the working tree to <code dir=\"ltr\">main</code>’s snapshot. <code dir=\"ltr\">git branch -m footer site-footer</code> renames the pointer; the commits don’t change at all.</p>\n","checkLabels":{}},"words":760,"readMinutes":4}