Now available from O'Reilly Media: Emma's videos Collaborating with Git: Crafting Workflows at the Command Line. Includes over six hours of hands-on tutorials to help you learn Git.

If you’ve previously tried to learn Git but found the structure of the materials to be opaque, too academic, or just plain confusing, this hands-on video course will help you complete the task. Author and educator Emma Jane Hogbin Westby takes an unconventional approach to teaching version control with Git. Rather than start with the commands you’ll be running, she first explains why—and then demonstrates how.

Along the way, you’ll learn several Git hacks to help you be more efficient. And that means navigating Git from the command line. Many people prefer the “convenience” of a GUI, but in the long run, learning commands is quicker and easier than clicking various buttons on a succession of screens.

  • Create a visual map of Git by sketching your own diagrams
  • Use an example project to get started with hosted Git repositories
  • Learn how to upload changes and merge work with branches
  • Work with tags to pinpoint specific commits in the history of your work
  • Find and fix bugs by comparing “working” and “non-working” states
  • Learn how to undo your work with rollbacks and resets
  • Clean up your commit history with rebase
  • Move your sample project from GitLab to GitHub
  • Learn how to collaborate on GitHub and BitBucket

The extended description of what's included in these videos is included below.


Welcome and Set-up Prepare your workstation (drawing tool; git installed)

Warm-up Exercise Sketch the assembly line for your code as it exists currently, or as you think you would like it to work. Examples: centralized, peer review, automated gate keeper.

Getting Started with Hosted Git Repositories

Overview of permission strategies Most of the people I've worked with are starting out with a project they need to collaborate with. They aren't starting with an empty folder, but rather with an existing project. I personally find it easier to tinker with something rather than stare at a blank screen. So the first thing we're going to do is set you up with a practice repository that I've created. You won't be able to edit my copy of the project, but you will be able to make edits to your own copy. Let's start with a review of permission strategies and the way a project can be setup with Git. Overview of permission strategies: Centralized, Branched, Patched, Forked.

Creating a GitLab Account GitLab is a free code hosting platform which allows you to create private, and public repositories. It's also an open source product you can install behind your own firewall if you're working with a large team. It's not the most popular system out there, but I believe it offers the most flexibility to the widest range of people watching these videos. We'll get started with GitLab, and later in the lessons, I'll show you how to migrate your project to GitHub, which is currently one of the most popular code hosting platforms for open source projects. Git is distributed because work can be easily shared across multiple hosting systems. Create a GitLab account to store your first remote repository.

Forking Your First Project Fork the GitLab sample project. We are forking so that you can upload your changes to your own repository. If you cloned from this project directly to your computer you wouldn't be able to upload your changes to the project (only “privileged” users can do that).

Privatizing Your Repository Adjust the visibility of your forked repository to PRIVATE. Although this is completely optional, a lot of people feel more comfortable making mistakes when they know no one will see them.

Downloading a Remote Repository

Overview of Git at the Command Line Open up the command line, and check to see which version of Git you have installed. Look at Git's short help, list of all commands, and a single command. Recommend Stack Overflow / Google in additional to the command line help.

Cloning your GitLab repository Review the instructions on GitLab to get the commands you need to run to download (“clone”) the remote repository. Issue the necessary commands at the command line.

Reviewing History with git log Take a look at the work done in the repository to date. Compare against what's stored in the GitLab browser.

Getting Started as a Team of One

Overview of Working Without a Code Hosting ServerIf you need to work offline, you should start here with the videos. This is several ways to start your project if you don't have a code hosting repository,such as GitLab.

Initializing an Empty Project Use the command git init to start a new project locally. This creates an empty directory that you can now put stuff into.

Converting an Existing Project to Git You can start with any folder of files and create a git repository from it, using the git init command. This time instead of starting with an empty directory, start with an existing directory of files and “convert” your non-versioned project into a git repository. Run the following commands: git init, git add, git commit. These will all be covered in more depth later on.

Importing a Repository Previously you learned how to clone a project, this hooks up the remote server as a connection to your repository. You can also start with any folder which has a .git directory in it. For example: you could share your git repository with someone via a zipped email (AVOID doing this with a tool that does synchronization, such as Dropbox, as it will corrupt your git repository!!).

Connecting to Remote Repositories

