Get started in three minutes! Understand the underlying working principle of Git in one article

This is an article that will allow you to quickly understand the working principle of Git, practical case analysis, believe me, 3 minutes, you can definitely gain something!

 

Git directory structure

The essence of Git is a file system (very important, remember this sentence, understand this sentence), the historical version of all files in the working directory and the commit record (commit) are stored in the .git directory in the form of file objects middle.

Let's first create an empty directory called git-demo and initialize the Git repository with the git init command. This command will generate a .git directory under the working directory, which will be used to save the historical versions, commit, branch, tag and other information of all file history in the workspace.

$ mkdir git-demo
$ cd git-demo
$ git init

Its directory structure is as follows:

picture

We will focus on these directories later:

  • HEAD: The commit corresponding to the current state of the working directory, generally speaking, it is the head of the current branch. HEAD can also be directly set to a specific commit through the git checkout command. This situation is called detached HEAD
  • objects: This is the directory that actually saves Git objects, including three types of objects commit, tree, and blob (specifically, what are these three types of objects, you will know when you look down slowly)
  • refs: used to save the commit corresponding to branch and tag

Git three objects

Currently there is nothing in the Objects directory, let's create a file and commit:

$ git:(master) echo "my project" > README
$ git:(master) mkdir src
$ git:(master) echo "hello world" > src/file1.txt

Add and commit:

$ git:(master) git add .
$ git:(master) git commit -m "init commit"

picture

As you can see from the printout, the above command creates a commit object that contains two files. Check the .git/objects directory, and you can see that 5 subdirectories 06, 3b, 82, c5, ca have been added to this directory, and each subdirectory has a file with a long string of alphanumeric commands:

picture

What is this big string?

There are three kinds of objects stored in the Git Object directory: Commit, Tree and Blob. Git will generate a file for the object, and generate a SHA-1 hash value as the checksum of the file content according to the file information. The first two characters are the subdirectory of the name, and the remaining 38 characters (checksum) are the file name, and the file is saved in the subdirectory.

You can view the object type through the git cat-file -t hash value command, and view the content in the object through the git cat-file -p hash value command. The hash value is the directory name + file name. If there is no ambiguity, The command does not need to enter the entire hash value, just enter the first few digits.

Let's look at them one by one:

065bca(blob):

picture

3b18e(blob):

picture

824244(tree):

picture

c5bc98(commit):

picture

ca96(tree):

picture

Look at the picture carefully, and after reading it, you will almost know what the big objects such as commit, blob, and tree are.

Start with the commit object (c5bc98), which stores the author of the commit, the description information of the commit, signature information, and which tree objects and blob objects are contained in the commit. It can be seen from the figure above that the tree object (ca96) is included.

The tree object can be regarded as the root directory of all files related to this submission. You can see that the tree object ca96 contains a blob object (065bca), which is the README file, and a tree object (824244), which is the src directory. The blob object stores the real content.

The correspondence between these objects is shown in the figure below:

picture

Git Broch 和 day

Now look at the content in HEAD. As mentioned earlier, HEAD stores the commit corresponding to the current state of the working directory:

$ git:(master) cat .git/HEAD
ref: refs/heads/master
$ git:(master) cat .git/refs/heads/master
c5bc98b8990bedd7444da537320559e601eba87b

c5bc98 is our latest commit!

master is a branch name, so the essence of branch is a pointer to commit

We fork a new branch feat/work:

picture

Check the commit values ​​in refs/heads/master and refs/heads/feat/work:

picture

As can be seen from its content, the feat/work branch does not create any new version files, and points to the c5bc98 commit just like the master.

As can be seen from the above experiment, a branch is actually just an application of a commit object, and Git does not store a copy for each branch, so there is almost no cost to create a branch in git.

Next, we make some changes on the feat/work branch, and then submit:

$ git:(feat/work) echo "new line" >> src/file1.txt
$ git:(feat/work) echo "do nothing" >> License
$ git:(feat/work) git add .
$ git:(feat/work) git commit -m "some change"

picture

View the current HEAD:

picture

It can be seen that HEAD points to the feat/work branch, and feat/work branch points to the 8a442 commit, and the commit pointed to by the master branch remains unchanged, still c5bc98.

View the content of the commit object 8a442:

picture

You can see that commit has a parent field, pointing to the previous commit c5bc98. Also contains a tree object (2a9dd):

picture

It can be observed that since the README has not changed, it still points to the blob object 065bca. License is a new blob object, and src and file1.txt point to the new version of the object.

After adding this commit, the relationship of each object in Git is shown in the following figure:

picture

Tag is similar to branch, and it is also a pointer to a commit. The difference is that after the tag is created, the commit it points to cannot be changed, but after the branch is created, its pointer will move forward after submitting a new commit.

Guess you like

Origin blog.csdn.net/Z__7Gk/article/details/132341376