http://eagain.net/articles/git-for-computer-scientists/
Git object storage is just a DAG of objects, with several types of objects. They are all compressed and marked with SHA-1 hash.
Blob: The simplest object is just a heap of bytes. Often it is a file, but it can also be a symbolic link or anything else. The object that points to the BLOB to specify the specific semantics of the BLOB.
Tree: The directory is marked by the tree object. They refer to the relevant blobs that contain the contents of the file and the trees that point to the other subdirectories;
When a node points to another node in the DAG, it will depend on the node that is pointed to: that is, the node cannot exist without the node being pointed to. No other node that node points to will be recovered by a git GC command, or a inodes emergency rescue command similar to a file system without a file name: Git fsck--lost-found
Commit: A commit refers to a tree object that reflects the state of the file set when the commit is executed. It also references 0. n a commits of its fathers. More than one father commit means this is a merge commit, without a commit of the parent means initial commit, and of course there may be more than one initial Commit scenario: This usually means that two separate projects are joined together. The content of the commit object is a commit message.
Refs:referrences, or heads or branches, is like a sticky note that extracts a node from a DAG. Unlike the DAG feature, which only allows node to be added to the inside without changing the changes, this note can be moved arbitrarily. They are not recorded in history, they do not pass directly between repo, they are like a bookmark, "I am working here."
The git commit command adds a node to the DAG and moves the current branch note forward to the new node.
HEAD ref has something special because it actually points to another ref. It usually points to the currently active branch. Common refs is actually in heads/xxx namespace, but you tend to ignore heads/this part
The remote Refs:remote referrence is marked with a different color, which is also a note. The difference from normal refs is different namespace, and the fact that remote refs is usually controlled by remote server will update them when the GIT fetch operation is in place.
Tag: A tag is not only a node in the DAG but also a note. A tag that points to a commit and contains an optional message and a GPG signature;
The note itself simply provides a quick way to access the tag, and once it is lost, it can be retrieved via the Git fsck--lost-found.
The nodes in the DAG can be moved from one repo to another repo, which can be saved in a more efficient way (packs), and nodes that are no longer used will be garbage cleaned.
But finally, a git repo is always a dag and a corresponding set of notes
History:
How can we visualize similar merges actions after having the above knowledge of how Git preserves version history? It is best to use graphs to express:
Above is the simplest of a repo, we clone a remote repo, and the repo only a commit in the inside;
We have already taken the remote, and the fetch contains a commit from someone else, and the commit has not yet been merge;
Shows the situation after executing git merge remotes/myserver/master. Because the merge capability is fast forward (that is, we have no new changes in local branch Shanghai, so we can directly fast forward), after the merge, only the change: we moved our sign to the new node up, and accordingly changed the contents of working directory;
, we have a commit in the local and we have a git fetch, we keep a new commit locally and have a new remote commit, in which case a merge is required.
The results of git merge Remotes/myserver/master execution are as follows. Since we have a new local commits, we are no longer fast forward, and we have to indicate this merge by creating a new commit node in the DAG. Note that merge commit has two parent commits.
In, we have made several new commits and have a new merge. The Git Dag records any action history that has occurred;
The "stitch" pattern above sometimes seems to annoy life. If you don't have a publish your branch, or if you have clearly communicated, others should isn't base their work on it, you have another option: You can rebase your BR Anch, not merge. The advantage of doing this is that your commit will be replaced by another commit with a different parent, and your branch will move there. (This commit will be the parent commit with the latest commit of the remote branch)
Your old commit will still be saved in the Dag knowing that Git's garbage collection mechanism works to remove it. Of course, if you have additional notes pointing to the old commit, they will always point to it, and just because someone points to that unused commit, this will allow the old commit to be saved without being cleaned out.
Do not rebase branches that others has created new commits on top of.
After garbage collection, such as (or just or slightly unreachable commit), and create a new commit on the rebased branch
Rebase also knows how to rebase multiple commits in a commit
git internal for computer scientists