Важно понимать, что в Git ветви не являются историей. коммитов это история.(И истории файлов нет, есть только коммиты.) Обратите внимание, что у каждого коммита есть одно «истинное имя», которое является его хэш-идентификатором, большая уродливая строка из 40 шестнадцатеричных символов, например f84b9b09d40408cf91bbc500d9f190a7866c3e0f
.
КаждыйВ коммите хранится полный снимок вашего исходного дерева, а также некоторые метаданные.Здесь метаданные - более интересная часть.Метаданные в коммите включают в себя:
- ваше имя, адрес электронной почты и метку времени;
- ваше сообщение журнала;и
- идентификатор хеша своего предшественника или родительский commit.
Этот последний элемент является наиболее важным из всех, в данном конкретном контексте.Если мы используем одну заглавную букву в качестве замены для больших уродливых хеш-идентификаторов, мы можем нарисовать коммиты следующим образом:
... <-F <-G <-H
, где H
- это последний коммит.Commit H
запоминает хэш-идентификатор G
, поэтому мы говорим, что H
указывает на G
.Между тем G
помнит своего родителя F
, поэтому G
указывает на F
, что указывает на E
, и так далее по обратной цепочке.
Это равно история в хранилище.Создание нового коммита состоит в том, чтобы Git заморозил ваше исходное дерево, добавил сообщение журнала и тому подобное, и создал новый хэш-идентификатор I
.Новый коммит I
будет хранить хэш-идентификатор H
:
... <-H <-I
, и теперь история на один коммит длиннее.
Но: как мы узнаем, какой коммит является последний один в цепочке?В этом упрощенном примере, с заглавными буквами, это очевидно, но с реальными хэш-идентификаторами, которые кажутся случайными, это не так.На самом деле, нет ничего, кроме грубой силы: «перечислите каждый коммит, посмотрите, какой из них последний», чтобы узнать.Итак, Git дает нам имена ветвей , которые помогают наказывать людей (и сам Git, поскольку он не настолько умен) find last commit:
...--F--G--H <-- master
, который становится:
...--G--H--I <-- master
после того, как мы сделаем новый коммит.
Поместите как можно проще, имя ветви просто указывает на (содержитID хеша) последний коммит, который мы - и Git - должны считать частью этой ветви.
Это означает, что когда вы создаете новую ветку, вы выбираете какой-то существующий коммит и сообщаетеGit, чтобы добавить к нему другое имя:
...--F--G--H <-- master, branch1
Теперь Git нужен способ узнать , какое имя ветви использовать , поэтому мы должны Git присоединить специальное имя HEAD
к одному издва:
...--F--G--H <-- master, branch1 (HEAD)
Когда мы делаем наш новый коммит, Git обновляет имя , к которому прикреплен HEAD
, например:
...--F--G--H <-- master
\
I <-- branch1 (HEAD)
Примечаниеэтот коммит H
, который является вершиной мастера, также на ветке branch1
.
Если вы создаете другое имя, просто нарисуйте его, яГде бы он ни указывал.Если он указывает на H
, нарисуйте его, указывая на H
.Если он указывает на I
, например branch1
, нарисуйте его, указывая на I
.Затем добавьте еще несколько коммитов, обновляя любое имя HEAD
, к которому прикреплено:
J--K <-- branch2 (HEAD)
/
...--F--G--H <-- master
\
I <-- branch1
или:
...--F--G--H <-- master
\
I <-- branch1
\
J--K <-- branch2 (HEAD)
или что-либо еще.
Допустим, что вэта точка у нас есть:
...--F--G--H <-- master
\
I--L--M--N <-- branch1 (HEAD)
\
J--K <-- branch2
Удаление ветка (имя) просто означает стереть имя . коммиты остаются в покое - один коммит сделан, ничто не может его изменить.Если вы больше не можете найти коммит на графике, коммит теперь уязвим для удаления.Но если вы можете начать с какого-то существующего имени и вернуться к коммиту, сам коммит является безопасным для кавычек.Поэтому, если мы git checkout master
(чтобы мы могли удалить branch1
), мы получим:
...--F--G--H <-- master (HEAD)
\
I--L--M--N [abandoned]
\
J--K <-- branch2
Commit I
все еще достижимо , начиная с K
с branch2
и работает в обратном направлении: commit I
был на обоих branch1
и branch2
.Теперь, когда branch1
ушел, I
только на branch2
, но он все еще доступен с помощью трюка Git "идти назад от всех названий ветвей",
Commits L-M-N
, однако, стали незащищенными.Через некоторое время, обычно через льготный период, по крайней мере, 30 дней, через механизм, который Git вызывает reflogs - «сборщик мусора» Git в конечном итоге запустит и очистит недоступные объекты (коммиты)и другие объекты).Эти коммиты со временем полностью исчезнут, оставив вам:
...--F--G--H <-- master (HEAD)
\
I
\
J--K <-- branch2
, что делает его похожим на branch1
, которого никогда не было.