меня беспокоит то, что эффекты / проблемы --allow-unrelated-histories
вызовут ...
Сам флаг ничего не вызывает.Он выполняет действие, которое не соответствует ожиданиям новых пользователей Git.
Чтобы понять его - или Git в целом, на самом деле - вам нужно иметь некоторые базовые знания о графиках, как это определено обычными математическимиопределение, в котором граф G представляет собой набор вершин V , соединенных ребрами E или записанных в обычных обозначениях, G = (V,E) .Когда у ребер есть направление - своего рода односторонняя стрелка, так что каждая вершина (или узел) «переходит» к другой вершине, но вы не можете вернуться назад, ребра называются arcs .
В Git граф фиксации направлен следующим образом: каждый коммит действует как узел графа, и в нем перечислены родительские коммиты .Это исходящие дуги, поэтому они связывают коммиты в некотором роде назад. имена веток Git затем работают для поиска последнего коммита, так что в крошечном репозитории с тремя коммитами у вас будет:
A <-B <-C <--master
Commit A
это первый сделанный вами коммит, поэтому у него нет родителя.Commit B
перечисляет commit A
в качестве родителя, а C
перечисляет B
в качестве родителя;и Git находит commit C
- чье настоящее имя, то есть его хеш-идентификатор, выглядит совершенно случайным - используя имя master
для хранения хеш-идентификатора C
.
Зная, что эти ссылки -дуги - все идут в обратном направлении, от дочернего к родительскому, мы можем рисовать их более удобно в виде ссылок и добавлять больше коммитов:
A--B--C--D <-- master
\
E--F--G <-- branch
Если мы теперь перейдем к объединить ответвление обратно вmaster
, Git использует эти соединительные стрелки, чтобы выяснить, где в истории ваша работа по master
разделялась на чью-либо работу в branch
.Это снова в коммите B
, где узлы графа воссоединяются.Теперь Git может сравнить снимок, сохраненный в этой базе слияния B
, с кончиком master
:
git diff --find-renames <hash-of-B> <hash-of-D>
, чтобы выяснить, что вы изменили.Затем Git может сравнить снимок в B
со снимком в кончике branch
:
git diff --find-renames <hash-of-B> <hash-of-G>
Акт слияния - глагол to merge - делает эти два сравнения иобъединяет их, применяя объединенные изменения к тому, что было в базовом коммите.Если все идет хорошо, Git фиксирует окончательный результат самостоятельно.(Если нет, Git останавливается и заставляет вас убрать беспорядок и выполнять коммит самостоятельно; что входит в этот коммит, зависит от того, как вы исправите конфликты, обнаруженные Git.) В результате получается Фиксация слияния , не с одним, а с двумя родителями:
A--B--C--D---H <-- master (HEAD)
\ /
E--F--G <-- branch
Опять же, снимок исходного кода для нового коммита слияния H
- эторезультат объединения изменений , сделанных после базы слияния, - общая отправная точка двух кончиков ветвей.
Однако в вашем случае вы сделали два несвязанных репозитория .Результатом является то, что математики называют несвязным графом .Это может выглядеть примерно так, например:
A--B--C--D---H <-- br1
\ /
E--F--G
L--M
/ \
I--J--K------N <-- br2
Если вы теперь git checkout
одна из этих двух ветвей, так что HEAD
присоединяется, скажем, к br1
, и запускаете git merge br2
, Git идет, чтобы найти общую отправную точку, работая в обратном направлении (влево) из двух кончиков веток.Но нет общей отправной точки: истории не связаны.
Старые версии Git просто продолжали бы и сливались.Новые жалуются, если вы не поставите флаг;если вы поставите флаг, они продолжат и объединятся точно таким же образом.
Проблема здесь в том, что у нет общей начальной точки , поэтому Git предполагает, чтообщей отправной точкой является действительно пустой коммит: коммит без файлов вообще.
Это означает, чтоКаждый файл в каждой из двух ветвей создается заново.Два файла с одинаковым именем пути вызовут "конфликт добавления / добавления": Git говорит, что you написал README.txt
с нуля, и они write README.txt
с нуля, и сам Git не знает, как их объединить, поэтому вы должны сделать это самостоятельно.Это повторяется для каждого файла с тем же именем.
С другой стороны, если вы создали README.md
, а они создали README.rst
, два имени отличаются, поэтому Git предполагает, что правильный способ объединенияREADME.md
ни с чем - это взять README.md
, а правильный способ объединить README.rst
с ничем - это взять README.rst
.Таким образом, вы получите оба файла, и Git считает, что теперь они правильно объединены.(Это правда? Я понятия не имею. Так же как и Git, но Git предполагает , что это правда.)
Это повторяется для всех файлов: либо каждое имя файла уникально для этого конкретного diff,поэтому Git добавляет его или нет, поэтому Git объявляет конфликт и оставляет его на ваше усмотрение, чтобы решить проблему.В конце, если не было конфликтов имен файлов, Git делает новый коммит самостоятельно;если были конфликты, Git заставляет вас их убирать и делать коммит самостоятельно.Мы можем нарисовать новый коммит:
A--B--C--D---H-----O <-- br1 (HEAD)
\ / /
E--F--G /
/
L--M /
/ \ /
I--J--K------N <-- br2
Было ли это разумно сделать?Я не могу ответить на это;только ты можешь ответить на это.