Почему у меня возникают конфликты слияния git?

Я столкнулся с ситуацией, связанной с git и Bitbucket, которую я не понимаю.

Я создал ветку branchB, которая возникла из master. Я сделал несколько коммитов и создал запрос на включение в master. Пока этот пулреквест рассматривался, я начал работать над другой функцией, которая была расширением функции из branchB. Поэтому я создал еще одну ветку (branchC), которая возникла из branchB. Когда моя расширенная функция была готова, я создал запрос на включение в branchB. См. Изображение I. В то время у меня не было конфликтов слияния.

Почему у меня возникают конфликты слияния git?

Я хотел, чтобы рецензенты могли просматривать оба пулл-реквеста по отдельности и иметь отдельные пулл-реквесты с небольшими изменениями.

Мой план был следующим:

  • объедините запрос на извлечение 1 (PR1) с мастером, используя опцию --squash
  • измените целевую ветку в запросе на включение 2 (PR2) на master (см. Изображение 2)
  • объединить запрос на извлечение 2 (PR2) с мастером

Однако, когда я объединяю пул реквест 1 (PR1) с мастером, используя опцию --squash, Bitbucket автоматически изменил целевую ветвь запроса на вытягивание 2 (PR2) на master, и у меня возникли некоторые конфликты в запросе на вытягивание 2 (PR2).

Итак, я разрешил конфликты:

  1. git checkout master

  2. git pull

  3. git checkout branchC

  4. git rebase master

  5. git mergetool

  6. Я решил все конфликты здесь.

  7. git rebase --continue

На самом деле, описанная проблема случилась со мной дважды, так как у меня тоже было branchD, происходящее от branchC. Когда я объединил branchB в master, мне пришлось разрешить некоторые конфликты на шаге 6. Однако, когда я объединил branchC в master, мне не пришлось разрешать какие-либо конфликты вручную на шаге 6 (хотя Bitbucket показал мне конфликты слияния, поэтому мне пришлось перебазировать branchC).

Му вопросы следующие:

  1. Почему Bitbucket показал мне какие-либо конфликты слияния для PR2, когда я объединил PR1 с мастером, используя опцию --squash? Я ожидаю, что он поймет, что разница между картинками I и II есть только в идентификаторах коммитов — код не изменился. Git/Butbucket должен определить, какие изменения я хочу внести.
  2. Почему у меня не было конфликтов, которые нужно было бы разрешать вручную, когда я перебазировал branchD в master (после слияния branch C в master)? Поскольку Bitbucket не смог объединить мой запрос на извлечение, я ожидаю, что мне придется разрешать некоторые конфликты вручную. Может ли это быть связано с версией git на моем рабочем столе и на Bitbucket?
  3. Был ли у меня лучший вариант, чем создание этих трех запросов на включение в моем случае? Можно ли было избежать этих конфликтов слияния?

Дополнительная информация:

  • git на моем рабочем столе: 2.17.1.windows.2
  • Версия Bitbucket: v5.12.2
  • git на сервере Bitbucket: 2.14.5
  • Я искал похожие вопросы (1, 2, 3). Никто из них не занимается моей проблемой.

Я был бы признателен за любое объяснение этого явления.

Редактировать: 1. Я объединил все свои пулреквесты с помощью опции --squash. 2. Я обновил картинку, чтобы показать, что branchB и branchC не начинаются с коммитов B1 и C1 соответственно.

Одно уточнение: ветка указывает на конкретный коммит и содержит все коммиты до него. Я отмечаю это, потому что там, где вы помечаете branchB и branchC, создается впечатление, что эти ветви начинаются именно там. Это неверно, потому что обе ветки начинаются с коммита A1. Я полагаю, вы имеете в виду, что branchB заканчивается на фиксации B2, а branchC заканчивается на фиксации C2.

Code-Apprentice 10.04.2019 21:53

@Code-Apprentice, ты прав. Я не хотел предложить, чтобы branchB и branchC начинались с коммитов B1 и C1. У меня были линии, соединяющие коммиты A2- B1 и B2- C1 на моей картинке, чтобы показать, что все ветки содержат коммиты из master. Обновил картинку-надеюсь теперь понятно.

user2738748 11.04.2019 17:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
839
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если я правильно Вас понимаю. Проблема была в этом --squash. Вот тема, в которой объясняется, как выполняются слияния в GIT Как git узнает, какую версию строки оставить?.

Когда вы объединились с --squash, поскольку коммиты git на самом деле неизменяемы, вы создали новый сжатый коммит с новым идентификатором. Когда Вы захотели слить PR2 обратно в мастер, содержимое файла было изменено в обоих местах. Для branchB было несколько коммитов с некоторыми идентификаторами, а для master был только один коммит с другим идентификатором, и некоторые файлы были изменены в обеих ветках, поэтому в основном git не знает, какая версия правильная. Вот почему не было конфликтов в случае branchC, потому что история коммитов была одинаковой для branchB и branchC (здесь --squash не делалось).

Для OP и будущих посетителей: обратите внимание, что не имеет значения, что сжатый коммит имеет те же текстовые изменения, что и исходная последовательность коммитов. Git видит две разные последовательности изменений и называет это конфликтом слияния.

Code-Apprentice 10.04.2019 21:37

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

Dominik Wosiński 10.04.2019 21:48

так что в этом случае вы имеете в виду, что слияние branchC с master (после слияния PR1) учитывало кумулятивные изменения коммитов с B1 по C2? Эти изменения отличаются от просто A3 в отдельности.

Code-Apprentice 10.04.2019 21:56

Я имею в виду, что если бы вы сбрасывали branchC на коммит B2, чтобы изменения, сделанные в master и branchC, были точно такими же. Если бы вы объединили branchC с мастером, git смог бы сделать это без конфликтов, даже несмотря на то, что история коммитов технически отличается. По крайней мере, мне удалось это сделать без конфликтов в ситуации, описанной выше.

Dominik Wosiński 10.04.2019 22:11

Так что насчет того, когда branchC находится в состоянии фиксации C2 и master находится в стадии фиксации A3, и вы пытаетесь объединить master в branchC. Почему git не определяет, что A3 идентично изменениям в коммитах B1 и B2?

Code-Apprentice 10.04.2019 22:14

Сообщение, которое я вставил, объясняет это, я думаю. GIT на самом деле не смотрит на коммиты из истории. Он будет смотреть хэши последних изменений, и они не совпадут в точке. Поэтому он попытается сравнить файлы построчно и обнаружит, что различия действительно есть, и пометит их как конфликты.

Dominik Wosiński 10.04.2019 22:53

@DominikWosiński, это ответ на мой первый вопрос. Что насчет второго? Почему мне приходилось разрешать некоторые конфликты вручную для PR2, а не для PR3? Все 3 запроса на включение были объединены с помощью опции --squash.

user2738748 11.04.2019 17:38

Что такое PR3 в данном случае? :)

Dominik Wosiński 11.04.2019 18:00

Это пул реквест с branchD на master, который я объединил после того, как слил пул реквест с branchC на master. На самом деле у меня было три ветки: branchB, branchC и branchD. Я не ставил branchD на картинке, чтобы было проще. Я упомянул об этом в своем вопросе.

user2738748 11.04.2019 19:12

Такая ситуация может возникнуть, если изменения в branchD не конфликтуют с предком. Это означает, что файлы, измененные в branchD, не совпадают с файлами, измененными в branchC. В таком случае трехстороннее слияние может правильно их объединить.

Dominik Wosiński 11.04.2019 19:43

Другие вопросы по теме