Git Branching#
Git supports “branches”, a feature of tracking different versions of your project code. These branches can be used to model different versions, or to safely test out a new idea or fix a bug. In this lecture, we’ll cover what Git branches are used for, and how to best use them.
To download the demo for this lecture:
$ dmget wb-git-branching --demo
Introduction#
Goals#
Understand data structures of Git
Learn to use Git branches
Data Structures of Git#
Commits are linked nodes#
Each commit node contains:
Information about all changes made to files
Author name and email
Commit message
Pointer(s) to commit(s) that came directly before this commit
Zero parents for the initial commit
One parent for a normal commit
Multiple parents for a commit merging two or more branches.
Git Branching#
What are branches good for?#
Testing an idea safely
So you can still work on the “main branch” separately
Maintaining separate releases
Example branches:
dev
andprod
Starting a project#
Let’s start a fresh Git repo in the demo directory.
$ git init $ git add README.md $ git commit -am "Initial commit."
Now let’s add hello.js
and commit it.
console.log('Hello, world!');
$ git add hello.js $ git commit -am "Add hello.js"
$ git log
commit f5956ee (HEAD -> main)
Author: Jane Hacks <jhacks@developer.dev>
Date: Tue Aug 15 13:05:15 2050 -0000
Add hello.js
commit 4e7a1dd
Author: Jane Hacks <jhacks@developer.dev>
Date: Tue Aug 15 13:04:51 2050 -0000
Initial commit.
- main
The default branch Git creates for you.
- HEAD
A pointer to the commit at which your working directory is currently set.
Creating a branch#
Our project exists but it needs something more…
Let’s add a new feature.
$ git branch output-more-stuff
Notice git branch
doesn’t change HEAD.
To move HEAD ➡️ more-stuff
, we’ll need to checkout more-stuff
.
Checkout a branch#
$ git branch * main more-stuff $ git checkout more-stuff Switched to branch 'more-stuff' $ git branch main * more-stuff
You’ve now switched to the more-stuff
branch!
You can shortcut these two steps with:
$ git checkout -b name-of-branch
This creates the branch and moves HEAD in one step.
Work on your branch#
Let’s add more stuff to hello.js
and commit our changes.
console.log('Hello, world!');
console.log('more stuff...');
$ git commit -am "Start implementing more stuff"
Merging in changes#
You love the new stuff added to the more-stuff
branch!
Let’s merge those changes back into main
.
$ git checkout main Switched to branch 'main' $ git merge more-stuff Updating 71760b68..0707a4f0 Fast-forward hello.js | 1 + 1 file changed, 1 insertion(+) $ git branch * main more-stuff
This didn’t delete
more-stuff
—it’s still there!But we’re back on the
main
branch, so commits will go onto thatWe can switch back to
more-stuff
and work more thereAnd re-merge it back into
main
periodically
Fast-forward merge#
This merge was a fast-forward merge
All of the changes were on one branch
So the other branch could just be “fast-forwarded” to that commit
This kind of merge is very straightforward for you and for Git
Deleting branches#
We can delete the more-stuff
branch
Perhaps it was a failed experiment
Or perhaps we’ve merged it back to
main
and don’t need to keep it around
$ git branch -d more-stuff
Deleted branch more-stuff
Complex Merging#
Working across branches#
Earlier, we branched
more-stuff
and did all our work there.Sometimes you’ll have active work in multiple branches
A longer-lived feature/bug branch, while work is still happening in
main
Working on teams (each feature or person might have a branch)
This can lead to more significant merges
Merging changes across branches#
Let’s say we’re working on a team.
During sprint planning, we’re assigned a new task: to integrate a hip, new JS library.
We’ll make a new branch for this feature.
$ git checkout -b hip-js
…and make changes in a new file:
// Code using the hip new JS lib!
$ git add hip.js $ git commit -am "Integrate new library"
While you’re working on hip-js
, your team makes some changes to main
…
$ git checkout main
Switched to branch ‘main’
console.log('Hello, world!');
console.log('more stuff...');
console.log('A bug fix');
$ git commit -am "Bugfix"
Now they’re ready to merge in your changes:
$ git status # check that we're still on main On branch main nothing to commit, working directory clean $ git merge hip-js -m "Merge in hip-js." Merge made by the 'recursive' strategy. hip.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 hip.js
git log --graph
#
Adding --graph
to git log
will show a visualization of merge history:
$ git log --graph On branch main * commit abc4 |\ Merge: cc90 5fc3 | | Author: Jane Hacks <jhacks@developer.dev> | | | | Merge in 'hip-js'. | | | * commit 5fc3 | | Author: Jane Hacks <jhacks@developer.dev> | | | | Integrate new library. | | * | commit cc90 |/ Author: Jane Hacks <jhacks@developer.dev> | | Bugfix. | * commit 87ab | Author: Jane Hacks <jhacks@developer.dev> | | Start implementing more stuff. | ...
Syncing hip-js
with main
#
To continue working in hip-js
, we should sync it with changes in main
:
$ git checkout hip-js Switched to branch hip-js $ git merge main Updating ... Fast-forward hello.js | 1 + 1 file changed, 1 insertion(+)
Merge Conflicts#
What’s a merge conflict?#
Most of the time, Git can figure out how to merge your work…
…unless there are changes to the same parts of the same file(s).
In this case, you have to resolve a merge conflict.
Making a conflict#
Let’s add two lines to hello.js
on main
and commit:
$ git checkout main
Switched to branch ‘main’
console.log('Hello, world!');
console.log('more stuff...');
console.log('A bug fix');
// Change from main
// End
$ git commit -am "Add comments."
[main abe15a32] Add comments.
1 file changed, 2 insertions(+)
Now we’ll do the same on hip-js
:
$ git checkout hip-js
Switched to branch ‘hip-js’
console.log('Hello, world!');
console.log('more stuff...');
console.log('A bug fix');
// Change from hip-js
// End
$ git commit -am "Add comments."
[main abe15a32] Add comments.
1 file changed, 2 insertions(+)
Merging with conflicts#
When we go to merge this, we’ll get a conflict:
main
#console.log('Hello, world!');
console.log('more stuff...');
console.log('A bug fix');
// Change from main
// End
hip-js
#console.log('Hello, world!');
console.log('more stuff...');
console.log('A bug fix');
// Change from hip-js
// End
$ git checkout main $ git merge hip-js -m "Merge hip-js" Auto-merging hello.js CONFLICT (content): Merge conflict in hello.js Automatic merge failed; fix conflicts and then commit the result.
Resolving conflicts#
Start by following the directions from git status
:
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add [file]..." to mark resolution)
both modified: hello.js
Open the file with the conflicts:
console.log('Hello, world!');
console.log('more stuff...');
console.log('A bug fix');
<<<<<< HEAD
// Change from main
======
// Change from hip-js
>>>>>> hip-js
// End
VS Code comes with tools to help resolve merge conflicts.

