Почему ветвь B конфликтует во всех коммитах слияния от A до B после первого коммита слияния? - PullRequest
0 голосов
/ 15 октября 2018

У меня есть основная ветка разработки (A), которая имеет долгую историю.Все коммиты релиза в A помечены как таковые.Я проверил корневой коммит A, и разветвился в тест (B).

Итак, у меня есть первичная ветвь A, а глава ветки B указывает на корневой коммит A. Моя цель - создать историю всех выпусков, объединив каждый помеченный коммит из A в B.

Первое слияние из A в B работает должным образом, никаких конфликтов.

$git checkout B
$git merge [release-commit-ID] --squash
$git commit -m "release#"

Первый коммит работает отлично, но все другие коммиты рассматривают все коммиты слияния как полные конфликты.Я вижу, что корень B совпадает с корнем A, но общая история не распознается после первого сдавленного коммита слияния из первого релиза в A в B. Что вызывает конфликты и как получить общую историюбыть признанным?

1 Ответ

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

Что вызывает конфликты и как я могу распознать общую историю?

Нет общей истории (или, скорее, недостаточно).Нечего распознать, вот почему возникают конфликты.

Ключом является флаг --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, Git записывает новый коммит с двумя родителями:

...--*--C--D--E--I   <-- B (HEAD)
      \         /
       F-------G--H   <-- somebranch

и теперь самая последняя общая отправная точка между двумя строками - это коммит G.Но если вы do используете --squash, Git записывает новый коммит только с одним parent:

...--*--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, убедитесь, что вы понимаете все последствия.)

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