# Янник Килхер: «Фундаментально Git — это граф коммитов»

Источник: https://www.youtube.com/watch?v=BBp0tHcirtQ
Канал: Yannic Kilcher
Опубликовано: 13.12.2017

---

Совместная научная работа над статьями и исследованиями часто превращается в хаос из-за бесконечных копий документов с названиями в духе «финальная версия_исправлено_ред». Популяризатор науки и исследователь искусственного интеллекта Янник Килхер (Yannic Kilcher) предлагает решить эту проблему с помощью Git — инструмента, который традиционно ассоциируется с программированием, но идеально подходит для академической коллаборации. В своем видеоруководстве он подробно разбирает базовую логику работы системы версионирования, помогая авторам навсегда забыть о путанице в файлах.

## 📂 Фундамент технологии: Git как граф коммитов
[[JUMP:0:42]]



В основе работы Git лежит простая математическая структура — направленный граф. Традиционный подход к контролю версий, когда пользователи вручную копируют файлы и переименовывают их в «версию 2» или «самую финальную версию», неэффективен и приводит к ошибкам. Git решает эту проблему изящнее. 

Главным элементом системы является коммит (commit), который метафорически можно представить в виде изолированного пузыря или узла графа. Каждый коммит содержит в себе полный снимок (образ) определенной папки на жестком диске — репозитория — в конкретный момент времени. Эти состояния сохраняются в базе данных системы навсегда.

Связующим звеном графа выступают указатели. Когда пользователь вносит изменения и создает второй коммит, этот новый узел автоматически получает ссылку на своего «родителя» — предыдущий коммит. Таким образом формируется непрерывная цепочка версий. 

Каждый коммит обладает уникальным именем — хэшем (например, `f5c259...`). Этот идентификатор вычисляется на основе содержимого всех файлов и ссылки на родительский узел. Для обращения к конкретному состоянию системы не обязательно вводить длинную строку символов целиком: по словам Янника Килхера, достаточно указать первые несколько букв или цифр, если они уникальны. Хотя под капотом Git в целях оптимизации сохраняет лишь разницу (diff) между файлами, для простоты понимания разработчику достаточно представлять коммит как полноценный снимок файловой системы.

## 🚩 Управление указателями: теги и ветки
[[JUMP:4:43]]

Для удобной навигации по графу коммитов в Git предусмотрены два типа текстовых ярлыков.

Первый тип — это теги (tags). Тег представляет собой статичное пользовательское имя для конкретного коммита, напоминающее жестко закрепленный флажок (например, `v1` для первой версии статьи). Сколько бы новых коммитов ни создавалось позже, тег всегда будет указывать на один и тот же исторический узел, избавляя от необходимости помнить его хэш.

Второй тип — ветки (branches). Ветка работает иначе: это динамический указатель. Когда пользователь находится на определенном коммите и создает поверх него новое изменение, Git автоматически стирает старый флажок ветки и переносит его на только что созданный коммит. 

По умолчанию в любой системе Git автоматически создается основная ветка под названием `master`. Работа в ветке `master` означает последовательное создание коммитов, за которыми непрерывно следует этот одноименный флажок.

При необходимости пользователь может принудительно переместить флажок ветки или тега на любой другой узел графа. Если в процессе работы группа коммитов оказалась «заброшена» (на них больше не ссылается ни одна ветка или тег), встроенная система сборки мусора (garbage collection) со временем безвозвратно удалит их с диска. Однако Янник Килхер предупреждает, что ручное перемещение указателей может быть опасным при совместной работе, так как коллеги могли уже взять брошенные коммиты за основу для своих собственных изменений.

## 🌿 Параллельное производство и логика слияния
[[JUMP:8:42]]



Истинная сила Git раскрывается при использовании нескольких параллельных веток. Этот подход незаменим, когда над одним проектом работают несколько человек. Пока один участник тестирует новую структуру статьи или экспериментальный код в отдельной ветке (например, `f1`), остальные авторы могут спокойно продолжать исправлять ошибки в основной ветке `master`. Поскольку изоляция защищает стабильную версию от багов, незавершенная работа не мешает общему прогрессу команды.

Когда работа над новой функцией или разделом завершена, ветки необходимо объединить с помощью операции слияния (merge). Этот процесс создает особый тип узла — коммит слияния (merge commit), который уникален тем, что имеет сразу двух «родителей». Задача этого коммита — бесконфликтно собрать воедино изменения из двух разных веток, берущих начало от одного общего предка.

