Git - Повторное присоединение к основному филиалу - PullRequest
0 голосов
/ 15 октября 2018

Я создал ветку branch-1 из master, затем сделал на ней кучу коммитов, затем столкнулся с двумя вариантами, разветвленными оттуда, и сделал кучу коммитов на исходной ветке branch-1, некоторые нановая ветвь branch-2.

Коммиты на исходной ветке branch-1 оказались тупиковыми (те, что после второго ветвления), но те, что на ветке branch-2, должны остаться.

Есть ли способ избавиться от первой ветви branch-1 и сохранить только вторую с полной историей?

1 Ответ

0 голосов
/ 15 октября 2018

Важно понимать, что в 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, которого никогда не было.

...