Overview of Connecting to Remotes You've been working locally, and suddenly you realize you could share your work with the upstream project. Depending on how you started your project, you will need to connect your local work in slightly different ways.

Creating a Writeable Upstream Repository You initially cloned a repository that uses a forking repo. Now you need to go back and create an intermediate step on the code hosting platform that you can use to issue a pull request to.

Converting a Set of Files to a Repository You initially started with a .zip folder with all the files, but not with the .git repository. You now want to submit an upstream patch, but you have absolutely no local history from the upstream project to connect with.

Creating a Local Remote Repository You want to play with remotes, but you're entirely offline (for example: watching these videos behind a firewall and you can't get access to GitLab, GitHub, etc). Use a local directory as your “remote” repository. Remote actually just means any directory that's not THIS directory.

Working with Branches

Overview of Branching Strategies Scheduled release vs. Continuous development.

Listing All Branches List all branches in the repository. Compare between the local branches, and the remote branches.

Using a Different Branch Checkout a different branch. Open a finder window at the same time and see how files (dis)appear when different branches are checked out.

Using Best Practices for Changes Always start by creating a written description of what you're about to do. Yes, this will often feel like overhead, but it is a really good habit to get into, especially when you're working in larger teams.

Creating an Issue in GitLab In your private repository, create a new issue ticket which outlines the changes you're about to make.

Creating a Branch Using the branching convention, start on MASTER, and then, create a new branch using the convention: ticket number-issue, create a new branch in your local respository. Checkout the new branch as well

Creating a Tracked Branch Repeat the previous lesson, but this time add tracking when the branch is created. Start by checkout of master, and branching from there.

Adding Changes to your Local Repository Use the command git add filename to add the file to the index. Then commit your changes to save the change to your local repository. I usually do a commit at the command line, and then commit --amend to write a longer commit message which relates to the issue.

Uploading Your Changes with git push Upload the change to the remote repository with git push origin master. In newer versions of git, you should be able to just use git push.

Adding Tracking to a Previously Created Branch Checkout the branch which doesn't have tracking added. Try (and fail) to push the branch. Make necessary adjustments to be able to upload the branch to the remote repository.

Confirming Your Branch was Uploaded Log into GitLab to ensure the branch has been uploaded to the remote repository.

Working with Tags

Overview of Tagging Strategies Tags are used to pin-point specific commits. They don't follow a series of commits, like a branch does. They are a single point in time along the history of your work. You can add additional information (like a commit message) to the tag. See git help tag for extra options.

Listing All Tags Use the command git tag to see a list of existing tag.

Investigating a Specific Tag Use the command git show <tagname> to get the commit message and the author details.

Checking Out Tags You can also checkout this tag. You'll go into a DETACHED HEAD STATE! But you'll be fine.

Recovering from a Detached HEAD State Checkout the branch you were on previously to return to your regular work.

Finding and Fixing Bugs

