{"course":{"slug":"building-apps-with-ai","title":"Building Apps with AI","url":"https://addaly.com/learn/building-apps-with-ai","level":"beginner","track":"build"},"lesson":{"slug":"branches-for-the-risky-change","title":"Branches for the risky change","url":"https://addaly.com/learn/building-apps-with-ai/branches-for-the-risky-change","position":40,"of":87,"minutes":8,"answer":"A branch is a movable name for a commit, so an agent's failed afternoon on a branch costs one delete command and main never saw it.","keyIdea":"A branch is a movable name for a commit, so an agent's failed afternoon on a branch costs one delete command and main never saw it."},"body":{"format":"markdown","text":"## A branch is a sticky note\n\nInside your project, `.git/refs/heads/main` is a file containing forty-one bytes: the id of a commit and a newline. That is a branch. It is a name that points at a commit, and when you commit on that branch the name moves forward to the new one.\n\n`main` is not special. It is the default name and nothing more. Creating a branch writes another forty-one-byte file, which is why it is instant and free, and why the advice in this lesson is to use them more often than you would guess.\n\n```bash\ngit switch -c payments      # create and move to it (older form: git checkout -b)\ngit branch                  # list branches; the * marks where you are\ngit switch main             # go back\n```\n\n## What travels with you\n\nYour uncommitted edits are in the working tree, and the working tree belongs to no branch. Switch branches and they come along. Git refuses the switch only when it would have to overwrite a file you have edited with a different version from the target branch; then it says so and stops, and the answer is to commit or to stash.\n\nThe earlier lesson used `git stash` to set work aside for a test. The same command lets you park half-finished work, switch to main to fix something urgent, and return with `git stash pop`. A stash is a stack; `git stash list` shows what is parked. Forgotten stashes are the common way work goes missing, so pop them the same day.\n\n## Merging back\n\n```bash\ngit switch main\ngit merge payments\ngit branch -d payments      # tidy up once merged\n```\n\nTwo things can happen at the merge. If main has not moved since you branched, git slides the `main` name forward to your latest commit: a fast-forward, no new commit made. If main has moved, git makes a merge commit with two parents, one from each line of work. Both are normal.\n\n`git branch -d` refuses to delete a branch whose commits are not merged anywhere. `-D` deletes it regardless. That capital letter is the one to use on purpose, and it is the point of the next section.\n\n## One branch per agent task\n\nThis is the single most protective habit in the course for people working with an agent.\n\nBefore you hand an agent a feature, `git switch -c feature-name`. Let it work. When it goes well, merge. When it goes badly (three hours, forty files, an app that will not start) the exit is two commands:\n\n```bash\ngit switch main\ngit branch -D feature-name\n```\n\nThe mess is gone. Main is exactly what it was this morning, because main was never on the receiving end. Compare that with the alternative of picking through forty files deciding what to keep.\n\nBranch for anything you might abandon or that will take more than one session: a redesign, swapping a library, \"let us try Postgres instead\". Do not branch for a one-line fix; the overhead is real and the protection is not needed.\n\n## Two folders at once\n\nA branch checked out in one folder cannot be checked out in another. `git worktree add ../app-payments payments` creates a second folder with the `payments` branch in it, sharing the same history. Two agents can work on two features without editing the same files, and main stays runnable in its own folder while a branch is broken.\n\nThe cost is that each worktree needs its own `node_modules`; a symlink between them breaks some build tools, so install separately or copy.\n\n## The word you will hear: rebase\n\nRebase rewrites your branch so its commits appear to start from the current tip of main, giving a straight-line history instead of merge commits. It does this by making new commits with new ids. That is fine on a branch only you have; it is the reason for the one rule people learn the hard way: never rebase commits that have been pushed and that somebody else may have built on.\n\nYou can build real software for years without rebasing. It is mentioned here so that when an agent proposes it, you know it rewrites history and can decline.\n\n## Branch names are a message\n\n`fix-cancel-button` beats `fix`. In a fortnight the list of branches is the list of things you started, and the name is all you have. Most hosts also turn a branch into a preview URL that carries the name, which is where the shipping half of this block picks up."},"check":{"question":"You are on main with uncommitted edits and want to try a risky refactor without losing them. You run git switch -c refactor. What happens to the edits?","options":[{"text":"They come with you, still uncommitted, on the new branch.","correct":true},{"text":"Git refuses to switch because the working tree is not clean.","correct":false,"tempting":"Git refuses only when switching would overwrite an edited file with a different version; a new branch starts from the same commit, so nothing is overwritten."},{"text":"They stay on main and the new branch starts from the last commit.","correct":false,"tempting":"Uncommitted edits live in the working tree, which belongs to no branch; there is nothing for them to stay on."},{"text":"Git stashes them automatically and restores them when you return.","correct":false,"tempting":"Stashing is always a manual step; git never sets your work aside without being told."}]},"prev":{"slug":"three-ways-back","title":"Three ways back, and the undo for undo","url":"https://addaly.com/learn/building-apps-with-ai/three-ways-back"},"next":{"slug":"github-and-the-remote","title":"GitHub, and what a remote is for","url":"https://addaly.com/learn/building-apps-with-ai/github-and-the-remote"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'Branches for the risky change', in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/branches-for-the-risky-change (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"Branches for the risky change","courseTitle":"Building Apps with AI","module":{"index":5,"slug":"save-points-and-shipping","title":"Save points, and shipping to a stranger"},"answer":null,"keyIdea":"A branch is a movable name for a commit, so an agent’s failed afternoon on a branch costs one delete command and main never saw it.","hero":{"kind":"plate","image":null,"alt":null,"caption":null},"blocks":[{"t":"h2","id":"a-branch-is-a-sticky-note","runs":[{"text":"A branch is a sticky note"}]},{"t":"p","runs":[{"text":"Inside your project, "},{"text":".git/refs/heads/main","code":true},{"text":" is a file containing forty-one bytes: the id of a commit and a newline. That is a branch. It is a name that points at a commit, and when you commit on that branch the name moves forward to the new one."}]},{"t":"p","runs":[{"text":"main","code":true},{"text":" is not special. It is the default name and nothing more. Creating a branch writes another forty-one-byte file, which is why it is instant and free, and why the advice in this lesson is to use them more often than you would guess."}]},{"t":"code","lang":"bash","label":"Bash","text":"git switch -c payments      # create and move to it (older form: git checkout -b)\ngit branch                  # list branches; the * marks where you are\ngit switch main             # go back"},{"t":"h2","id":"what-travels-with-you","runs":[{"text":"What travels with you"}]},{"t":"p","runs":[{"text":"Your uncommitted edits are in the working tree, and the working tree belongs to no branch. Switch branches and they come along. Git refuses the switch only when it would have to overwrite a file you have edited with a different version from the target branch; then it says so and stops, and the answer is to commit or to stash."}]},{"t":"p","runs":[{"text":"The earlier lesson used "},{"text":"git stash","code":true},{"text":" to set work aside for a test. The same command lets you park half-finished work, switch to main to fix something urgent, and return with "},{"text":"git stash pop","code":true},{"text":". A stash is a stack; "},{"text":"git stash list","code":true},{"text":" shows what is parked. Forgotten stashes are the common way work goes missing, so pop them the same day."}]},{"t":"h2","id":"merging-back","runs":[{"text":"Merging back"}]},{"t":"code","lang":"bash","label":"Bash","text":"git switch main\ngit merge payments\ngit branch -d payments      # tidy up once merged"},{"t":"p","runs":[{"text":"Two things can happen at the merge. If main has not moved since you branched, git slides the "},{"text":"main","code":true},{"text":" name forward to your latest commit: a fast-forward, no new commit made. If main has moved, git makes a merge commit with two parents, one from each line of work. Both are normal."}]},{"t":"p","runs":[{"text":"git branch -d","code":true},{"text":" refuses to delete a branch whose commits are not merged anywhere. "},{"text":"-D","code":true},{"text":" deletes it regardless. That capital letter is the one to use on purpose, and it is the point of the next section."}]},{"t":"h2","id":"one-branch-per-agent-task","runs":[{"text":"One branch per agent task"}]},{"t":"p","runs":[{"text":"This is the single most protective habit in the course for people working with an agent."}]},{"t":"p","runs":[{"text":"Before you hand an agent a feature, "},{"text":"git switch -c feature-name","code":true},{"text":". Let it work. When it goes well, merge. When it goes badly (three hours, forty files, an app that will not start) the exit is two commands:"}]},{"t":"code","lang":"bash","label":"Bash","text":"git switch main\ngit branch -D feature-name"},{"t":"p","runs":[{"text":"The mess is gone. Main is exactly what it was this morning, because main was never on the receiving end. Compare that with the alternative of picking through forty files deciding what to keep."}]},{"t":"p","runs":[{"text":"Branch for anything you might abandon or that will take more than one session: a redesign, swapping a library, “let us try Postgres instead”. Do not branch for a one-line fix; the overhead is real and the protection is not needed."}]},{"t":"h2","id":"two-folders-at-once","runs":[{"text":"Two folders at once"}]},{"t":"p","runs":[{"text":"A branch checked out in one folder cannot be checked out in another. "},{"text":"git worktree add ../app-payments payments","code":true},{"text":" creates a second folder with the "},{"text":"payments","code":true},{"text":" branch in it, sharing the same history. Two agents can work on two features without editing the same files, and main stays runnable in its own folder while a branch is broken."}]},{"t":"p","runs":[{"text":"The cost is that each worktree needs its own "},{"text":"node_modules","code":true},{"text":"; a symlink between them breaks some build tools, so install separately or copy."}]},{"t":"h2","id":"the-word-you-will-hear-rebase","runs":[{"text":"The word you will hear: rebase"}]},{"t":"p","runs":[{"text":"Rebase rewrites your branch so its commits appear to start from the current tip of main, giving a straight-line history instead of merge commits. It does this by making new commits with new ids. That is fine on a branch only you have; it is the reason for the one rule people learn the hard way: never rebase commits that have been pushed and that somebody else may have built on."}]},{"t":"p","runs":[{"text":"You can build real software for years without rebasing. It is mentioned here so that when an agent proposes it, you know it rewrites history and can decline."}]},{"t":"h2","id":"branch-names-are-a-message","runs":[{"text":"Branch names are a message"}]},{"t":"p","runs":[{"text":"fix-cancel-button","code":true},{"text":" beats "},{"text":"fix","code":true},{"text":". In a fortnight the list of branches is the list of things you started, and the name is all you have. Most hosts also turn a branch into a preview URL that carries the name, which is where the shipping half of this block picks up."}]}],"check":{"question":[{"text":"You are on main with uncommitted edits and want to try a risky refactor without losing them. You run git switch -c refactor. What happens to the edits?"}],"options":[{"text":[{"text":"They come with you, still uncommitted, on the new branch."}],"correct":true,"tempting":null},{"text":[{"text":"Git refuses to switch because the working tree is not clean."}],"correct":false,"tempting":[{"text":"Git refuses only when switching would overwrite an edited file with a different version; a new branch starts from the same commit, so nothing is overwritten."}]},{"text":[{"text":"They stay on main and the new branch starts from the last commit."}],"correct":false,"tempting":[{"text":"Uncommitted edits live in the working tree, which belongs to no branch; there is nothing for them to stay on."}]},{"text":[{"text":"Git stashes them automatically and restores them when you return."}],"correct":false,"tempting":[{"text":"Stashing is always a manual step; git never sets your work aside without being told."}]}],"order":[1,3,0,2],"why":null},"prev":{"slug":"three-ways-back","title":"Three ways back, and the undo for undo","minutes":9},"next":{"slug":"github-and-the-remote","title":"GitHub, and what a remote is for","minutes":9}}}