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

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

1.1. Git directory structure

The essence of Git is a file system (very important, remember this sentence and understand this sentence). The historical versions and commit records (commit) of all files in the working directory are saved in the .git directory as file objects. middle.

Let's first create an empty directory named git-demo, and use the git init command to initialize the Git repository. This command will generate a .git directory in 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:

1.webp

We will focus on these directories later:

  • HEAD: The commit corresponding to the current status of the working directory, generally 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 (you will know what these three types of objects are as you read on)
  • refs: used to save the commits corresponding to branches and tags

1.2. Three major objects of Git

There is currently nothing in the Objects directory, so we create a file and submit it:

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

Add and submit:

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

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

3.webp

What is this big string?

There are three types 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 based on the file information as a checksum for the file content. Create a file with this checksum The first two characters are the subdirectory of the name, and the remaining 38 characters (checksum) are used to name the file, 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 contents of 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 require entering the entire hash value, just enter the first few digits.

Let’s take a look one by one:

065bca(blob):

4.webp

3b18e(blob):

5.webp

824244(tree):

6.webp

c5bc98(commit):

7.webp

ca96(tree):

8.webp

Look at the picture carefully. After reading it, you will almost understand what the major objects commit, blob, and tree are.

Starting with the commit object (c5bc98), the commit object stores the author of the commit, the commit's description information, signature information, and which tree objects and blob objects are included in the commit. As can be seen from the above figure, 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 corresponding relationship between these objects is shown in the figure below:

9.webp

1.3. Git Brach 和 day

Now let’s look at the contents of HEAD. As mentioned before, HEAD stores the commits corresponding to the current status 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

Let’s cut a new branch feat/work:

10.webp

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

11.webp

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

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

Next we make some modifications to 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"
12.webp

View the current HEAD:

13.webp

You can see that HEAD points to the feat/work branch, and feat/work branch points to the commit 8a442. The commit pointed to by the master branch has not changed and is still c5bc98.

View the contents of the commit object 8a442:

14.webp

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

15.webp

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

After adding this commit, the relationship between various objects in Git is as shown below:

16.webp

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

Guess you like

Origin blog.csdn.net/wan212000/article/details/132413933