Lesson Tuesday

So far we've learned what Git and GitHub are, how to set up a project, track changes, push code to GitHub, clone projects back down from GitHub into a local Git repository, and even publish websites on GitHub Pages.

In this lesson we'll dive deeper into Git by exploring something called branching. We were introduced to branching briefly when we learned about GitHub pages. In this lesson, we'll learn more about what it is, how it works, what benefits it offers, and how to create and maintain branches in our own projects.

To do this, we'll walk through creating an example project in the next two lessons. Together, we'll create and merge branches in this example project. Then, in an upcoming exercise you'll have the opportunity to work with branches on your own project with a partner.

Overview

In Git, branching is the act of creating multiple copies of similar code in the same repository. There are many reasons developers do this. Here are a few of the most common:

  • Multiple branches allow a team of developers to work together without "stepping on each others' feet", so to speak. If a team was all working on the same files at the same time, things could get messy very quickly. Branches allow each developer their own copy of the project to work on. When part of the project is done, the team can merge multiple branches together into a completed final product. We'll get plenty of practice with this when we work on group projects in week 5 of this course.

  • Branching also allows us to experiment with changes without risking our final product. We can use branching to create a copy of our code separate from our final version to experiment with new features and code. If this new code causes any bugs, we can rest assured knowing our original code is still safe!

  • Branching allows us to pursue multiple options at once. Not sure which approach to a problem is preferable? With branching, you could always create multiple copies of your project, try implementing different code in each, and see which result is preferable.

Master Branch

You may be surprised to learn that you've been interacting with branches since the beginning of the course! At this point in the curriculum, you've most likely pushed several projects to GitHub already, and published at least one on GitHub Pages. Your current GitHub repositories should look something like this:

basic-github-repo

Notice the dropdown menu on the left side labeled "Branch":

branch-dropdown-on-github

If we click this dropdown we see it contains one entry: master (if you've published a project to GitHub pages it will also contain a branch named gh-pages).

master-branch-on-github

When you learned how to push a project to a remote GitHub repo yesterday, you pushed your local Git repositories to online GitHub repositories using a command like this:

$ git push al master

(The initials al in the command above are just an example; your own initials would be placed here.)

The master portion of this command instructs Git to push the current master copy of your local repository to the remote repository under the nickname al.

But what does master mean? Well, projects tracked in Git and GitHub may have multiple branches. The term master specifies that code should be pushed to the master branch on GitHub. Remember, we saw there was a branch named master in the dropdown menu on GitHub.

A branch is just another copy or version of the project's main code. Both Git and GitHub repositories may have multiple branches at once. There is always at least one branch in a project: Master.

Master is the name of the default branch. If you don't create or navigate between branches in your project, you will have one branch named master, and you will be located in it by default. When you have multiple branches in a project, the master branch is like the "final draft".

Branches that are not master are often referred to as feature branches, because they allow developers to experiment with new features before integrating them into the "final draft" master branch.

Additionally, you probably published a project to GitHub pages with a command like this in a previous lesson:

$ git push origin gh-pages

Much like master, gh-pages is also a branch name. While master is responsible for containing the final product, gh-pages is responsible for publishing content to GitHub's special GitHub Pages tool.

Example Project

Let's walk through a basic example of branching together. We'll craft a small website. Then, we'll create multiple branches to experiment with different CSS styles. We'll compare the styles, choose which we like best, and integrate the favored styles into our "final draft" (that is, our master branch). You and your partner should begin following along at this time.

Project Setup

First, we'll set up our basic site. Everything in this section should be review from yesterday.

.pairs File

This lesson assumes you have a .pairs file located in your home directory, as described in this lesson. A .pairs should look something like this:

.pairs
pairs:
  al: Ada Lovelace 
  edlf: Enrique de la Fuente 
email:
  al: [email protected]
  edlf: [email protected]  

You should already have a .pairs file containing your and your partner's information. If you do not, create one at this time.

Project Directory

Next, let's create a new project directory on our Desktop. Remember, whenever we start a new project we must create a new directory for it to reside in. First, we'll navigate to our Desktop:

$ cd Desktop

Then, we'll create a new directory called branching-test-project:

$ mkdir branching-test-project

If we run $ ls we can see our new branching-test-project directory. Next, use the $ cd command to navigate to the new project folder:

$ cd branching-test-project

Remember, if you're ever unsure of your location in the command line you can run the $ pwd command.

Git Initialization

Next, we'll initialize our Git repository:

$ git init

And configure it to use the information in our .pairs file:

$ git pair al edlf

In the command above, replace al and edlf with your and your partner's initials, as listed in your .pairs file.

HTML File

Next, let's create an HTML file for our website's code:

$ touch branching-website.html

We'll open our project directory in Atom:

$ atom .

And add the following code to our branching-website.html file:

branching-website.html
<!DOCTYPE html>
<html>
  <head>
    <title> Branching Practice Site </title>
  </head>
  <body>
    <h1> Branching </h1>
    <h2> A website to practice branching with Git. </h2>
    <p> This page has been created in order to practice branching with Git and GitHub. By creating branches, we can work on different versions of the same code in the same repository simultaneously!  </p>
  </body>
</html>

Committing Changes

Once this code is in place, we can make our first commit. First, we'll run $ git status to see there are new, uncommitted changes in our project:

$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    branching-website.html

nothing added to commit but untracked files present (use "git add" to track)

Then, we can run $ git add to add our new branching-website.html file to Git so it will track this file's changes:

$ git add branching-website.html

We can run $ git status again to see that our file is now being tracked, but has not yet been committed:

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   branching-website.html

Let's save our new HTML to the permanent history of the project by committing it. Since we're working with a partner, we'll use the $ git-pair-commit command to do this:

$ git-pair-commit -m "Add initial HTML file with explanation of branching practice site."

If we run $ git log we can see a new commit has been added to the history of our project:

$ git log
commit eb1774eee69d3e8fa1d74790dc9c64d70d1e9ec2
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 11:49:54 2016 -0700

    Add initial HTML file with explanation of branching practice site.

Adding Styles with CSS

Great! Now, earlier today you learned about CSS. Before we begin branching, let's create a basic CSS stylesheet for our example project. We'll make a folder called css in our existing project directory:

$ mkdir css

Then, we'll create a file called styles.css within our new css directory:

$ touch css/styles.css

Our project structure should look like this:

project-structure-with-css-in-atom

Next, let's tell our HTML document to use this new file for its CSS. We will include a link to the new CSS file in the <head> tags of our branching-website.html file, like this:

branching-website.html
<!DOCTYPE html>
<html>
  <head>
    <link href="css/styles.css" rel="stylesheet" type="text/css">
    <title> Branching Practice Site </title>
  </head>
  <body>
    <h1> Branching </h1>
    <h2> A website to practice branching with Git. </h2>
    <p> This page has been created in order to practice branching with Git and GitHub. By creating branches, we can work on different versions of the same code in the same repository simultaneously!  </p>
  </body>
</html>

Let's add these new changes to our Git repository:

$ git add . 

And commit them to the history of our project:

$ git-pair-commit -m "Create stylesheet, link in head of website."

Next, we'll add a basic CSS rule to our stylesheet:

styles.css
h1 {
  color: blue;
}

If we open the branching-website.html file in our browser, we should see that the text in the <h1> tags is blue:

blue-headers

Let's add and commit this new CSS rule to our project:

$ git add css/styles.css
$ git-pair-commit -m "Add CSS rule to make H1 headers blue."

If we run $ git log we will see we now have 3 commits:

$ git log
commit 982b0f21463be34d909c45dd67778d6ffe3d7668
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:06:35 2016 -0700

    Add CSS rule to make H1 headers blue.

commit 8e36f8bfd58643487565c5a4fbcb5250fed0808b
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:04:27 2016 -0700

    Create stylesheet, link in head of website.

commit eb1774eee69d3e8fa1d74790dc9c64d70d1e9ec2
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 11:49:54 2016 -0700

    Add initial HTML file with explanation of branching practice site.

Now that our basic website is set up, we can use it to learn about branching in the next section. Nice work!

Viewing a Project's Branches

Everything we've done thus far should be review. Now, let's explore the new concept at hand: Branching. First we'll run the following command:

$ git branch

The $ git branch command displays what branches are currently in our project. It also denotes which branch we're currently viewing with an asterisk *. After we execute this command, we should see this:

* master

This informs us that there is only one branch: master. And, we know we're currently located in that branch because there is an asterisk next to it. Remember, master is the default branch. If we do not create any branches, or move between any branches, we will be on master.

Creating a New Branch

Let's pretend we're unsure how to style our site. We want to test a couple different stylistic approaches, and see which looks best. To do this, we'll create several versions of our project with branches. We'll implement different styles in each branch.

We can create a new branch by running the $ git branch command and including the name of the new branch after it, like this:

$ git branch blue_theme

This creates a new branch named blue_theme. Branch names should be short and meaningful, and describe the reason for the branch. In our case, this branch will contain styles that use the color blue throughout.

(Note that there are only two exceptions to these naming rules: The master branch will always be named master, and GitHub pages requires branches be named gh-pages in order to publish them using the GitHub pages tool.)

Navigating Between Branches

If we run $ git branch again, we can see our project now contains two branches:

$ git branch

  blue_theme
* master

Notice the asterisk is still next to master. We created a new blue_theme branch, but we're still located on master. We can switch branches like this:

$ git checkout blue_theme

The $ git checkout command navigates to the specified branch. We can run $ git branch again to confirm we've successfully entered the blue_theme branch:

$ git branch

* blue_theme
  master

The asterisk is now next to blue_theme, so we know we've successfully navigated to that branch. Now, let's look at our project in Atom. Despite being located in our new branch, everything should look the exact same.

When you create a branch, the new branch is "branched off" from the branch you are located in when the command to create a new branch is executed. This means the new branch will contain all code and commits from the branch it was branched off from. In our case, since we were located in master when we created blue_theme , blue_theme contains all code and commits that master contained at the time of the new branch's creation.

We can confirm this by running $ git log. We should see our new branch contains the same commits we made on master:

$ git log

commit 982b0f21463be34d909c45dd67778d6ffe3d7668
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:06:35 2016 -0700

    Add CSS rule to make H1 headers blue.

commit 8e36f8bfd58643487565c5a4fbcb5250fed0808b
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:04:27 2016 -0700

    Create stylesheet, link in head of website.

commit eb1774eee69d3e8fa1d74790dc9c64d70d1e9ec2
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 11:49:54 2016 -0700

    Add initial HTML file with explanation of branching practice site.

Working on a Branch

We now have a separate, isolated version of our project to experiment with. We can safely test code in blue_theme without risking the integrity of code in master. We can change, add, and commit whatever we'd like in blue_theme and master will remain completely unaffected. Let's add more CSS to the styles.css stylesheet:

styles.css
h1 {
  color: blue;
  text-align: center;
}

h2 {
  font-style: italic;
  text-align: center;
  color: teal;
}

p {
  color: gray;
}

body {
  background-color: skyblue;
}

If we refresh our page in the browser, we can see these new styles:

test-site-blue-theme

As always, we'll add these changes to our Git repository and commit them:

$ git add css/styles.css
$ git-pair-commit -m "Add styles to h1, h2, p, and body to fit blue theme."

Separation of Commits Between Branches

Let's run $ git log again to see a summary of our commits:

$ git log

commit 268363ae7b81a7ee91540d93f82e3f9285c575dd
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:24:38 2016 -0700

    Add styles to h1, h2, p, and body to fit blue theme.

commit 982b0f21463be34d909c45dd67778d6ffe3d7668
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:06:35 2016 -0700

    Add CSS rule to make H1 headers blue.

commit 8e36f8bfd58643487565c5a4fbcb5250fed0808b
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:04:27 2016 -0700

    Create stylesheet, link in head of website.

commit eb1774eee69d3e8fa1d74790dc9c64d70d1e9ec2
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 11:49:54 2016 -0700

    Add initial HTML file with explanation of branching practice site.

The blue_theme branch now contains the commits it inherited from master, and the new commit we've just made. Before we continue, let's return to our master branch for a moment using the $ git checkout command:

$ git checkout master

As always, we can double-check we're on master by running $ git branch and confirming that master has an asterisk next to it:

$ git branch

  blue_theme
* master

Great. Now, let's look at the commits on our master branch again:

$ git log

commit 982b0f21463be34d909c45dd67778d6ffe3d7668
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:06:35 2016 -0700

    Add CSS rule to make H1 headers blue.

commit 8e36f8bfd58643487565c5a4fbcb5250fed0808b
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:04:27 2016 -0700

    Create stylesheet, link in head of website.

commit eb1774eee69d3e8fa1d74790dc9c64d70d1e9ec2
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 11:49:54 2016 -0700

    Add initial HTML file with explanation of branching practice site.

Notice that the new commit we just made on blue_theme is not present in master! Our blue_theme branch's most recent commit reads "Add styles to h1, h2, p, and body to fit blue theme." Whereas master's most recent commit reads "Add CSS rule to make H1 headers blue." And if we refresh our page in the browser again, we can see our blue styles are no longer present:

no-blue-theme

Also, if you view the styles.css stylesheet in Atom, you'll notice that the CSS rules we just added are gone! Don't worry; this is entirely normal. Because we switched branches, the version of the project we're seeing in Atom is different. The master branch does not have the same CSS rules as the blue_theme branch.

Remember, when we create a branch the new branch will inherit all commits from the branch it is branched off from. That is, the branch we are located in when we create the new branch. However, when we make new commits on our new branch, they remain on that branch. The organization of our current commits between branches look something like this:

flowchart-of-branches

We can see our first three commits on master. When we branched off of master to create blue_theme, it inherited all of master's commits. However, when we made subsequent commits in blue_theme they remained exclusive to blue_theme and were not shared with master.

Working with Multiple Branches

Let's create another branch with a different set of CSS styles for our site. Remember, you may branch off from any existing branch. The new branch will contain all code and commits from whatever branch you were located within when the new branch was created.

Creating a New Branch

Let's branch from master again. We'll run $ git branch and confirm we're located in master:

$ git branch

  blue_theme
* master

Then, we'll create another new branch named red_theme, like this:

$ git branch red_theme

We'll run $ git branch again to confirm our new branch has been created:

$ git branch 

  blue_theme
* master
  red_theme

Navigating Between Branches

Next, we'll switch to our new red_theme branch using the $ git checkout command:

$ git checkout red_theme

Switched to branch 'red_theme'

We can run $ git branch to confirm we've successfully navigated into the red_theme branch:

$ git branch

  blue_theme
  master
* red_theme

And, if we run $ git log we can see red_theme has inherited all commits from master, as expected:

$ git log

commit 982b0f21463be34d909c45dd67778d6ffe3d7668
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:06:35 2016 -0700

    Add CSS rule to make H1 headers blue.

commit 8e36f8bfd58643487565c5a4fbcb5250fed0808b
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:04:27 2016 -0700

    Create stylesheet, link in head of website.

commit eb1774eee69d3e8fa1d74790dc9c64d70d1e9ec2
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 11:49:54 2016 -0700

    Add initial HTML file with explanation of branching practice site.

Working on a Branch

Our styles.css file in Atom should currently look like this:

styles.css
h1 {
  color: blue;
}

Again, notice that it does not contain the CSS we just committed in the blue_theme branch. The new red_theme branch was branched off of master. Therefore, it contains all of master's commits and code. It does not contain the code we committed on the blue_theme branch, only the master branch. Let's add styles to this branch's version of the styles.css file now:

styles.css
h1 {
  color: darkred;
  text-align: center;
}

h2 {
  font-style: italic;
  text-align: center;
  color: red;
}

p {
  color: crimson;
}

body {
  background-color: salmon;
}

If we refresh our page in the browser, we can see our new CSS at work:

red-theme-styles

We'll add these changes to our Git repository, and commit:

$ git add css/styles.css
$ git-pair-commit -m "Add styles to h1, h2, p, and body to fit red theme."

As always, we can run $ git log to see a summary of our commits:

$ git log

commit 5f2d9510cdc76736c7c5cf7e5d56264cd405fcd1
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:51:11 2016 -0700

    Add styles to h1, h2, p, and body to fit red theme.

commit 982b0f21463be34d909c45dd67778d6ffe3d7668
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:06:35 2016 -0700

    Add CSS rule to make H1 headers blue.

commit 8e36f8bfd58643487565c5a4fbcb5250fed0808b
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:04:27 2016 -0700

    Create stylesheet, link in head of website.

commit eb1774eee69d3e8fa1d74790dc9c64d70d1e9ec2
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 11:49:54 2016 -0700

    Add initial HTML file with explanation of branching practice site.

Perfect. We now have the commits that came along with the new branch when we branched from master, and the new commit we've just made on the red_theme branch. Our organization of commits between branches currently looks like this:

flow-chart-2

Now, let's say we want to improve the styles in red_theme even further by changing the site's text. We'll include the following additional CSS rules in styles.css:

styles.css
h1 {
  color: darkred;
}

h2 {
  font-style: italic;
  color: red;
}

p {
  color: crimson;
}

body {
  background-color: salmon;
  font-family: sans-serif;
  text-align: center;
}

Here, we denote that everything located in the <body> tags should have sans-serif style font that is center-aligned. Because we're now styling everything in <body> tags we can remove text-align: center; from the existing h1 and h2 CSS rules. The <h1> and <h2> tags exist within the <body> tags, so this rule will automatically apply to them too. We can save our changes and refresh the site to see our new styles:

red-theme-sans-serif

Again, we'll add these changes to our Git repository:

$ git add css/styles.css

And commit them with a descriptive message:

$ git-pair-commit -m "Make all font sans-serif style."

Let's run $ git log. We can see that in addition to the 3 commits inherited from master, the red_theme branch also has 2 of its own commits:

$ git log

commit d5bae6406669988e154608ce990e08fed51e9cb3
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 13:00:42 2016 -0700

    Make all font sans-serif style.

commit 5f2d9510cdc76736c7c5cf7e5d56264cd405fcd1
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:51:11 2016 -0700

    Add styles to h1, h2, p, and body to fit red theme.

commit 982b0f21463be34d909c45dd67778d6ffe3d7668
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:06:35 2016 -0700

    Add CSS rule to make H1 headers blue.

commit 8e36f8bfd58643487565c5a4fbcb5250fed0808b
Author: Ada Lovelace and Enrique de la Fuente <[email protected]>
Date:   Mon Oct 10 12:04:27 2016 -0700

    Create stylesheet, link in head of website.

The commits across all branches of the project currently look like this:

flow-chart-3

Benefits of Branching

Are you beginning to see how branching can be beneficial? It allows us to experiment with code and ensure it works correctly before saving it to our "final draft" master branch. When developers integrate new features into projects, they commonly do so in a branch. This allows them to make a copy of the entire project, experiment with new code, and confirm it does what it is supposed to before saving it into the final version.

This prevents bugs or issues from affecting the project. If the new code a developer adds breaks anything, it won't cause issues on master, only on that isolated branch. This allows developers room to iron out any issues with code before integrating it into the final version of the project.

When code is fine-tuned and tested in the branch, and we know it works, we can add it into master. This process is called merging, and we'll explore it in detail in the next lesson as we continue to work with this example project.

Terminology


  • Branching: The act of making multiple copies of the same code in the same project. Usually in order to do different things with the same code base, or to allow multiple people to work on the same code at the same time.

  • Branch: Another copy of your code

  • Master Branch: Like the "final draft" of your code.

  • Feature Branches: A common term for branches that are not master. Usually branches meant for experimenting with new features before adding them to the final version of the project.

Tips


  • The $ git branch command with nothing after it will display all branches in a project. The branch you're currently located in will be denoted with an asterisk *.

  • The $ git branch command with a branch name after it (ie: $ git branch <name-of-new-branch>) will create a new branch of the name you specify. Branch names should be short and meaningful, and describe the reason for the branch.

  • We can switch which branch we're viewing by using the $ git checkout command with the name of the branch we'd like to see. For instance, $ git checkout blue_theme will move us to a branch named blue_theme.