Skip to content
Ameen Abozaid
PublishedBEG-046-L04

Branches

  • Lesson 4 of 8
  • 10 min read
  • Beginner
On This Lesson 11 topics

Lesson Overview

So far your history is one straight line of commits. Real work is not that tidy. You want to try a new feature while the working version stays safe. You want to fix an urgent bug while a half-finished feature sits in your files. You and a teammate each need your own space to work.

A branch solves this: it is a separate line of commits that starts from some point in the history. You can build and break things there, and the main line stays working. When the work is good, you combine it back (that is the next lesson).

In the album analogy, a branch is a parallel copy of the album where you can add new pages without touching the original. In this lesson you will create, list, switch, and delete branches, and learn the one thing that surprises beginners: what happens to your files when you switch.

You need a repository with at least one commit (lessons L02 and L03). Outputs below come from Git 2.44; hashes will differ for you.

Learning Objectives

By the end of this lesson you will be able to:

  • Explain what a branch is and why teams keep main working.
  • List branches with git branch and see which one you are on.
  • Create and switch to a branch with git switch -c, and switch back with git switch.
  • Predict what your files look like after switching branches.
  • Draw a history with two diverging branches and read it with git log --graph.
  • Delete a branch with git branch -d and explain why Git sometimes refuses.
  • Choose a small, descriptive branch name.

Written Explanation

What a branch is

A branch is a named line of development. Technically, Git stores a branch as a small pointer to a commit. When you commit while "on" a branch, that pointer moves forward to the new commit. Creating a branch is therefore cheap and fast: Git does not copy your project, it just adds another pointer. That is why teams create branches freely, often one per task.

HEAD is Git's marker for "where you are now": it points at the branch you are on. In git log --oneline --decorate, you see it as (HEAD -> main).

The default branch of a project is usually called main (older repositories often use master; lesson L02 explained why). By convention, main holds code that works. New work happens on other branches and is brought into main once it is ready.

Listing branches

bash
git branch
text
* main

The * marks the branch you are on. With one branch, that is all you see. git branch -v adds each branch's latest commit.

Creating and switching: git switch

Create a branch and move to it in one step:

bash
git switch -c add-interest
text
Switched to a new branch 'add-interest'
bash
git branch
text
* add-interest
  main

-c stands for "create". To go back to an existing branch, leave -c off:

bash
git switch main
text
Switched to branch 'main'

Older tutorials use git checkout -b name and git checkout name for the same two jobs. They still work; git switch is the newer, clearer command for moving between branches, and the one this course uses. If you are on a very old Git that does not know switch, update Git or use checkout.

What happens to your files when you switch

This is the key surprise. Your working folder always shows the files of the branch you are on. When you switch, Git rewrites the files in your folder to match the other branch.

Suppose on add-interest you create and commit Interest.java. Then:

bash
ls *.java
text
Account.java
Interest.java
bash
git switch main
ls *.java
text
Account.java

Interest.java is gone from the folder. It is not deleted: it lives safely in the commits of add-interest. Switch back and it reappears. If your editor or IDE has the file open, it will update or ask you to reload; the exact behaviour depends on the tool.

Uncommitted changes. Git is careful with edits you have not committed. If your uncommitted changes do not clash with the other branch, Git carries them along to the new branch. If they would be overwritten, Git refuses to switch and tells you. The safest habit: commit (or deliberately set aside) your work before switching, so you always know which branch owns which change.

Diverging histories

Create a branch, commit on it, switch to main, and commit there too. Now the histories have diverged. git log --oneline --graph --all --decorate draws them:

text
* 4b9cb47 (feature) Add B on feature
| * 38db0ef (HEAD -> main) Edit A on main
|/  
* 42d209f Add A

Read it from the bottom: both branches share the commit Add A, then each has its own commit. The * marks commits and | and / show the lines splitting. --all shows every branch, not only the current one; --decorate labels where each branch points. This picture is the starting point of the next lesson, where the two lines are joined.

Deleting a branch

After the work of a branch is merged, the branch name is no longer needed:

bash
git branch -d add-interest

If the branch has commits that are not in your current branch, Git refuses:

text
error: the branch 'add-interest' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D add-interest'

That refusal is a safety net: deleting would leave commits that nothing points to. -D (capital) forces the deletion. Use it only when you are sure the work is not needed.

Good branch names and habits

  • Name by purpose: add-interest, fix-negative-balance. Avoid test, new, stuff.
  • Use lowercase and hyphens; avoid spaces.
  • One purpose per branch keeps changes easy to review and easy to merge.
  • Keep branches short-lived. A branch open for weeks drifts far from main, which makes the later merge harder.

Examples

Example 1: Your first branch (simple)

bash
git switch -c greeting

Edit Hello.java, then:

bash
git add Hello.java
git commit -m "Print a full greeting"
git switch main

Open Hello.java: it shows the old text, because main has not got the change yet. Switch back with git switch greeting and the new text returns. Nothing was lost; you were looking at two different pages of the album.

Example 2: A feature branch for the bank (practical)

You want to add interest to the Bank Accounts project, but main should keep compiling at all times.

bash
git switch -c add-interest

You create Interest.java and commit it:

bash
git add Interest.java
git commit -m "Add Interest class with yearly interest"

An hour later you find that a typo in the account number check needs an urgent fix. Switch to main, fix it there, commit, and switch back to add-interest to continue. Each task has its own place, and neither disturbs the other.

Example 3: Uncommitted changes meet a switch (realistic)

You edit Account.java on main and forget to commit. You run:

bash
git switch -c wip
git status -s
text
 M Account.java

