Video

Want to see the full-length video right now for free?

Notes

Welcome to our Mastering Git course!

In these videos we'll teach you everything you need to know to about Git to work efficiently and confidently.

This first video is focused on getting confident working within your repositories. Later videos will cover many different workflows, commands, and configurations. This video will make sure you're comfortable trying them all out, and not worried about "breaking" a repository.

Introductory Resources

Before moving on, we do want to highlight that this course is not intended to be your introduction to Git, but instead expects that you're familiar with core operations like staging and committing files, branching, viewing the log, and pushing to GitHub. If you're not quite there, we recommend starting with a few introductory resources, then coming back here when you're ready:

  • Try Git is a great interactive tutorial that requires no prior knowledge and walks you through the basic commands in the browser.
  • The Introduction Series in the GitHub & Git Foundations video series is a collection of short, focused lessons, introducing the primary commands and workflows of git.

Git Context In Prompt

One of the key features of my command line Git workflow is having the current Git context always displayed as part of the prompt. In particular, the prompt will display each of the following (depending on the current Git context):

  • Current branch name
  • Current commit hash
  • Indication of repo status (clean vs uncommitted changes)

This context is critical to my being able to confidently work with my repo, helping me to avoid common mistakes like committing to the wrong branch, forgetting to commit a specific file, etc.

The thoughtbot dotfiles contain a streamlined Git info segment, and my personal dotfiles contain a Git prompt configuration that includes the branch, current commit hash, and dirty status (note, this relies on some features of oh-my-zsh to display properly). Another option would be to use the excellent pure prompt for zsh which contains all this and more, but is still nice and snappy.

Always Be Committing!

Commits are a safety net, protecting you from any mishaps down the road. They're like save points in a video game and you can never have too many. Likewise, you can always reorder, combine, or even remove commits from your history if you want to clean it up later. Once you've made a commit, it's darn near impossible to lose that work without trying to.

I've never regretted making a commit, but I have regretted not making a commit. So, err on the side of caution and commit all the time!

Git Stash for Safety

git stash is a command that will grab all of the changes in the working directory and store them away. This allows you to focus on an emergency bugfix or similar, and later revisit the code you had stashed away.

This of this command as your panic button. Need to make an emergency change on another branch? Running off to lunch and not sure what to make of your experiment? git stash has your back.

The one caveat that makes git stash slightly less than ideal is that by default it will only grab changes to files already known to Git. This means it will leave behind any new or untracked files. When I run git stash I want it to grab everything and get back to an empty status, but unfortunately this is not the default.

Luckily, we can solve this with the -u, "include untracked", flag to the stash command. There isn't a way to make this the default behavior, but from now on, feel free to always use the -u flag and stash will work as expected:

$ git stash -u

The Reflog - Our Hero

The reflog is Git's internal record of every explicit change we've made. Any time you commit, reset, branch, merge, or otherwise update what Git is focused on (technically what HEAD is pointing at), Git makes a record of that.

Likewise, since everything in Git is immutable, all commits stick around even after we perform a seemingly destructive action like rebasing. With the reflog, we can look up these forgotten commits and restore them easily.

We won't go into detail here as our goal is not to master the reflog command, but instead simply introduce it to give us that last little bit of confidence as we try out more advanced commands within our repos. As long as we follow the golden rule of committing all the time, the reflog will allow us to get back to any version of our code we need.

Viewing The Reflog

The reflog can be viewed with the bare git reflog command.

$ git reflog
3001aaf HEAD@{0}: pull: Fast-forward
1576f8b HEAD@{1}: pull: Fast-forward
7caa99e HEAD@{2}: merge update-rss-summaries: Fast-forward
1a8a17d HEAD@{3}: checkout: moving from update-rss-summaries to master
7caa99e HEAD@{4}: checkout: moving from master to update-rss-summaries
1a8a17d HEAD@{5}: checkout: moving from update-rss-summaries to master
7caa99e HEAD@{6}: rebase -i (finish): returning to refs/heads/update-rss-summaries
# ...

The reflog lists the commit and operation for every single command that changes what we currently have checked out in working directory. Every commit, branch, checkout, rebase, reset, etc. all are tracked, and from this history we can restore any version of the code.

Branch Specific Reflog

The reflog can be focused down to just a specific branch by adding the branch name as an argument.

$ g reflog show update-landing-page
300b862 update-landing-page@{0}: commit (amend): Add bundler-audit to check gems for security issues
09682a4 update-landing-page@{1}: reset: moving to HEAD^1
a3b5690 update-landing-page@{2}: commit: Update gem versions based on bundler audit report
09682a4 update-landing-page@{3}: commit: Add bundler-audit to check gems for security issues
6a327f3 update-landing-page@{4}: branch: Created from HEAD

From there, you could restore your branch to a previous commit, for instance 09682a4, with:

$ git reset --hard 09682a4

Conclusion

With that, we've laid the foundation for the remainder of this course. With the combination of Git info in prompt, using git stash -u as our panic button, committing all the time, and knowing that the reflog has our back, we're ready to confidently move on to the more advanced commands and workflows covered in the remaining videos.