В подавляющем большинстве случаев слияние происходит в автоматическом режиме благодаря встроенным алгоритмам Git. Система руководствуется простой логикой:

* Если в ветке «А» файл был изменен, а в ветке «Б» остался прежним, Git считает изменение приоритетным и сохраняет его.
* Если в одном и том же файле первая ветка изменила строки в начале, а вторая — в конце, алгоритм объединит обе правки, посчитав их одинаково важными.

## 💥 Конфликты слияния и текстовые лайфхаки
[[JUMP:13:41]]

Единственная ситуация, в которой автоматика Git заходит в тупик — это изменение одной и той же строки файла в обеих ветках одновременно. В этот момент возникает так называемый конфликт слияния (merge conflict), требующий вмешательства человека.

Для авторов, пишущих научные работы на языке разметки LaTeX, Янник Килхер предлагает простое, но эффективное правило: при написании текста необходимо ставить каждое новое предложение с новой строки. Если писать текст сплошным абзацем, то при изменении всего одного слова Git зафиксирует изменение гигантской строки-абзаца, что затруднит поиск правок. Построчная же структура позволяет четко локализовать место изменений и минимизирует вероятность конфликтов.

## 🛠️ Практический практикум: от коммита до разрешения конфликта
[[JUMP:15:00]]



В качестве демонстрации ведущий показывает работу с репозиторием, где находится файл `test.txt` со словом «hello». Процесс фиксации изменений и разрешения конфликта состоит из нескольких последовательных шагов.

### Шаг 1. Проверка статуса и индексация
Для понимания текущего состояния репозитория используется команда `git status`. Если файл изменен, система подсветит его и подскажет дальнейшие действия. Чтобы подготовить файл к сохранению, его необходимо перевести в индекс (staged) с помощью команды:
```bash
git add test.txt
```
После этого статус файла в терминале изменится на зеленый.

### Шаг 2. Создание коммита
Команда `git commit` открывает системный текстовый редактор для ввода лог-сообщения. Комментарии, помеченные символом решетки `#`, игнорируются системой. Янник Килхер делится полезным секретом: если вы поняли, что совершили ошибку, достаточно закрыть редактор, оставив поле сообщения абсолютно пустым — в этом случае Git автоматически отменит процедуру коммита. После успешного сохранения сообщения команда `git log` выведет историю изменений на экран.

### Шаг 3. Ветвление и параллельное редактирование
Для создания новой ветки `f1` с одновременным переходом на нее применяется команда:
```bash
git checkout -b f1
```
В этот момент специальный внутренний указатель `head` (текущий фокус пользователя) перемещается на созданную ветку. 
В ветке `f1` текст файла меняется на «hello ... cool», после чего коммитится с помощью сокращенной команды, объединяющей индексацию и добавление сообщения:
```bash
git commit -a -m "more o"
```
Затем пользователь возвращается в ветку `master` с помощью `git checkout master` (при этом текст файла возвращается к исходному состоянию), меняет ту же строку на «hello ... more e» и делает еще один коммит.

### Шаг 4. Столкновение и ручное разрешение конфликта
Находясь на ветке `master`, пользователь инициирует слияние командной `git merge f1`. Система сообщает об ошибке автоматического слияния. При открытии файла `test.txt` внутри обнаруживаются маркеры конфликта:

* Указатель `<<<<<<< HEAD` отмечает начало изменений из текущей ветки (`master`).
* Разделитель `=======` разграничивает версии.
* Указатель `>>>>>>> f1` отмечает конец изменений, пришедших из ветки `f1`.

Для разрешения конфликта автору необходимо вручную отредактировать файл в текстовом редакторе: удалить все служебные маркеры (`<<<<<<<`, `=======`, `>>>>>>>`) и привести текст к финальному, желаемому виду. 

После редактирования файла выполняются финальные команды:
```bash
git add test.txt
git commit
```
Git автоматически сформирует стандартное сообщение о проведенном слиянии с указанием бывших конфликтов. Теперь история репозитория снова объединена в общий поток, а ставшую ненужной ветку `f1` можно безопасно удалить из списка указателей командой `git branch -d f1`. Сам коммит при этом не исчезнет из общей истории графа.