Home iOS & Swift Books Git Apprentice

7
Branching Written by Sam Davies & Chris Belanger

One of the driving factors behind Git’s original design was to support the messy, non-linear approach to development that stems from working on large-scale, fast-moving projects. The need to split off development from the main development line, make changes independently and in isolation of other changes on the main development line, easily merge those changes back in, and do all this in a lightweight manner, was what drove the creators of Git to build a very lightweight, elegant model to support this kind of workflow.

In this chapter, you’ll explore the first half of this paradigm: branching. You’ve touched on branching quite briefly in Chapter 1, “A Crash Course in Git,” but you probably didn’t quite understand what you, or Git, were doing in that moment.

Although you can hobble through your development career never really understanding how branching in Git actually works, branching is incredibly important to the development workflows of many development teams, both large and small, so knowing what’s going on under the hood, and having a solid mental model of your repository’s branching structure will help you immensely as your projects grow in size and complexity.

What is a commit?

That question was asked and answered in a shallow manner a few chapters ago, but it’s a good time to revisit that question and explore commits in more detail.

Recall that a commit represents the state of your project tree — your directory — at a particular point in time:

├── LICENSE
├── README.md
├── articles
│   ├── clickbait_ideas.md
│   ├── ios_article_ideas.md
│   └── live_streaming_ideas.md
├── books
│   └── book_ideas.md
└── videos
    ├── content_ideas.md
    └── platform_ideas.md

You probably think about your files primarily in terms of their content, their position inside the directory hierarchy, and their names. So when you think of a commit, you’re likely to think about the state of the files, their content and names at a particular point in time. And that’s correct, to a point: Git also adds some more information to that “state of your files” concept in the form of metadata.

Git metadata includes such things like “when was this committed?” and “who committed this?”, but most importantly, it includes the concept of “where did this commit originate from?” — and that piece of information is known as the commit’s parent. A commit can have one or two parents, depending on how it was branched and merged back in, but you’ll get to that point later.

Git takes all that metadata, including a reference to this commit’s parent, and wraps that up with the state of your files as the commit. Git then hashes that collection of things using SHA1 to create an ID, or key, that is unique to that commit inside your repository. This makes it extremely easy to refer to a commit by its hash value, or as you saw in the previous chapter, its short hash.

What is a branch?

The concept of a branch is massively simple in Git: It’s simply a reference, or a label, to a commit in your repository. That’s it. Really. And because you can refer to a commit in Git simply through its hash, you can see how creating branches is a terribly cheap operation. There’s no copying, no extra cloning, just Git saying “OK, your new branch is a label to commit 477e542”. Boom, done.

Creating a branch

You created a branch before in the crash-course chapter, but now you’re going to create a branch and watch exactly what Git is doing.

git branch testBranch

How Git tracks branches

To see that Git actually did something, execute the following command to see what Git’s done in the background:

ls .git/refs/heads/
master		testBranch
cat .git/refs/heads/testBranch
git log -1
commit 477e542bfa35942ddf069d85fbe3fb0923cfab47 (HEAD -> master, testBranch)
Author: Chris Belanger <chris@razeware.com>
Date:   Wed Jan 23 16:49:56 2019 -0400

    Adding .gitignore files and HTML

Checking your current branch

Git can easily tell you which branch you’re on, if you ever need to know. Execute the following command to verify you’re working on testbranch:

git branch
* master
  testBranch

Switching to another branch

To switch to testBranch, execute the checkout command like so:

git checkout testBranch
Switched to branch 'testBranch'
git checkout master
git branch -d testBranch

Viewing local and remote branches

To see all of the branches that Git knows about on this repository, either local or remote, execute the following command:

git branch --all
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/clickbait
  remotes/origin/master
git checkout --track origin/clickbait
Branch 'clickbait' set up to track remote branch 'clickbait' from 'origin'.
Switched to a new branch 'clickbait'

Explaining origin

OK, what is this origin thing that you keep seeing?

git remote -v
origin	https://www.github.com/belangerc/ideas (fetch)
origin	https://www.github.com/belangerc/ideas (push)
git branch --all -v
* clickbait                e69a76a Adding suggestions from Mic
  master                   477e542 [ahead 8] Adding .gitignore files and HTML
  remotes/origin/HEAD      -> origin/master
  remotes/origin/clickbait e69a76a Adding suggestions from Mic
  remotes/origin/master    c470849 Going to try this livestreaming thing

Viewing branches graphically

To see a visual representation of the current state of your local branches, execute the following command:

git log --oneline --graph
* e69a76a (HEAD -> clickbait, origin/clickbait) Adding suggestions from Mic

A shortcut for branch creation

I confess, I took you the long way ’round with that command git checkout --track origin/clickbait, but seeing the long form of that command hopefully helped you understand what Git actually does when it checks out and tracks a branch from the remote.

Challenge: Delete a branch with commits

You don’t want to muck up your existing branches for this challenge, so you’ll need to create a temporary local branch, switch to it, make a commit, and then delete that branch.

Key points

  • A commit in Git includes information about the state of the files in your repository, along with metadata such as the commit time, the commit creator, and the commit’s parent or parents.
  • The hash of your commit becomes the unique ID, or key, to identify that particular commit in your repository.
  • A branch in Git is simply a reference to a particular commit by way of its hash.
  • master is simply a convenience convention, but has come to be accepted as the original branch of a repository. main is also another common convenience branch name in lieu of master.
  • Use git branch <branchname> to create a branch.
  • Use git branch to see all local branches.
  • Use git checkout <branchname> to switch to a local branch, or to checkout and track a remote branch.
  • Use git branch -d <branchname> to delete a local branch.
  • Use git branch --all to see all local and remote branches.
  • origin, like master, is simply a convenience convention that is an alias for the URL of the remote repository.
  • Use git checkout -b <branchname> to create and switch to a local branch in one fell swoop.

Where to go from here?

Get used to branching in Git, because you’ll be doing it often. Lightweight branches are pretty much the reason that Git has drawn so many followers, as it matches the workflow of concurrent development teams.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2020 Razeware LLC

You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.