Git is widely used in current software development routine to do the version control of code. With the help of IDE like IntelliJ Idea
, we can avoid manually inputing git command in command line, like git add
, git commit
, git push
etc. But when some things goes wrong, it always need command line operations.
Today, we are not going to introduce git command, but to understand how git works and what abstraction it have. As soon as we make it clear, we can understand many restrictions of git usage and many command in depth. So, when we met a new problem, we can infer a new solution from what we known, rather than just relying on Google.
Abstraction
As Torvalds explains, Git
is first designed as a file system, so it has different concepts as old VCS system.
In many ways you can just see git as a filesystem – it’s content-addressable, and it has a notion of versioning
Git is a content-addressable filesystem, which means that we can retrieve the file with the “content” of file (it is actually the content identifier, i.e. sha
checksum). What this means is that we can insert any kind of content into a Git repository, for which Git will hand you back a unique key you can use later to retrieve that content. So, we can take Git
as a simple key-value data store, what we are going to dive into is what is the key and value.
Working Tree & Stage Area & Object Database
The working directory and all files we are working on is called Working Tree
(or Working Directory
, Workspace
) in Git
. After editing files in our Working Tree
, we need to add them to a mutable index (Stage Area
) before commit those changes to persistent state (Object Database
).
The Stage Area
is a mutable index which records all tracked files in current branch and other related info like sha
checksum, file name etc (we can see the content of .git/index
, which is the index
file, to verify).
The Object Database
store four kinds of objects:
- A
blob
object is the content of a file, in binary form, with a hash as its name; - A
tree
object is the equivalent of a directory of a normal file system, which has some entries and each stores the meta info of files like file name, ; - A
commit
object refer to tree objects and some meta info like author, linking the history of commit; - A
tag
object is the reference of other object with added attributes;
From above facts, we can understand that:
- When we edit a file and commit it, Git store a new file rather than delta/changed part: because the edited file has different binary content, so a different
blob
; - In Git, rename a file will not lost this file’s history: renaming the file will not change the hash of a file, so not change blob’s name;
The following is an example shows the relationship between objects in Git
:
Notice that we actually has multiple versions of Working Tree
, Stage Area
, because in different commit, those things are different.
References
As we have discussed, the tag
object is a references with extra info. Because tag
often refers to a commit, which is much like branch reference, like master
, test
, dev
. The difference is tag
will not move, but branch ref will go forward as commits evolve.
The next reference is HEAD
. HEAD
is a special reference to commit, always points to current working branch, so, in strict sense, it is a reference to reference.
The third type of reference is the remote reference. They are actually branch reference but they are read-only, i.e. can’t be influenced by local action.
Ref
Written with StackEdit.
评论
发表评论