Git за 500 слов

Прим. автора: Эта статья идет в качестве дополнения к Gitlet, моей реализации Git на JavaScript.

Предположим, у нас есть директория alpha, в которой содержится файл number.txt с текстом «first».

Мы можем выполнить команду git init для того, чтобы сделать alpha репозиторием Git.

Затем git add number.txt, чтобы добавить number.txt в индекс (index). Индекс — это список файлов, которые находятся под контролем Git. Он сопоставляет имена файлов с их содержимым. В данном случае мы получили number.txt -> first. Запуск команды добавления также добавит объект (blob), содержащий first, в базу данных репозитория.

Теперь мы можем выполнить git commit -m first. Эта команда делает три вещи. Во-первых, она создает объект-дерево в базе данных. Этот объект представляет список содержимого директории alpha и содержит указатель на объект first, который был создан командой git add. Во-вторых, она создает объект коммита, который представляет текущую версию директории. Он содержит указатель на дерево. И в-третьих, она ставит указатель ветки master на новый коммит.

Выполним команду git clone . ../beta. Она создаст новую директорию beta уровнем выше и инициализирует новый репозиторий в ней. Затем скопирует все объекты из базы данных репозитория alpha в свежесозданный. Ветка master в репозитории beta указывает на тот же коммит, что и ветка master в репозитории alpha. Индекс beta отражает содержимое первого коммита, а файлы — в данном случае number.txt — индекс.

Перейдем к репозиторию beta и поменяем содержимое файла number.txt на «second». Выполним git add number.txt и git commit -m second. Коммит, который мы только что создали, содержит указатель на своего родителя — коммит first. Ветка master теперь указывает на второй коммит.

Перейдем обратно к репозиторию alpha. Выполним git remote add beta ../beta. Таким образом мы добавим репозиторий beta в список удаленных (remote).

Выполним git pull beta master.

Эта команда работает в два этапа. Cначала она выполняет git fetch beta master, находя таким образом объекты, соответствующие второму коммиту, и копирует их из репозитория beta в репозиторий alpha. Затем помечает коммит, на который указывает master в репозитории beta (в нашем случае второй), и устанавливает указатель FETCH_HEAD на него, чтобы показать, что эта ветка была подтянута из другого репозитория. Затем выполняется команда git merge FETCH_HEAD. Она видит, что последние подтянутые изменения — это ветка master репозитория beta (указатель FETCH_HEAD), и она указывает на второй коммит. Ветка master в alpha указывает на первый коммит, который является родителем второго. Это значит, что для того, чтобы завершить слияние, достаточно просто установить указатель master на второй коммит. Команда merge обновляет индекс, чтобы он соответствовал содержимому второго коммита, и обновляет содержимое директории, чтобы оно соответствовало индексу.

Выполним git branch red. Эта команда создаст ветку (branch) с именем red, которая указывает на второй коммит.

Теперь git checkout red. Перед чекаутом (checkout) HEAD указывал на ветку master, теперь он указывает на ветку red. Таким образом, ветка red становится текущей.

Поменяем содержимое number.txt на «third» и выполним git add numbers.txt, а затем git commit -m third.

Теперь выполним команду git push beta red. Она берет третий коммит и копирует его содержимое из репозитория alpha в репозиторий beta, а затем устанавливает на него указатель ветки red в beta. Вот и все!

Если вы хотите больше узнать о внутреннем устройстве Git, вы можете прочитать мою статью «Git from the inside out».

По материалам статьи «Git in six hundred words»