Check out a free preview of the full Git In-depth course
The "Git Commits" Lesson is part of the full, Git In-depth course featured in this preview video. Here's what you'd learn in this lesson:
Nina reviews commits, which is an object that stores the current contents of the project in a new commit with a log message from the user describing the changes. Nina takes questions from students.
Transcript from the "Git Commits" Lesson
[00:00:00]
>> Nina Zakharenko: Next we're gonna talk about commits. Commits are just like the other types of get objects that we talked about. A commit points to a tree, and it contains some other metadata. It contains the author and the committer, who might be different people although we generally don't use get that way.
[00:00:21]
A date when the commit was created, a message, and a parent commit, we can have one or more, we might have more parents in the case of a merge. And the SHA1 of the commit is the hash of all of this information. So a commit looks something like this.
[00:00:42]
Has that commit, identifier, the size, which tree it's pointing to. So that's kind of the root directory. Which parent it's pointing to, the author and the message. So, commits point to parent commits. In this example the lower commit is that green circle that starts with fa. That's the very first commit in our repository.
[00:01:15]
The initial commit doesn't have a parent. It's first. The second commit, the green circle above that, points to the first commit as its parent. So, graph. So, these commits point to trees, just one tree, and that tree points to other trees and other commits, and so on and so forth.
[00:01:41]
>> Nina Zakharenko: So that's our parent commit and this is a tree. Now, the tree is a snapshot of the repository. Of what the repository staging area looked like at the time of the commit. It points to those files and folders.
>> Nina Zakharenko: So a commit is a code snapshot, what the project looked like at that point in time.
[00:02:07]
And it's a combination of the changes from the staging area on the previous commit.
>> Nina Zakharenko: When we make a commit, the first status line that we'll see tells us what the hash of that commit is.
>> Nina Zakharenko: You guys have all seen this message before.
>> Nina Zakharenko: If we look in .git/objects.
[00:02:32]
All right, let's see the hash here was adf, starts with adf. If we look in .git/objects, we'll see now that there is a subdirectory called ad, with a new file on it.
>> Nina Zakharenko: Now what happens if we try to look at one of these git objects with cat for example.
[00:02:54]
You're gonna get a whole lot of nothing and that's because these binary objects, they are compressed. So if you wanted to look at them, were going to use another plumbing command and git called git cat-file. This one has two useful flags that you can use. I'm sorry. -t will print the type.
[00:03:22]
So here if I git cat-file -t, that commit, the commit that we made earlier, we'll see that the type is a blob. If we wanna print the contents of the object, we use the -p flag. So, we cat the file that's or the content that's pointed out by that shot starting with 980 and we get back the data that we put in hello word.
[00:03:59]
>> Nina Zakharenko: Let's try this again with some of the other objects that were created in that .git directory. So here I'd pick another commit. That one's a tree. I'm sorry, I'd pick another sha to pass in to git cat-file -t. This time I get a tree. If I print the contents of that I get, that first number is the mode, so that says if it's executable, for example.
[00:04:29]
The next is the blob that's stored in that tree, and that points to hello.txt.
>> Nina Zakharenko: And the next time we try to do this, we get back our commit. So if we look at this commit, we have the tree that it's pointing at, the author, which is me.
[00:04:49]
The committer, also me. And a message, the initial commit. So these commits are just objects that you can poke around and look at. There's nothing particularly scary about them. But the most important lesson that you can learn from this section is that we can't change commits. We can't change them, we can't change them with re-base, we can't edit them, we can't go back.
[00:05:20]
And change the author. We can't edit that specific commit because if you change any of the data about the commit, the commit is gonna have a new SHA1. So even if you copy everything else, you're gonna have a new date when that commit was created, meaning that commit will have a different SHA1.
[00:05:40]
Even if it has the same contents.
>> Nina Zakharenko: So, you can't change the file, the date, commit message. Any of that other data in git without changing the IDs of everything after it. And that's a great security feature, it means that if you have a commit ID, you can really be assured that not only is your project exactly the same as when it was committed.
[00:06:09]
But that nothing in its history has changed, right? No one can go, no malicious actor can go and forge with something and your commit history without it being very obvious.
>> Nina Zakharenko: Another really great thing is that prevents against corruption. So, if something has gone wrong with the disk, it will tell you that the content and the SHA don't match.
[00:06:38]
Now, a quick note about references. References are just pointers to commits. We have a few types of them. We're gonna talk more about them later. But we can have tags, branches, or head. So head is a special type of pointer and get. It points to the current commit.
[00:06:59]
When you check out a branch, HEAD also points to the current Branch. So, it's just the very last commit that you made. Now, why is changing branches in Git lightning fast? It's not pulling down new data. All it's doing is just changing a pointer.
>> Nina Zakharenko: If we look at the references under the hood, if I look in my .git directory, there are two important places where those references are stored.
[00:07:36]
The first is a file called all upper case HEAD in .git and the next is refs heads. That directory refs/heads is where all your branches live. Now, if I look at my history I have one commit. Here, the initial commit. It starts with a hash adf0. If I cat the docket /refs/heads/master file, I'm gonna get back the SHA of that initial commitment.
[00:08:20]
So, it's just a pointer. It's one of those handy features so you don't have to remember these big long jobs, right. It makes git human-readable.
>> Nina Zakharenko: Now if we check out the contents of .git/HEAD, we'll see that at this point in time, HEAD, our current branch pointer is also pointing to master.
[00:08:50]
And master's pointing to the initial commit, so HEAD is also pointing to that initial commit. And there are some cases where HEAD can point to a commit instead of a branch, and we'll talk about that a little bit later.
>> Nina Zakharenko: So here we can see that HEAD is a pointer to the current branch.
[00:09:19]
Yes?
>> Student: Can you have two HEADs?
>> Nina Zakharenko: No, just one. Git only has one HEAD at a given point in time. And if you're ever wondering what it is, you can run that command cat.git/HEAD and it'll tell you what HEAD is pointing at.
>> Student: So I think in Mercurial, I think you can have two HEADs.
[00:09:41]
>> Nina Zakharenko: Mercurial is a different beast. Before we move on to the exercise, does anyone else have anything to ask about what's in the .git directory? So we talked about three types of objects, the blob, the tree and the commit. We talked about where references are stored. And we talked about how to see what HEAD points to.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops