Preface: Plumbing Command and porcelain command
The commands in Git are divided into plumbing commands and porcelain commands:
- Porcelain commands are what we use
git add , and git commit so on.
- The plumbing command can be understood as a lower-level command, in fact a porcelain command can be done by a number of plumbing commands (see below), and the Plumbing command can help us understand how git works at the bottom.
Reading this article also requires understanding the structure of the. git directory , as well as the concepts of objects in Git (Commit objects, tree objects, blob objects , and so on), and refer to other documents yourself.
1. Git add
git add fileThe 3 steps are actually completed at the bottom:
- Calculate SHA-1 values based on file contents
- Store the contents of the file in a warehouse database (. git/objects)
- Registering the contents of a file in a. git/index file
The following functions are done with the plumbing command git add :
------------------------------------------------------------~ ? git init demo Initialized empty Git repository in /home/lvhao/demo/.git/------------------------------------------------------------~ ? cd demo ------------------------------------------------------------~/demo(master) ? echo "nihao" >> nihao.txt ------------------------------------------------------------~/demo(master*) ? git status On branch masterNo commits yetUntracked files: (use "git add <file>..." to include in what will be committed) nihao.txtnothing added to commit but untracked files present (use "git add" to track)
~/demo(master*) ? git hash-object -w nihao.txt # 对应于步骤1和2,-w表示写 ba9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf
View the. Git/objects directory at this time:
~/demo(master*) ? tree .git/objects .git/objects├── ba│ └── 9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf├── info└── pack3 directories, 1 file
~/demo(master*) ? git update-index --add --info-only nihao.txt # 对应于步骤3(关于两个参数请参见git help update-index)
Above update-index , is to update the. git/index file, for the detailed format of the file, please refer to https://stackoverflow.com/questions/4084921/ what-does-the-git-index-contain-exactly.
The index file mainly contains the file entries that exist in staging area (that is, index) and can be viewed by the git ls-files --stage main contents of the file:
~/demo(master*) ? git ls-files --stage 100644 ba9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf 0 nihao.txt
At this point, Nihao.txt already exists in staging area (that is, index), so the above three steps are equivalent to git add nihao.txt :
~/demo(master*) ? git status On branch masterNo commits yetChanges to be committed: (use "git rm --cached <file>..." to unstage) new file: nihao.txt
Summarize:
Porcelain command:
git add file
Equivalent to the Plumbing command:
git hash-object -w filegit update-index --add --info-only file
2. Git commit
The work done by commit is actually taking a "snapshot" of the current working tree (working tree) and then saving it and git commit actually completing the steps at the bottom:
- Generates a tree object based on the current working tree (the tree object records the structure of the current working directory, holds a reference to the current version of the file), and saves the tree object to the. git/objects
- A commit object is generated by the tree object above, optionally specifying the parent, message, and so on of the commit object
- Move a branch to a newly generated commit object
# 继续上面的代码~/demo(master*) ? git write-tree # 即步骤1 8e335a3e0ffa15ff97acc7f4d97e03d63612ec7a
Let's take a look at the tree object, which shows that it holds a reference to the file/directory under the current working directory:
~/demo(master*) ? git cat-file -p 8e335a 100644 blob ba9c1ad3d3b761e84cd8f9e9a18404f6f2552fcf nihao.txt
~/demo(master*) ? git commit-tree -m "Initial Commit" 8e335a # 即步骤21f1fbcf8ff46d8d2548372c38cf3f1eabf8bfbc8 # 新生成的commit的SHA-1
This is when we look at the status or the commit state, because Commit-tree only generates a new commit object and does not cause head and branch movement:
~/demo(master*) ? git status On branch masterNo commits yetChanges to be committed: (use "git rm --cached <file>..." to unstage) new file: nihao.txt
To take advantage of the current branch, we need to modify the branch's reference to the git update-ref refs/heads/分支名 commit-hash command to update the branch's location to the commit that was just created:
~/demo(master*) ? git update-ref refs/heads/master 1f1fbc # 即步骤3
Because. Git/head is pointing to the master branch by default, you get the following result:
~/demo(master) ? git status On branch masternothing to commit, working tree clean
Check the Commit log:
~/demo(master) ? git log --graph --oneline * 1f1fbcf (HEAD -> master) Initial Commit
Summarize:
of the porcelain command:
git commit -m "xxx" file
Equivalent to the Plumbing command:
git write-tree # 得到tree的hash: tree-hashgit commit-tree -m "xxx" (-p parent-hash) tree-hash # 得到commit的hash,commit-hashgit update-ref refs/heads/分支名 commit-hash
Use the Plumbing command to get a deeper understanding of how git add and git commit works