linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it works
  • Уроки
  • База знаний
  • Собеседование
home/git/lessons/git-lab-04-1-plumbing-log

lesson ── git-labs ── ~20 мин ── 7 шагов

Реконструируй log руками через cat-file

Цель - пройти Git «снизу вверх». Соберёшь репо из нескольких коммитов обычными командами, потом руками доберёшься от ветки до коммита, до tree, до blob - используя только cat-file. Когда сделаешь это раз, все остальные plumbing-команды читаются как очевидные.

▶ интерактивный sandbox

Поднимется контейнер gitlab/git-base с git, bash, pre-commit. В браузере откроется терминал, можно сразу git init. Каждый шаг проверяется автоматически. Сеть air-gapped, github.com недоступен.

запустить sandbox →

stack ── git · bash · 256 MB RAM · air-gapped · самоуничтожается через 30 мин простоя

Шаги

  1. 01

    Создай маленький репо с тремя коммитами

    bash
    cd /home/student/work
    mkdir -p plumbing-log && cd plumbing-log
    git init -b main
    echo "v1" > version.txt
    git add . && git commit -m "init"
    echo "v2" > version.txt
    git commit -am "bump to v2"    # -a = staged уже отслеживаемых, -m = inline-сообщение
    mkdir docs
    echo "# readme" > docs/README.md
    git add . && git commit -m "add docs"
    git log --oneline              # --oneline = одна строка на коммит (short-sha + subject)

    Три коммита, второй меняет файл, третий добавляет директорию. Дальше всё это будем читать руками.

    ✓ Три коммита на месте. Готово к раскопкам.

  2. 02

    Найди SHA коммита через файл ветки

    Ветка - это просто текстовый файл с SHA. Прочти его:

    bash
    cd /home/student/work/plumbing-log
    cat .git/refs/heads/main

    Сравни с git rev-parse HEAD - один и тот же SHA. То есть git rev-parse - это cat плюс resolve символических ссылок.

    ✓ SHA HEAD найден. Это указатель на последний коммит.

  3. 03

    Прочти сам commit-объект

    bash
    cd /home/student/work/plumbing-log
    SHA=$(cat .git/refs/heads/main)   # ref - текстовый файл с SHA, не магия
    git cat-file -t $SHA              # -t = тип объекта (commit)
    git cat-file -p $SHA              # -p = pretty-print: tree, parent, author, message

    Тип - commit. Внутри - поля: tree <sha>, parent <sha>, author, committer, сообщение. Запомни tree-SHA и parent-SHA - они тебе нужны.

    подсказка

    Зафиксируй tree-SHA: `TREE=$(git cat-file -p $SHA | head -1 | cut -d' ' -f2)`.

    ✓ Коммит читается. Видны tree и parent.

  4. 04

    Раскрой tree последнего коммита

    bash
    cd /home/student/work/plumbing-log
    SHA=$(cat .git/refs/heads/main)
    # первая строка вывода - "tree <sha>", cut -f2 берёт второе поле
    TREE=$(git cat-file -p $SHA | head -1 | cut -d' ' -f2)
    git cat-file -t $TREE         # должно быть "tree"
    git cat-file -p $TREE         # список записей: mode type sha name

    Внутри tree - две записи: version.txt (blob) и docs (другой tree). Обрати внимание на колонку mode: 100644 для файла, 040000 для подкаталога.

    ✓ Tree раскрыт. Видно файл и подкаталог.

  5. 05

    Прочти содержимое blob'а

    bash
    cd /home/student/work/plumbing-log
    SHA=$(cat .git/refs/heads/main)
    TREE=$(git cat-file -p $SHA | head -1 | cut -d' ' -f2)
    # awk '{print $3}' - формат tree-записи: "<mode> <type> <sha> <name>", sha в 3-й колонке
    BLOB=$(git cat-file -p $TREE | grep 'version.txt' | awk '{print $3}')
    git cat-file -p $BLOB         # содержимое файла version.txt

    Должно вывести v2. Сравни с тем, что в working tree: cat version.txt. То же содержимое - просто другой путь к нему.

    ✓ Blob прочитан. Это финальный лист дерева объектов.

  6. 06

    Пройди один шаг назад по parent

    Связь между коммитами - поле parent. Сделай шаг назад руками:

    bash
    cd /home/student/work/plumbing-log
    SHA=$(cat .git/refs/heads/main)
    # ищем строку "parent <sha>" в commit'е, берём sha (2-е поле)
    PARENT=$(git cat-file -p $SHA | grep '^parent' | head -1 | cut -d' ' -f2)
    git cat-file -p $PARENT       # это второй коммит из лога ("bump to v2")

    Это второй коммит из лога. Tree у него другой - там version.txt содержит v2, но нет docs/. Каждый коммит - snapshot, не diff.

    ✓ Шаг назад сделан. Теперь у тебя в голове есть весь граф.

  7. 07

    Напиши скрипт, который воспроизводит git log

    Собери всё вместе. Скрипт, который от HEAD идёт по parent и печатает SHA + первое слово сообщения:

    bash
    cd /home/student/work/plumbing-log
    # <<'EOF' (с кавычками) = heredoc без интерполяции $ внутри
    cat > log.sh <<'EOF'
    #!/bin/bash
    cur=$(cat .git/refs/heads/main)           # стартуем с tip ветки
    while [ -n "$cur" ]; do                   # пока есть parent - идём дальше
      msg=$(git cat-file -p $cur | tail -1)   # последняя строка commit'а - тело сообщения
      echo "${cur:0:7} $msg"                  # ${cur:0:7} = short-sha (первые 7 hex)
      cur=$(git cat-file -p $cur | grep '^parent' | head -1 | cut -d' ' -f2)
    done
    EOF
    chmod +x log.sh
    ./log.sh
    git log --oneline             # сравни вывод с твоим скриптом - должны совпасть

    Сравни выводы. Должно совпасть построчно (с точностью до short-sha).

    ✓ Свой git log готов. Внутренности больше не магия.

Что ты узнал

git cat-file -t - тип объекта, -p - его pretty-print. Цепочка: ref -> commit -> tree -> blob. Каждое звено - один SHA.

команды

  • cat .git/refs/heads/mainSHA текущего коммита ветки
  • git cat-file -p <commit-sha>распечатать commit (увидеть tree-sha)
  • git cat-file -p <tree-sha>распечатать tree (увидеть blob-sha)
  • git cat-file -p <blob-sha>увидеть содержимое файла

концепции

  • · ref - текстовый файл со ссылкой на commit
  • · commit -> tree (snapshot) + parent (history)
  • · tree -> blob (содержимое) + mode + name

← предыдущая

Собери коммит руками через plumbing-команды

следующая →

Три зоны: working tree, index, repository

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки