Почему git коммитов в объединенной ветви отображается на моей основной ветви? - PullRequest
1 голос
/ 16 октября 2019

В настоящее время у меня есть дерево коммитов git, которое выглядит примерно так с указателями (?) В скобках:

*   305f Merge branch 'develop' (HEAD->master, origin/master, origin/HEAD)
|\
| * d97b Some other commit on dev branch (develop) 
| * df14 Some commit on dev branch
|/
* 7a761b6 Initial commit

Я перенес ветку master на удаленный (Gitlab, если это важно), и когдаЯ смотрю на коммиты в ветке master в пользовательском интерфейсе Gitlab, присутствуют все 4 коммита, где я ожидал, что только коммиты «Merge ветвь 'развиваются» »и« Initial commit »присутствуют в ветке master.

Насколько я понимаю, master относится к двум коммитам, которые я только что перечислил, тогда как develop относится к "Некоторым другим ...", "Некоторым коммитам ..." и, возможно, также "Первоначальному коммиту". , так как это предок.

Где я иду не так?

1 Ответ

3 голосов
/ 16 октября 2019

В некоторых системах контроля версий, когда вы делаете коммит C на ветке B , коммит C находится на ветке B навсегда. Любой, кто получает коммит C , получает ветку B . Если раньше у них была их собственная ветка B , то теперь у их ветви B есть новый коммит C в нем

Git не делает это. Комитеты не привязаны к филиалам. Однако коммиты являются в основном постоянными, 1 и постоянно привязаны к тому месту, где они появляются в графе коммитов . Для того, чтобы эта работа работала, коммиты не делаются на любых ветках. Вместо этого имя ветви - это просто метка. Несколько меток могут указывать на один и тот же коммит , например:

*   305f Merge branch 'develop' (HEAD->master, origin/master, origin/HEAD)

Здесь master и origin/master 2 обаопределить совершить 305f. Если вы создадите новую ветку br2 сейчас, это имя также укажет на фиксацию 305f.

Коммит 305f имеет двух родителей: 7a761b6 (его первый родитель) и d97b (его второй родитель). Полное имя 305f соответствует его полному хэш-идентификатору. Это никогда не изменится;и этот хэш-идентификатор навсегда зарезервирован для , что commit, который всегда будет иметь тех же двух родителей. Этот коммит замораживается на все времена и никогда не будет перемещаться.

В Git все, что делает движение - это имена ветвей . В настоящее время master означает 305f. Однако минуту назад master означало 7a761b6. Комитеты остаются на месте, навсегда, как их необработанные хэш-идентификаторы. Имена ветвей перемещаются.

Результатом всего этого является то, что множество ветвей, которые содержат некоторые изменения, динамически изменяются по мере того, как мы создаем и уничтожаем имена ветвей. В настоящее время имя master позволяет найти все четыре коммита. Если вы позволите Git перемещать имя master так, как предпочитает Git, эти четыре коммита будут по-прежнему доступны, начиная с 305f и просматривая обоих его родителей, затем просматривая родителя d97b (изатем с d97b вы вернетесь к 7a761b6, который вы уже видели). Обратите внимание, что new фиксирует только когда-либо добавление к графику . В общем, каждый новый коммит будет иметь некоторый существующий коммит в качестве своего родителя - своего единственного родителя, если это типичный коммит, или одного из двух родителей, если это коммит слияния. 3

Если мынарисовать эти вещи в сторону, это немного проще. Чтобы сделать это еще проще, мы можем использовать одну заглавную букву для обозначения непонятных хеш-идентификаторов, которые использует Git:

        D--E   <-- br1
       /
A--B--C
       \
        F--G   <-- br2

Здесь имя br1 позволяет нам найти commit E, который находит D, затем C, затем B, затем A (и останавливается, потому что A является первым коммитом). Имя br2 позволяет нам найти G, затем F, затем C, затем B, затем A (и затем остановить). Таким образом, первые три коммита находятся на обеих ветвях, в то время как два коммита - это только одна одна ветвь.

Стирание имени br1 вызывает коммиты D иE чтобы стать неотразимым. В конце концов Git выбросит их по-настоящему. Если вместо этого мы добавим новый коммит, выполнив git checkout br1, сделав все необходимые изменения git add и git commit, мы получим новый хэш-идентификатор H и добавим имя br1, чтобы включить его:

        D--E--H   <-- br1
       /
A--B--C
       \
        F--G   <-- br2

Теперь есть шесть коммитов, доступных с br1, начиная с H и работая в обратном направлении. Если мы создадим новое имя br3, чтобы запомнить, где находится E, мы захотим немного перерисовать график:

             H   <-- br2
            /
        D--E   <-- br3
       /
A--B--C
       \
        F--G   <-- br2

Обратите внимание, что ни один из коммитов не имеетна самом деле изменилось: мы просто добавили H, чтобы освободить место для метки br3.

Если мы удалим name br3 позже, это нормально: нет коммитов, которые исключительно найдено через br3. Коммит E не исчезнет, ​​потому что br1 находит H, который находит E.


1 в основном достигается через достижимость . Вы находите коммиты, начиная с какой-либо ветви или имени тега, который предоставляет необработанный хэш-идентификатор. Затем, найдя коммит, вы используете его родительские хеш-идентификаторы, чтобы найти предшествующий коммит. Затем вы используете эти коммиты для поиска их родителей и т. Д.

Выполняя этот процесс из каждой ссылки - см. Сноску 2 -Git находит все достижимые коммиты. Любые коммиты, которые существуют в репозитории и которые недоступны для этого процесса, в конечном итоге собираются и удаляются.

2 Имя master является именем ветви. Его полное имя действительно refs/heads/master, а имена, полное имя которых начинается с refs/heads/, являются именами ветвей. В отличие от этого, origin/master на самом деле является именем для удаленного слежения : его полное имя начинается с refs/remotes/, а затем продолжается origin/master. Git иногда удаляет только часть refs/ из этого имени, так что вы видите remotes/origin/master.

Теги, если они есть, живут в refs/tags/. Все это вместе называется refs или ссылки . В reflogs хранятся дополнительные скрытые ссылки. Reflog - это просто файл журнала, в котором хранятся значения - предыдущие хэш-идентификаторы, - которые были сохранены в ссылке до того, как вы или Git обновили его. Срок действия этих записей журналов в конце срока истекает, и именно поэтому преднамеренно оставленные коммиты - например, те, которые вы заменили новыми и улучшенными версиями с новыми идентификаторами хеша - в конечном итоге удаляются.

3 Техническое определение коммит слияния состоит в том, что он имеет по крайней мере двух родителей. Поэтому вы также можете создать коммит слиянием с 3 или более родителями, но редко есть причина для этого. Следует также отметить, что можно создать новый коммит с no parent. За исключением самого первого коммита - того, который я обозначил A на боковых графиках - вы не будете делать это и в обычной практике.

...