Branches
Overview
Teaching: 20 min
Exercises: 0 minQuestions
What are branches?
How can I work in parallel using branches?
Objectives
Understand why branches are useful for:
working on separate tasks in the same repository concurrently
trying multiple solutions to a problem
check-pointing versions of code
Merge branches back into the main branch
So far we’ve always been working in a straight timeline.
However, there are times when we might want to keep
our main work safe from experimental changes we are working on.
To do this we can use branches to work on separate tasks in parallel
without changing our current branch, main
.
You may not have noticed before, but the first branch made is called main
.
This is the default branch created when initializing a repository and
is often considered to be the “clean” or “working” version of a
repository’s code.
We can see what branches exist in a repository by typing
$ git branch
* main
The ‘*’ indicates which branch we are currently on.
In this lesson, Alfredo wants to create two new categories of recipes, one for starters and one for desserts. However, he does not want to work on the main branch because it is stable and he wants to keep it safe.
First let’s make the starters
branch. We use the same git branch
command but
add the name we want to give our new branch.
$ git branch starters
We can now check our work with the git branch
command:
$ git branch
* main
starters
We can see that we created the starters
branch but we are still in the main
branch. We can also see this in the output of the git status
command.
$ git status
On branch main
nothing to commit, working directory clean
To switch to the new branch we can use the checkout
command
we learned earlier and check our work with git branch
.
$ git checkout starters
$ git branch
main
* starters
We have previously used the checkout
command to checkout a file from a
specific commit using commit hashes, or HEAD
and the filename
(git checkout HEAD <file>
). The checkout
command can also be used to
checkout an entire previous version of the repository, updating all files in
the repository to match the state of a desired commit.
Branches allow us to do this using a human-readable name rather than memorizing
a commit hash. This name also typically gives purpose to the set of changes in
that branch. When we use the command git checkout <branch_name>
, we are using
a nickname to checkout a version of the repository that matches the most recent
commit in that branch (a.k.a. the HEAD
of that branch).
You can use git log
and ls
to see that the history and
files are the same as our main
branch. This will be true until
some changes are committed to our new branch.
Let’s create a starter recipe for olives. Use the command
touch olives.md
to create an empty file (but imagine we spent hours
working on this recipe!).
$ touch olives.md
Now we can add and commit the file to our branch.
$ git add olives.md
$ git commit -m "Wrote olives recipe"
[starters x792csa1] Wrote olives recipe
1 file changed, 1 insertion(+)
create mode 100644 olives.md
Lets check our work!
$ ls
$ git log --oneline
As expected, we see our commit in the log. Now let’s switch back to the main
branch.
$ git checkout main
$ git branch
* main
starters
Now that we’ve confirmed we are in the main
branch again, let’s explore the
repository a bit more. Confirm that olives.md
and our last commit aren’t
in main
:
$ ls
$ git log --oneline
We no longer see the file olives.md
and our latest commit doesn’t
appear in this branch’s history. Where has it disappeared to? I hasn’t vanished;
all of our hard work remains in the starters
branch. We can confirm this by
moving back to that branch.
$ git checkout starters
$ git branch
main
* starters
$ ls
$ git log --oneline
And we see that our olives.md
file and respective commit have been
preserved in the starters
branch.
Now we can repeat the process in a branch called desserts
.
First we must checkout the main
branch again. New branches will
include the entire history up to the current commit, and we’d like
to keep the two branches independent.
$ git checkout main
$ git branch
* main
starters
This time let’s create and switch to the desserts
branch
in one command. We can do so by adding the -b
flag to checkout.
$ git checkout -b desserts
$ git branch
* desserts
main
starters
We can use ls
and git log
to see that this branch is
the same as our current main
branch.
Now we can make apple_pie.md
and add and commit it.
Again imagine instead of touch
ing the file we worked
on it for many hours.
$ touch apple_pie.md
$ git add apple_pie.md
$ git commit –m “Wrote recipe for apple pie”
[bashdev 2n779ds] Wrote recipe for classic tiramisu
1 file changed, 1 insertion(+)
create mode 100644 apple_pie.md
Lets check our work again before we switch back to the main branch.
$ ls
$ git log --oneline
Alfredo decides his olives recipe needs more work before it is ready. But
he is happy with the apple pie recipe, so let’s merge this version into our
main
branch so we can use it. Merging brings the changes
from a different branch into the current branch.
First we must switch to the branch we’re merging changes into, main
.
$ git checkout main
$ git branch
desserts
* main
starters
Now we can merge
from the desserts
branch into our current branch
(main
). In English, this command could be stated as “git
, please
merge
the changes in the desserts
branch into the branch
I am currently in”.
$ git merge desserts
Updating 12687f6..x792csa1
Fast-forward
apple_pie.md | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 apple_pie.md
Now that we’ve merged desserts
into main
, these changes
exist in both branches. This could be confusing in the future if we
stumble upon the desserts
branch again. We would therefore like to
delete our old branches to avoid such future confusion.
We can do so by adding the -d
flag to the git branch
command.
git branch -d desserts
Deleted branch desserts (was x792csa1).
Alfredo decides he doesn’t want to keep the starters branch after all, and deletes it.
$ git branch -d starters
error: The branch 'starters' is not fully merged.
If you are sure you want to delete it, run 'git branch -D starters'.
Git recognises that we’ve never merged the changes from the starters
branch
into main
, and warns us that deleting it will cause us to lose the
development that we have done in that branch. Git tells us to use the -D
flag
instead if we are absolutely sure we want to delete this branch and the work
contained in it.
Alfredo decides that he really does want to delete this branch, so we go ahead and do so.
git branch -D starters
Deleted branch starters (was 2n779ds).
Key Points
Branches are useful for developing new features while ensuring that the main working base of code is not disturbed
Branches are quick to create and to delete
Creating a branch, adding a new feature in that branch, merging it with the main branch, and then deleting the branch is a basic engineering workflow when working with# Git
Or: “branch early and often”