Объедините два слияния в одно (или я могу изменить родителей коммита?) - PullRequest
1 голос
/ 30 апреля 2020

Можете ли вы рассмотреть следующий сценарий:

Предположим, у нас есть следующие топи c ветви: A, B, C, D, E, F и что мы хотим объединить их все вместе .

Также предположим, что из-за нескольких конфликтов НЕ возможно объединить их все вместе в одно объединение осьминога:

# git checkout A
# git --no-ff B C D E F
ERROR: no octopus strategy allowed

Однако, было возможно объединить их по очереди:

# git checkout A
# git merge --no-ff B C
OK with conflicts.
(resolve conflicts)
# git commit

# git checkout D
# git merge --no-ff E F
OK with conflicts.
(resolve conflicts)
# git commit

Теперь у нас есть два коммит-слияния на заголовках A и D соответственно. И мы можем объединить эти два.

# git checkout A
# git merge --no-ff D
OK: no conlicts

Теперь история выглядит примерно так:

* A
|\
|*- D
||\\
|||* E
||* F
|*
*-
|\\
||* B
|* C
*

Как вы теперь можете видеть, коммит в ГОЛОВКЕ А имеет двух родителей каждый из которых является коммитом слияния. Можно ли переписать последний коммит (со всеми содержащимися в нем изменениями), чтобы он имел в качестве родителей коммиты, указанные заголовками исходных шести ветвей?

Если нет команды git, которая может сделать это, возможно ли найти объект в базе данных git, изменить его, вычислить новый SHA-1 и сохранить его?

Заранее большое спасибо.

1 Ответ

2 голосов
/ 30 апреля 2020

Вы не можете изменить любую часть любого существующего коммита.

Вы можете , как RomainValeri отметил в комментарии , построить любой new коммит, который вам нравится, включая пользовательский коммит слияния, сделанный с git commit-tree. Затем вы можете изменить идентификаторы ha sh, хранящиеся в любой конкретной ветви name (s) , которые вы хотите сослаться на это новое коммитное слияние, которое по сути является слиянием осьминога с разрешением конфликтов:

          ________________
         /                \
...--o--o   <-- name1      \
         \   _______________\
          \ /                \
           X                  \
          / \                  \
 ...--o--o---M1   <-- name2     @   <-- branch
               >--M3 <--name5  /
 ...--o--o---M2   <-- name3   /
          \ /                /
           X________________/
          /                /
 ...--o--o   <-- name4    /
          \______________/

где @ - это ваше слияние осьминога, сделанное вручную, например. Измените имена вокруг по мере необходимости (вы можете удалять и заново создавать имена, или принудительно обновлять имена, или переименовывать имена ветвей, по желанию), чтобы одно конкретное имя, которое вам показалось особенно интересным, выбирало commit @, который вы сделали с помощью git commit-tree с использованием того же дерева , что и слияния M3, которое объединяет коммиты слияния M1 и M2.

(приведенные выше значения name в основном необязательны, но помогают вы найдете каждый коммит.)

Я бы не советовал делать это, потому что это не типичный рабочий процесс. Если вы делаете , сделайте это, поместите что-нибудь в сообщение коммита необычного слияния о том, как вы это сделали и почему. Некоторые будущие археологи кода - возможно, даже вы сами через год - могут просматривать исторические коммиты, пытаясь понять, например, как возникла какая-то ошибка, и могут столкнуться с этим необычным, сделанным вручную коммитом слияния. Без руководства или, по крайней мере, напоминания, кто бы ни сталкивался с этим слиянием осьминога, он мог бы посмотреть на него и подумать: ага, слияние осьминога, не должно быть никаких конфликтов и, следовательно, предположить, что у этого слияния не было конфликтов.

Если у вас есть два обычных слияния подряд, тот, кто с ними сталкивается не может предположить отсутствие конфликтов, потому что обычные слияния часто связаны с разрешением конфликтов.

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