阿里云主机折上折
  • 微信号
Current Site:Index > Analysis of Git directory structure

Analysis of Git directory structure

Author:Chuan Chen 阅读数:50690人阅读 分类: 开发工具

Git is a distributed version control system, and its directory structure is key to understanding Git's internal workings. Familiarity with the purposes of these directories and files helps developers use Git more efficiently for version management.

Core Structure of the .git Directory

The heart of a Git repository is the .git directory, which contains all the metadata and objects required for version control. Below is the typical structure of the .git directory:

.git/
├── HEAD
├── config
├── description
├── hooks/
├── info/
├── objects/
├── refs/
└── index

The HEAD File

The HEAD file points to the current branch or commit. It usually contains content like this:

ref: refs/heads/main

This indicates the current branch is main. When in a "detached HEAD" state, HEAD will directly contain a commit hash:

e3d5a7f8d4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d

The config File

The config file stores repository-specific configuration information in an INI-like format:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = git@github.com:user/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

The objects Directory

The objects directory is Git's object database, storing all Git objects (blobs, trees, commits, and tags). Its structure is as follows:

objects/
├── 12/
│   └── 3456789abcdef0123456789abcdef01234567
├── ab/
│   └── cdef0123456789abcdef0123456789abcdef
└── info/
└── pack/

Each object is named using the first two characters of its SHA-1 hash as the directory name and the remaining 38 characters as the filename.

The refs Directory

The refs directory contains various references (refs), typically structured as:

refs/
├── heads/
│   ├── main
│   └── feature-branch
├── tags/
│   └── v1.0
└── remotes/
    └── origin/
        ├── HEAD
        └── main
  • heads/ contains local branches.
  • tags/ contains tags.
  • remotes/ contains remote-tracking branches.

The index File

The index file (also called the staging area) is a binary file that stores information about files ready to be committed. You can view its contents using the Git command:

git ls-files --stage

Example output:

100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       README.md
100644 5d308e1d4a5a3a7e8b9c0d1e2f3a4b5c6d7e8f9 0       src/index.js

The hooks Directory

The hooks directory contains sample client- or server-side hook scripts. These scripts are triggered during specific Git events:

hooks/
├── applypatch-msg.sample
├── commit-msg.sample
├── fsmonitor-watchman.sample
├── post-update.sample
├── pre-commit.sample
├── pre-push.sample
├── pre-rebase.sample
├── pre-receive.sample
├── prepare-commit-msg.sample
└── update.sample

To enable a hook, simply remove the .sample suffix and ensure the script is executable.

The info Directory

The info directory contains additional repository information, typically with two files:

info/
├── exclude
└── refs

The exclude file is similar to .gitignore but applies only to the current repository and is not shared.

Packed Refs and Objects

For large repositories, Git packs refs and objects for efficiency:

  • The packed-refs file contains packed refs.
  • The objects/pack/ directory contains packed objects.

Example packed-refs file:

# pack-refs with: peeled fully-peeled 
e3d5a7f8d4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d refs/heads/main
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b refs/tags/v1.0
^f1e2d3c4b5a6f7e8d9c0b1a2f3e4d5c6b7a8d9

Relationship Between the Working Area and the Git Directory

The working area consists of all contents in the project directory except .git. Git tracks working area files in the following way:

  1. Working directory: Actual file content.
  2. Staging area (index): Snapshot of files ready to be committed.
  3. Object database (objects): Committed files and directory structures.

Special Files and Directories

  • COMMIT_EDITMSG: Stores the edit message of the last commit.
  • ORIG_HEAD: Stores the position of HEAD before certain operations.
  • FETCH_HEAD: Records the result of the last fetch.
  • MERGE_HEAD: Stores the commit to be merged during a merge operation.
  • CHERRY_PICK_HEAD: Stores the source commit during a cherry-pick operation.

Git Directory Creation Process

When initializing a new repository, Git creates the following structure:

git init sample-repo

The resulting directory structure:

sample-repo/
└── .git/
    ├── HEAD
    ├── config
    ├── description
    ├── hooks/
    ├── info/
    │   └── exclude
    ├── objects/
    │   ├── info/
    │   └── pack/
    └── refs/
        ├── heads/
        └── tags/

Practical Example

The following JavaScript code checks the Git directory structure:

const fs = require('fs');
const path = require('path');

function checkGitStructure(dirPath) {
  const gitPath = path.join(dirPath, '.git');
  if (!fs.existsSync(gitPath)) {
    console.log('Not a Git repository');
    return;
  }

  const structure = {
    HEAD: fs.existsSync(path.join(gitPath, 'HEAD')),
    config: fs.existsSync(path.join(gitPath, 'config')),
    objects: fs.existsSync(path.join(gitPath, 'objects')),
    refs: fs.existsSync(path.join(gitPath, 'refs')),
    hooks: fs.readdirSync(path.join(gitPath, 'hooks'))
  };

  console.log('Git directory structure:');
  console.log(structure);
}

// Example usage
checkGitStructure(process.cwd());

Directory Differences Across Git Versions

The repository format version (repositoryformatversion) affects the directory structure:

  • Version 0: Traditional format.
  • Version 1: Supports the extensions/ directory.
    • extensions/objectFormat: Specifies the object format (e.g., SHA-256).
    • extensions/refStorage: Specifies the ref storage format.

Structure of a Bare Repository

A bare repository (without a working area) has a slightly different structure:

repo.git/
├── HEAD
├── config
├── description
├── hooks/
├── info/
├── objects/
└── refs/

Key differences:

  1. No index file.
  2. No working area files.
  3. Typically named with a .git suffix.

Git's Internal Object Model

The objects in the Git directory fall into the following types:

  1. Blob: File content.
  2. Tree: Directory structure.
  3. Commit: Commit information.
  4. Tag: Annotated tags.

You can view an object's content using:

git cat-file -p <object-hash>

Reference Logs (reflog)

Reference logs are stored in the logs/ directory and record all reference changes:

logs/
├── HEAD
└── refs/
    └── heads/
        └── main

Example of HEAD's reflog:

git reflog show HEAD

Output:

e3d5a7f HEAD@{0}: commit: Update README
a1b2c3d HEAD@{1}: pull origin main: Fast-forward
f4e5d6c HEAD@{2}: commit: Add new feature

Git Directories for Submodules

When using submodules, each submodule has its own .git directory, usually as a file:

.gitmodules
modules/
└── submodule-name/
    └── .git

Example .gitmodules file:

[submodule "lib"]
    path = lib
    url = https://github.com/user/lib.git

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:环境变量影响

下一篇:对象存储格式

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.