Overview of Isolating Problems There are two ways to look for bugs: determining where the problem code is; and determining when (and by whom) the problem code was introduced. Generally I debug from within the current code, but in more complicated code bases it can be useful to compare “working” and “non-working” states (we'll use git bisect for this).

Using Advanced Options for Git Log Tips and tricks for getting the most useful git log messages – match this with diagrams of what the command is actually showing.

Finding the Last Working State with Bisect Define the problem you're trying to isolate, and then use git bisect to find the commit where the problem was introduced. Talk about the problem of web caching. Explain how to get “out” of the bisect once you've identified the problematic commit (by using checkout to return to a different branch).

Finding the Author History of a File with Blame Quick command to get a history of who has changed a specific file. Can be helpful when you're working in teams to find the person who might know more about the specific changes that were made to that part of the code base.

Using Stash to Work on an Emergency Bug Fix You need to do something “real quick” for a client, but you're in the middle of a complicated set of tasks in your current branch. Put all of this work on hold with the “stash” command instead of writing a useless commit that you have to unpack later.

Rollbacks, Resets, and Undoing Your Work

Overview of Undoing Previous Work Show a sketch of the working directory; index; and remote repository. You can undo work in three different places. Work can be undone by deleting commits, or by moving a previous commit to the front of the tip of your work. Rebasing allows you to also unhook previous commits from a chain of events, and create a new chain in the history (without actually deleting anything). Reflog always has your history...if you can remember the commit hash.

Using Branches for Experimental Work Review of how to create / delete branches locally.

Amending a Commit Previously we've used commit amend to change the message for a commit, but you can also add/remove files from the commit.

Removing Changes to the Working Directory Use checkout and the file name to undo uncommitted work. To undo changes in bulk, you can checkout the remote again, but things might get squirrelly if there are new commits (it might try to merge commits you've made), so when you're just getting started, stick to using this method when you have Uncommitted work you want to undo.

Removing Commits with Reset Use this to throw away commits you didn't want to keep because they were somehow very wrong and shouldn't exist.

Promoting a Previous Commit with Revert Use this to rollback to a previous commit, while still showing that the previous work did exist at some point.

Rewiring History with Rebase

Overview of Rebase Unlike the previous examples, rebase is about changing the commit history for the sake of a cleaner history. Its primary function is to help you rework how you got to a given solution, rather than change the final solution itself.

Bringing Your Work Up-to-Date with Rebase This is likely one of the first times you'll be “forced” to use rebase when working with Git. In this use case, you're using rebase to bring your local branch up-to-date by replaying previous commits which happened upstream as if they were already in place before you started your work.

Saving and Sharing Your Resolutions with Rerere Once you've solved a rebase once, you'll never want to have to deal with the merge conflicts that mayhave come up during the process again. Use rerere to save and share your resolutions.

Using Squash to Combine Several Commits The next most common use for rebase is to take several little commits you've made and squash them into a single commit. This allows you to hide some of your messy work, and show only a lovely final solution to your team.

Using Squash to Truncate a Branch Before Merging This example is the same as the previous, except this time you are simplifying a merge / pull request before incorporating it into the trunk.

Combining Your Changes Into Another Branch with Rebase When you merge two branches, you preserve the history that there was once a different branch. You can maintain a single line of work in your log by “merging” two branches with rebase.

Changing Previous Commits with Interactive Rebase Let's say you tucked two files into a commit a little while ago which should have actually been two separate commits. Use interactive rebasing to go back to that point and fix what went where (note: you can also do interactive commits if you want to chunk changes in a single file into two commits).

Collaborating on GitHub

Overview of GitHub Introduction to who/what GitHub is. Special notes: this is a private company, it is not based on open source software. It is a platform which improves your experience with Git, but has several of its own GitHub “isms” which can make it difficult to know when you're working with Git, and when you're working with GitHub terms.

Creating an Account Signup for a GitHub account.

Forking a Repository Start by making a copy of the repository that I created. This is now your own playground to do whatever you want in. (Review of the GitLab procedure, except for GitHub.)

Making Changes to Your Fork If you want to make changes to your fork, you need to clone the work locally, and the push the revisions back up to the server.

Making Quicker Changes with the Web UI You can avoid making a local copy by using the Web UI to make simple changes to your repository. Generally it's harder to maintain good commit message quality through this method. (Linus refuses to accept commits submitted this way because of the poor formatting on messages.)

Tracking Your Changes with Issues A review of how to create a ticket with an issue.

Importing a New Repository Import the repository you created on GitLab (or download and upload the one that I created which you initially cloned from).

Accepting a Pull Request Overview of how to deal with an incoming pull request. (might need to break this into smaller segments)

Extending GitHub with Hub There is an additional set of command line tools available through the project Hub. I've used it to convert issues into Pull Requests (although I think that feature is now deprecated). Others have used it to create Pull Request builders (create a new EC2 instance for specific pull requests). If you use GitHub a lot, and are comfortable at the command line, you may find this project useful.

Collaborating on BitBucket

Overview of BitBucket Introduction to who/what BitBucket is. Special notes: this is a private company, it is not based on open source software. It is a platform which improves your experience with Git, but has several of its own “isms” which can make it difficult to know when you're working with Git, and when you're working with their terms.

Creating an Account Signup for a BitBucket account.

Importing a Repository Import the repository you created on GitLab (or download and upload the one that I created which you initially cloned from).

Making Changes to Your Fork If you want to make changes to your fork, you need to clone the work locally, and the push the revisions back up to the server.

Tracking Your Changes with Issues A review of how to create a ticket with an issue. Check to see if you can still convert an issue into a pull request.

Accepting a Merge Request Overview of how to deal with an incoming pull request. (might need to break this into smaller segments)