In this lesson, we'll cover how to navigate around and work with code from different commits. Occasionally, we provide a reference repository that only has one branch and multiple commits. Each commit tracks what the project's code should look like at that moment. So, you'll need to learn how to access specific commits. More generally speaking, this is an important part of Git functionality to learn.
When downloading the project from a specific commit, the process is exactly the same as if you downloaded from a specific branch. Navigate to that specific commit in GitHub as the GIF below shows:
As we see in the GIF, we can click on Commits in a repository and then click on the
<> icon to the far right of the commit we want to access. Once we access that commit, we can navigate around the code in GitHub or download code from that specific commit directly using the Download ZIP option. However, if we try to clone the project from that specific commit, we'll just get a link to the repository itself. That's because specific commits aren't part of a branch and GitHub doesn't have a way to directly link to that code. So if we clone the project and then open the code, it will be the code from the most recent commit. Often, that will not be what we want.
Let's take a look at the GIF above again - you'll see that when we navigate to a specific commit, we can click on a clipboard icon instead of
<>. This copies the SHA-1 hash of the specific commit. A hash is just a unique string of specific length.
Here's an image that further clarifies where the clipboard is:
We've added a green circle around the clipboard icon so it's clear. As we can see, part of the SHA-1 hash is just to the right of the clipboard. If we click on the hash, it will take us to the changes that have been made since the previous commit - which can also be super helpful if we want to look at how the code has changed. However, that's not what we are looking for here.
To actually get to a specific commit, we can clone the project and then use the
$ git checkout [SHA-1_HASH] command to access that specific commit, where
[SHA-1_HASH] is the copied hash of the commit we want. Remember, we need to grab the hash by clicking on the clipboard icon by the commit in GitHub.
Here's an example - along with what will happen when we checkout a specific commit.
$ git checkout bddd3819ecf0bc36ec8c35e6fbb34546fb6a1579 Note: checking out 'bddd3819ecf0bc36ec8c35e6fbb34546fb6a1579'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at bddd381 project with functioning environment
We are now looking at the code from the specific commit that we've checked out, but what's going on with the detached HEAD state? This state can seem scary for beginners, but it just means we are looking at code from a commit rather than a branch. If we were to make a bunch of commits to our code while we are in a detached HEAD state, that code would be lost if we then moved to another already existing branch. That's because git doesn't know what to do with the committed code in the detached HEAD state, so it will get rid of it while doing routine cleanup when we switch to another existing branch.
So what should we do if we want to go to a specific commit, update the code, and then be able to properly add it to git?
Fortunately, the instructions are in the message that git helpfully includes for us when we switch into a detached HEAD state. We just need to use the
$ git checkout -b command to create a new branch! We've used this command before, and as we know,
$ git checkout -b doesn't just create a new branch - it switches us to that branch and includes all the code from the branch (or detached HEAD) that we just switched from.
So if you are in a situation where you want to navigate to a specific commit and then make changes to the code, that is what you need to do. If you want to simulate the process of creating a repository that has a branch for each commit, you can checkout the commit and then immediately create a new branch from that commit with a name of your choosing. Your code will no longer be in a detached HEAD state and you can update or work with it just as you would code on any other branch.
However, you do need to be careful if you plan to eventually merge code that was once in a detached HEAD state. Your code will likely diverge considerably if you use
$ git checkout to go to a prior commit from main and then you start working on a new branch from there. That means there will be merge conflicts to fix once you merge code from the main branch.
In general, the repository code we provide is meant to be a reference - not code you should actually work from yourself. Ideally, we always recommend working along with the lessons and writing the code from scratch. If you do need to work from a specific commit in the reference repository (such as if you don't have the project available yourself or your code isn't working correctly), it's often easier to just download the ZIP file and work from there - since it won't be attached to a repository and you can treat that starter code as your scratch code to build out further. However, it's important to know what a detached HEAD state is - and how to get it out of it as needed.
Lesson 19 of 43
Last updated October 18, 2021