Почему ветвь B конфликтует во всех коммитах слияния от A до B после первого коммита слияния?
У меня есть основная ветка разработки (A), которая имеет долгую историю. Все коммиты релиза в A помечены как таковые. Я проверил корневой коммит A, и разветвился в тест (B).
Итак, у меня есть первичная ветвь A, а глава ветки B указывает на корневой коммит A. Моя цель - создать историю всех выпусков путем слияния каждого тегового коммита от A до B.
Первое слияние из А в Б работает как положено, никаких конфликтов.
$git checkout B
$git merge [release-commit-ID] --squash
$git commit -m "release#"
Первый коммит работает отлично, но все остальные коммиты рассматривают все коммиты слияния как полные конфликты. Я вижу, что корень B такой же, как корень A, но общая история не распознается после первого сдавленного коммита слияния из первого релиза коммит в A в B. Что вызывает конфликты и как мне получить общую историю быть признанным?
1 ответ
Что вызывает конфликты и как я могу получить общую историю, которая будет распознана?
Там нет общей истории (или, скорее, не достаточно). Там нет ничего, чтобы признать, поэтому есть конфликты.
Ключ является --squash
флаг:
$ git checkout B $ git merge [release-commit-ID] --squash
Первый шаг прикрепляет ваш HEAD
на название филиала B
, проверяя, какое имя зафиксировать B
определяет:
...--*--C--D--E <-- B (HEAD)
\
F--G--H <-- somebranch
Здесь имя B
определяет совершить E
(каждая из этих букв обозначает настоящие хэш-идентификаторы). совершить *
(который я бы назвал B
(но вы использовали это название для своей ветви) - это точка, в которой два потока разработки расходятся, что означает, что когда мы работаем в обратном направлении (как это делает Git), это точка, где они объединяются. Вы сейчас бежите git merge --squash <hash>
где <hash>
определяет совершить F
, или же G
, или же H
так что Git сравнивает содержимое коммита *
к содержанию коммита E
чтобы узнать, что вы изменили:
git diff --find-renames <hash-of-*> <hash-of-E> # what we changed
и повторяет, скажем, G
:
git diff --find-renames <hash-of-*> <hash-of-G> # what they changed
Git теперь объединяет эти два набора изменений, применяет объединенные изменения для фиксации *
и делает новый коммит.
Если вы не используете --squash
Гит записывает новый коммит с двумя родителями:
...--*--C--D--E--I <-- B (HEAD)
\ /
F-------G--H <-- somebranch
и теперь самая последняя общая отправная точка между двумя строками - это фиксация G
, Но если вы используете --squash
Git записывает новый коммит только с одним родителем:
...--*--C--D--E--I <-- B (HEAD)
\
F--G--H <-- somebranch
и теперь общая отправная точка не изменилась. Вся работа через G
находится в совершении I
, но совершают I
не помню, почему эта работа там. Будущее git merge
от коммита H
должен начать заново при коммите *
,
Git не помешает вам развиваться на ветке somebranch
, но в целом после git merge --squash
, вы должны считать ветку, из которой вы слились, "мертвой" и просто прекратить ее использование. После того, как мы объединились G
с git merge --squash
мы должны перестать использовать F
а также G
полностью. Это означает, что мы также должны прекратить использование H
полностью. Если H
полезно, мы должны скопировать его в новый, другой коммит:
$ git checkout -b newbranch B
давая нам:
...--*--C--D--E--I <-- B, newbranch (HEAD)
\ /
F-------G--H <-- somebranch
с последующим:
$ git cherry-pick somebranch # or <hash of H>
копировать H
очень похожий, но не идентичный, совершить H'
:
H' <-- newbranch (HEAD)
/
...--*--C--D--E--I <-- B
\ /
F-------G--H <-- somebranch
Теперь мы можем отказаться somebranch
:
$ git branch -D somebranch
и переименовать newbranch
в somebranch
если нам нравится
(Обратите внимание, что мы можем сделать это с помощью копирования с именем за один шаг, используя git rebase --onto
, с git checkout somebranch; git rebase --onto B <hash of G>
, Независимо от того, как вы это делаете, однако, имейте в виду, что git cherry-pick
не может скопировать коммиты слияния, и любой, кто использует коммиты, которые мы хотим убить - здесь F-G-H
цепочка - должна сделать эту вещь "убить с копированием тех, кто хочет сохранить". Так что перед использованием --squash
Убедитесь, что вы понимаете все последствия.)