Naked git structure
The following is an freshly initialized git v188.8.131.52 repository.
. └── .git/ ├── HEAD ├── branches/ ├── config ├── description ├── hooks/ │ ├── applypatch-ms │ ├── commit-msg │ ├── post-commit │ ├── post-receive │ ├── post-update │ ├── pre-applypatc │ ├── pre-commit │ ├── pre-rebase │ └── update ├── info/ │ └── exclude ├── objects/ │ ├── info/ │ └── pack/ └── refs/ ├── heads/ └── tags/
HEAD indicates the currently checked out code. This will usually point to the branch you're currently working on.
You can also enter what git calls a "detached HEAD" state, where you are not on a local branch. In this state the HEAD points directly to a commit rather than a branch.
The configuration file for this git repository. It can contain settings for how to manage and store data in the local repository, remote repositories it knows about, information about the local user and other configuration data for git itself.
Used by repository browser tools - contains a description of what this project is. Not normally changed in non-shared repositories.
Contains scripts to be run when particular events happen within the git repository.
Hooks would be used, for example, to run tests before creating each commit, filter uploaded content, and implement other such custom requirements.
This is where all the files, directory listings, commits and such are stored.
There are both unpacked objects in numbered directories under this, and "packs" containing many compressed objects within a pack directory. The uncompressed objects will periodically be collected together by automatic "git gc" runs in to packs.
This contains the information about which branches point where. It normally contains a "heads" directory for your local branches and a "remotes" directory for your copies of remote branches. Not all branches are within these directories - branches which have not changed recently may be found in the file .git/packed-refs .
A Git repository is made up of these object types:
- A blob holds the entire contents of a single file. It doesn’t hold any information about the name of the file or any other metadata, just the contents.
- A tree represents the state of a directory tree. It contains the pathnames of all the component files and their modes, along with the IDs of the blobs holding their contents. Note that there is no representation for a directory on its own, so a Git repository cannot record the fact that subdirectories were created or deleted, only the files in them.
- A commit points to a tree representing the state of the source tree as of immediately after that commit. It also records the date/time of the commit, the author/committer information, and pointers to any parent(s) of that commit, representing the immediately-prior state of the source tree.
- A tag is a name pointing to a commit. These are useful, for example, to mark release milestones. Tags can optionally be digitally signed, to guarantee the authenticity of the commit.
- A branch is a name pointing to a commit. The difference between a branch and a tag is that, when a branch is the currently-checked-out branch, then adding a new commit will automatically update the branch pointer to point to the new commit.
Blobs, trees and commits all have IDs which are computed from SHA-1 hashes of their contents. These IDs allow different Git processes on different machines to tell whether they have identical copies of things, without having to transfer their entire contents over. Because SHA-1 is a cryptographically strong hash algorithm, it is practically impossible to make a change to the contents of any of these objects without changing its ID. Git doesn’t prevent you from rewriting history, but you cannot hide the fact that you have done so.
A commit may have 0, 1 or more parents. Typically there is only one commit with no parents—a root commit—and that is the first commit to the repository. A commit which makes some change to one branch will have a single parent, the previous commit on that branch. A commit which is a merge from two or more branches will have two or more parent commits.
Note that a branch points to a single commit; the chain of commits is implicit in the parent(s) of that commit, and their parents, and so on.
Topology Of Commits
The commit history in Git is arranged as a directed acyclic graph (DAG). To understand what this means, let’s take the terms step by step.
- In mathematical terms, a graph is a bunch of points (nodes) connected by lines (edges).
- A directed graph is one where each edge has a direction, represented here by an arrowhead.
- Acyclic means that, if you start from any point and traverse edges in the direction of the arrows, you can never get back to your starting point, no matter what choice you make at any branch.
In Git terms, each node represents a commit, and the lines and arrows represent parent-child relationships. Banning cycles simply means that a commit cannot be a (direct or indirect) parent or a child of itself!
The reflogs record changes that are not saved as part of the commit history—things like rebases, fast-forward merges, resets and the like. There is one reflog per branch. The reflog is not a public part of the repository, it is strictly specific to your local copy, and information is only kept in it for a limited time (2 weeks by default). It provides a safety net, allowing you to recover from mistakes like deleting or overwriting things you didn’t mean to.
Reachability And Garbage Collection
A commit is reachable if it is pointed to by a branch, tag or reflog entry, or is a parent of a commit which is reachable. A tree is correspondingly reachable if it is pointed to by a reachable commit, and a blob is reachable if it is pointed to by a reachable tree. Other commit/tree/blob objects are unreachable, and are not really serving any purpose beyond taking up space.
It is quite normal for your repositories to accumulate unreachable objects over time, perhaps as a result of aborted commits, deletion of unwanted branches, that kind of thing. Such objects will be deleted from the repository by a
git gc command. This is also done automatically every now and then by some other commands, so it is rarely necessary to invoke
git gc explicitly.
- ^ Generated with tree v184.108.40.206 using