Почему некоторые коммиты не принадлежат ни одной ветке? - PullRequest
0 голосов
/ 25 апреля 2018

Я обнаружил, что некоторые коммиты не принадлежат ни одной ветке в репозиториях Git.Например, следующий коммит помечен как выпуск для Apache Commons CSV, но он не принадлежит ни одной ветви:

https://github.com/apache/commons-csv/commit/0fbd1af5e3bd70454d5e398493a5c983aead2b67

Его родительский коммит принадлежит master.

https://github.com/apache/commons-csv/commit/7688fbc3f9f5acf73d3c5018dd83310f7580d02e

Можете ли вы помочь мне понять это?

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Эта ситуация достаточно нормальна в Git, который использует ветки совсем не так, как большинство традиционных систем контроля версий (VCS). На самом деле здесь скрыт довольно глубокий философский вопрос: см. Что именно мы подразумеваем под "ветвью"?

Имена ветвей идентифицируют коммиты чаевых

В большинстве VCS, имя ветви важно, возможно, даже самая важная вещь о ветви. Это не так в Git: ветви names в Git имеют очень небольшое значение (в любом случае для самого Git). Для Git важны коммиты . Коммиты являются постоянными - ну, в основном, постоянными - и неизменными: после внесения ни один коммит не может быть изменен. Но истинное имя каждого коммита - ужасное, неуместное, непроизносимое, невозможно запомнить строку цифр и букв, например fe0a9eaf31dd0c349ae4308498c33a5c3794b293. Это не очень хорошо для людей, поэтому Git позволяет нам использовать имена для замены этих необработанных хеш-идентификаторов.

Другая важная вещь в каждом коммите, однако, заключается в том, что любой коммит хранит истинное имя - хэш-идентификатор - другого коммита, который мы называем parent или предшественник коммита, Мы говорим, что этот дочерний коммит указывает на его родителя. 1 Если мы возьмем строку непроизносимых хеш-идентификаторов и поместим их в "самый дедушка-у-у" к «самому детскому» порядку мы получаем что-то вроде:

... <-26e4... <-8b02... <-fe0a...

Наиболее похожий на ребенка из этих коммитов получает имя ветви, а затем имя указывает на последний коммит:

... <-26e4... <-8b02... <-fe0a...   <--master

Git использует последний (или tip ) коммит, чтобы найти своего родителя, а затем использует родителя для поиска деда и т. Д. Во всем хранилище. Но поскольку хеш-идентификаторы выглядят случайными - и преднамеренно почти невозможно предсказать - даже сам Git хочет иметь имя , по которому он может найти последний коммит в цепочке. Этот хэш-идентификатор особенно важен, поскольку Git использует этот коммит для поиска оставшихся коммитов. Это дает нам такую ​​картинку:

          o--o   <-- branch1
         /
...--o--o
         \
          o--o--o   <-- branch2

(где я просто перестал рисовать внутреннее обратное направление стрелок и заменил хэш-идентификаторы круглыми точками для каждого коммита).

Коммиты в среднем ряду немного озадачивают: на какой они ветке? Git отвечает, что они находятся на обеих ветках. Вместо коммита, принадлежащего ветви, в которой коммит впервые сделан, коммит Git принадлежит каждой ветви - ну, каждая ветка name - которая ведет к ней.

Чтобы добавить новый коммит в какую-либо ветку, вы git checkout ветвь, работаете как обычно, git add соответственно и запускаете git commit. Это записывает новый коммит, который указывает на текущий коммит в качестве его родителя:

               o   (new!)
              /
          o--o   <-- branch1 (HEAD)
         /
...--o--o
         \
          o--o--o   <-- branch2

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

          o--o--o   <-- branch1 (HEAD)
         /
...--o--o
         \
          o--o--o   <-- branch2

и это один из нормальных путей роста ветвей.


1 Ребенок помнит родителя, а не наоборот. Поскольку коммиты неизменны, это необходимо. Так же, как с человеческими родителями и детьми, родитель существует, когда ребенок создается, но ребенок еще не существует, когда родитель создается. Поскольку коммиты могут помнить только прошлое, родители не могут вспомнить своих детей.


Теги также идентифицируют коммиты

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

          o--o--o   <-- branch1
         /
...--o--o
         \
          o--o--o   <-- branch2 (HEAD)
                ^
                |
             tag:v1.2

и затем добавьте еще один коммит:

          o--o--o   <-- branch1
         /
...--o--o
         \
          o--o--o--o   <-- branch2 (HEAD)
                ^
                |
             tag:v1.2

тег остается на месте.

Имена могут быть удалены в любое время

Если мы решим, что branch2 - плохая идея, мы можем git checkout branch1 и затем удалить name branch2. Без имени branch2 окончательный коммит, который мы только что добавили, больше не может быть найден:

          o--o--o   <-- branch1
         /
...--o--o
         \
          o--o--o--o   ???
                ^
                |
             tag:v1.2

Тег name v1.2, тем не менее, все еще существует, и делает помеченный коммит доступным для поиска. Этот помеченный коммит находится на нет ветвей (и на этом чертеже ни его родитель, ни прародитель, хотя его пра-пра-родитель все еще находится на branch1).

Имена защищают коммиты

Я упоминал выше, что коммиты в основном постоянны. Последний коммит, который больше не имеет имени, теперь незащищен . У Git есть устройство под названием сборщик мусора , которое действует как своего рода Grim Reaper для удаления остатков ненужных вещей. Этот Grim Collector, git gc, ищет всю фиксацию во всей базе данных Git, а также использует все names , чтобы найти все коммиты. Коммиты, которые можно найти по какому-либо имени - любому имени, включая имя тега - помечаются как сохраняемые. Коммиты (и другие объекты Git), которые не можно найти таким образом, которые недоступны из именованных коммитов, собираются и уничтожаются.

Этот процесс позволяет Git свободно генерировать объекты и решает использовать их по-настоящему в последнюю минуту. Это позволяет вам перемещать имена филиалов в любое время. Пока коммиты защищены именем, они остаются на месте. Если для них есть no , они становятся доступными для сборки мусора. Вот как вы (и Git) избавляетесь от нежелательных коммитов. Такие команды, как git stash, работают, создавая коммиты, которые не находятся ни в одной ветви, но защищены именем refs/stash (или его reflog , о котором я не буду здесь говорить). Отбрасывание тайника сбрасывает его имя; в конце концов git gc удаляет его по-настоящему.

Тег защищает зафиксированный коммит и любой более ранний (родительский) коммит, как это делает имя ветви. Если вы удалите тег, теперь безымянный коммит станет уязвимым для git gc. Но до тех пор он может счастливо держаться, даже если его совсем нет.

0 голосов
/ 25 апреля 2018

Поскольку этот коммит также является тегом, как вы можете видеть здесь:

enter image description here может быть нескольких вариантов:

  1. Это было на данной ветке и ветка была удалена
  2. Это было зафиксировано на ветке, а reset было сделано на ветке

1 является наиболее вероятным случаем .
Содержание было разработано в функциональной ветви, последнему коммиту был присвоен тег, а ветвь была удалена

Вот пример сценария, чтобы сделать это:

  • Я создал ветвь функций
  • Преданный контент для него
  • Пометить этот коммит
  • Удалил ветку, не объединяя ее с другой веткой
  • Список тегов и он в списке

enter image description here enter image description here enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...