Because the new branch starts at the same commit, your edit comes along and shows as modified on wip. You commit it there, switch back to main, and the edit is not on main any more: it belongs to wip. The lesson: an uncommitted change is not owned by any branch yet, and it moves with you. To avoid surprises, commit before you switch, or create the branch first, then edit.

Backend Insight

Backend teams are rarely alone in a repository, and the code on main is often what gets built and deployed. A rule seen in many teams is "never commit unfinished work directly to main": each task gets a branch, is reviewed, and only then joins main. This is the basis of the pull-request workflow you will meet in BEG-047 and JNR-053.

Branches are also how you work on two things at once without risk: an urgent production bug fix goes on its own short branch from main, while your long feature stays on another. Small branches with one purpose are easy to read, test, and, if needed, discard, which reduces the risk of every release.

Common Mistakes

Mistake 1: Working on main by habit

  • Incorrect: editing and committing straight on main while a feature is half done.
  • Correct: git switch -c feature-name first, then edit.

How to avoid it: run git status or git branch at the start of a session to check where you are. git status prints On branch ... on its first line.

Mistake 2: Thinking switching deletes your files

When a file disappears after git switch, it is just not part of that branch. Switch back and it returns. Panic is not needed.

Mistake 3: Forgetting where you are

Beginners often commit on the wrong branch. Always check the branch name before committing. Many terminals and IDEs can show it in the prompt or status bar; the setup varies by tool.

Mistake 4: Using -D to silence a refusal

If git branch -d says "not fully merged", read why. Deleting with -D throws away commits you may need.

Exercises

Level A: Foundation

A1. What does the * mean in git branch output?

Show solution A1

A1. It marks the branch you are currently on.

A2. Write the command that creates a branch named fix-rounding and switches to it.

Show solution A2

A2. git switch -c fix-rounding.

A3. Write the command that moves you back to main.

Show solution A3

A3. git switch main.

Level B: Application

B1. In a repository, create a branch greeting, add a new file Bye.java, and commit it. Switch to main. Does Bye.java exist? Does it exist after you switch back? Explain.

Show solution B1

B1. After switching to main, Bye.java does not exist in the folder, because its commit is only on greeting. After git switch greeting it exists again. Switching rewrites the working files to match the branch; nothing was deleted.

B2. Create a branch, make one commit on it, switch to main, and make one commit there too. Which command draws both lines, and what does the output look like?

Show solution B2

B2. git log --oneline --graph --all --decorate. The output shows a shared commit at the bottom and two lines splitting from it, one commit each, with branch names beside the latest commits.

B3. Pick better names for these branches: test, new, my-branch. The work is: adding a deposit limit, fixing a crash on empty names, and renaming classes.

Show solution B3

B3. Examples: add-deposit-limit, fix-empty-name-crash, rename-account-classes. Any name describing the purpose is fine.

Level C: Challenge

C1. You are on main and you edit Account.java but have not committed. You then realise the change belongs on a new branch called add-limit. What do you run, and where does the change end up? Where will it not be?

Show solution C1

C1. Run git switch -c add-limit. The uncommitted change comes with you and is a modification on add-limit. Commit it there. It is not on main, because it was never committed there.

C2. git branch -d add-interest prints "not fully merged". Explain what that means, and describe two different choices you have.

Show solution C2

C2. The branch has commits that the current branch does not contain, so deleting it would leave them unreachable. Choice one: merge the branch first (next lesson), then delete with -d. Choice two: if you are certain the work is not needed, delete it anyway with git branch -D add-interest.

Mini Challenge

In a practice repository, create two branches from main with different purposes (for example add-farewell and fix-typo). Make one commit on each. Return to main and draw, on paper, the picture of the three lines of history you expect. Then run git log --oneline --graph --all --decorate and compare.

Check your work: your drawing and the real graph agree; each branch name describes its purpose; you checked git status before every commit to confirm the branch.

Summary & Next Lesson

Key takeaways

  • A branch is a separate line of commits; creating one is cheap.
  • git switch -c name creates and switches; git switch name moves between branches; git branch lists them.
  • Switching rewrites your working files to match the branch; nothing is lost.
  • Commit before you switch; uncommitted edits travel with you.
  • git branch -d refuses to delete unmerged work; -D forces it.
  • Keep main working and use short, purposeful branches.

Next lesson

Next is "Merging and conflicts": you will bring a branch's commits back into main, and learn what to do when both branches changed the same lines.

Self-check

  1. Which command creates and switches to a new branch?
  2. What does HEAD point at?
  3. A file vanished after git switch main. Is it deleted?
  4. Why does git branch -d sometimes refuse?
  5. Why keep branches small?
Show answers
  1. git switch -c name.
  2. The branch (and so the commit) you are currently on.
  3. No. It is not part of main; it is safe in the other branch.
  4. The branch contains commits not yet in the current branch, so deleting would lose them.
  5. They are easier to review and merge, and drift less from main.

References

  • Pro Git book, "Basic Branching and Merging". It supports creating and switching branches, that git branch -d removes merged branches, and the divergent-history picture. The page uses git checkout -b; git switch -c is the newer equivalent and I verified it by running it with Git 2.44.
  • Git documentation, git log. It supports --oneline and --graph. I read only the first part of the page.
  • Not verified from an official page: the claim that a branch is stored as a pointer to a commit, the exact conditions under which uncommitted changes are carried across a switch, and "many teams" avoid direct commits to main. These come from general Git knowledge and from running the commands.

Practice

Apply this lesson with the module's lab, exercises and quiz.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.