1.3 Branches#

In this section, we will learn about branches in Git. We will discuss why are they useful, what they are, how to create them, and how to switch between them.

Motivation for branches#

Branches allow you to diverge from the main line of development and work independently without affecting the main line. This is useful when you want to work on a new feature or fix a bug without affecting the main line of development. Once you are done with your work, you can combine your changes back into the main line.

What are branches?#

A branch is a lightweight movable pointer to a commit. When Git initializes a repository, it creates a branch. As you commit changes, Git moves the branch pointer forward to point to the latest commit. In our repository, we used the option b with the argment main to indicate that the initial branch should be named main.

Test your knowledge

  • List the commit history of the repository.

Hide code cell source
git log
commit 2007711caa39b5ad6bee678519eb0b98e71bd1a3 (HEAD -> main)
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:17 2024 +0100

    Create file1.txt with the first line

What to notice

  • main is at the side of the latest commit.

  • HEAD is pointing to the main branch.

What is HEAD?

HEAD is a special pointer in Git that points to the current branch reference or sometimes directly to a commit (detached HEAD state). It indicates the “current” snapshot of your repository that you are working on. Git stores the HEAD pointer in a file named HEAD within the .git/ directory.

Modified files in Git#

Let’s add some commits to our commit history to see how the branch pointer moves. Let’s add a new line to our file1.txt file and check the status of the repository.

echo "This is the second line." >> file1.txt
git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   file1.txt

no changes added to commit (use "git add" and/or "git commit -a")

What to notice

  • Git recognizes that file1.txt has been modified.

In VSC:

  • a M symbol indicates a modified file.

Remember to save your changes

  • You need to save your changes for Git to track them.

  • VSC adds a dot to the file names to indicate unsaved changes.

Staging files with VSC#

This time, instead of using the command line, we will use VSC to stage the changes.

  1. Open the Source Control Panel: In VSC, click on the Source Control icon on the sidebar or press Ctrl+Shift+G (Cmd+Shift+G on macOS) to open the Source Control panel.

  2. View Changes: You’ll see a list of changed files in the Source Control panel. These files are modifications in your working directory that Git has not yet committed.

  3. Stage Files:

    • To stage an individual file, hover over the file name and click the + icon. This action stages that specific file.

    • To stage all changes, click the + icon next to the “Changes” section at the top of the list. This stages all modified files.

Committing with VSC#

Now that we have staged changes, we can commit them.

  1. Enter a Commit Message: At the top of the Source Control panel, you’ll find a text field to enter your commit message. Enter “Add second line to file1.txt” as the commit message.

  2. Commit the Changes:

    • To commit the staged changes, click the checkmark icon () above the text field where you entered your commit message. Alternatively, you can press Ctrl+Enter (Cmd+Enter on macOS) to commit.

Checking how the branch pointer moves#

Let’s check the commit history again to see how the branch pointer moves.

git log
commit d30b4a05bd3582bd7ec537c09ed0c764cc605e1e (HEAD -> main)
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:22 2024 +0100

    Add second line to file1.txt

commit 2007711caa39b5ad6bee678519eb0b98e71bd1a3
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:17 2024 +0100

    Create file1.txt with the first line

What to notice

  • The branch automatically moves to point to the latest commit.

Listing local branches#

So far we have been working with the main branch. Let’s list the branches in our repository. To list the branches, we use the git branch command.

git branch
* main

What to notice

  • The * symbol indicates the current branch.

  • The main branch is the only branch in the repository.

Creating a new branch#

Let’s imagine that we want to add a new feature to our project. We will create a new branch called feature. To create a new branch, we use the git branch command followed by the name of the new branch.

git branch feature

Test your knowledge

  • List the local branches in the repository.

Hide code cell source
git branch
  feature
* main

What to notice

  • The feature branch has been created.

  • The * indicates that the current branch is still main.

Since our current branch is main if we commit changes, they will be added to the main branch and not to the feature branch.

Test your knowledge

  • List the commit history of the repository.

Hide code cell source
git log
commit d30b4a05bd3582bd7ec537c09ed0c764cc605e1e (HEAD -> main, feature)
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:22 2024 +0100

    Add second line to file1.txt

commit 2007711caa39b5ad6bee678519eb0b98e71bd1a3
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:17 2024 +0100

    Create file1.txt with the first line

What to notice

  • As expected, feature points to the same commit as main.

  • HEAD is pointing to main, indicating that the current branch is main.

How does Git store branches?#

Git stores branches as files within the .git/refs/heads/ directory. Let’s list the files in this directory.

ls .git/refs/heads
feature  main

A file is created for each branch. Let’s look at the contents of the feature file.

cat .git/refs/heads/feature
d30b4a05bd3582bd7ec537c09ed0c764cc605e1e

The file contains the hash of the commit to which the branch is pointing.

cat .git/HEAD
ref: refs/heads/main

The HEAD file contains the reference to the current branch.

Switching to the new branch#

git switch feature
Switched to branch 'feature'
git branch
* feature
  main

What to notice

  • The * symbol now indicates that the current branch is feature.

In VSC:

  • on the left corner, we see that the active branch is now feature.

git log
commit d30b4a05bd3582bd7ec537c09ed0c764cc605e1e (HEAD -> feature, main)
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:22 2024 +0100

    Add second line to file1.txt

commit 2007711caa39b5ad6bee678519eb0b98e71bd1a3
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:17 2024 +0100

    Create file1.txt with the first line

What to notice

  • The feature branch still points to the same commit as main.

  • HEAD is pointing to feature, indicating that the current branch is feature.

Let’s now create our next commit, add a new line to the file1.txt file with the message This is the third line. and commit the changes.

#echo -en "\nThis is the third line." >> file1.txt
echo "This is the third line." >> file1.txt

git add file1.txt
git commit -m "Add third line to file1.txt"
[feature 4c34d2d] Add third line to file1.txt
 1 file changed, 1 insertion(+)
git log
commit 4c34d2de5a3d346a271ea3c30477f0049ddc88cc (HEAD -> feature)
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:24 2024 +0100

    Add third line to file1.txt

commit d30b4a05bd3582bd7ec537c09ed0c764cc605e1e (main)
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:22 2024 +0100

    Add second line to file1.txt

commit 2007711caa39b5ad6bee678519eb0b98e71bd1a3
Author: msdp-book <msdp.book@gmail.com>
Date:   Fri Mar 15 19:16:17 2024 +0100

    Create file1.txt with the first line

What to notice

  • We have added a new commit to the feature branch.

  • The feature branch now points to the new commit.

  • HEAD is pointing to feature, indicating that the current branch is feature.

  • The main branch still points to the same commit as before.

The Commit history diagram#

As the number of commits grows, it becomes harder to keep track of the commit history. This is where representing the commit history with a diagram comes in handy. In our diagram, we will represent commits as circles, branches with boxes and the HEAD pointer with a diamond.

flowchart RL C2((C2)) --> C1((C1)) C3((C3)) --> C2 main --> C2 feature --> C3 HEAD{HEAD} --> feature