Changes in green come from HEAD (main
), changes in blue come from hip-js
.#
You can resolve conflicts without VS Code’s tools too.
Just remove the merge markers (like <<<<<<< HEAD
)
console.log('Hello, world!');
console.log('more stuff...');
console.log('A bug fix');
// Change from main and hip-js
// End
$ git commit -am "Merge comments from hip-js"
Best Practices#
Branching styles#
These are tools
Different companies use them differently!
Some branch for every bug, some rarely branch
Expect your team lead to explain how it works
You can practice with throwaway repos
Don’t panic#
You probably won’t be doing much merging yourself
Typically, a team lead does the merging
It’s good for you to understand how to help them
Good habits to practice#
Make sure you’re working on different areas
Communicate before you code!
Make small commits and push often
Avoid using GitHub’s “edit in browser” feature
Making changes in the browser and locally can lead to merge conflicts!
Branches and GitHub#
Pushing branches to GitHub#
To push branches to GitHub:
$ git push -u origin hip-js
This works even if you’re in a different branch.
Pulling from GitHub#
To pull a branch from GitHub:
$ git checkout name-of-branch $ git pull origin name-of-branch
Branches and Pull Requests#
In GitHub, pull requests let you notify others about changes you’ve made to a branch.
Pull requests enable collaborators to discuss and review potential changes before they’re merged into the base branch.
You’ll learn how to make a pull request during lab!
Resources#
Resources#
Pro Git by Scott Chacon and Ben Straub (available for free!)
Other things to learn about#
Set your Git editor (you might have already set this to VS Code when you set up your dev environment)
How to create aliases (shortcuts) for commonly used commands
Looking ahead#
Learn how to collaborate using GitHub (forking, code reviews, etc.)!