Как избежать поломки детали при слиянии ветвей git?

#git

Вопрос:

Я импортировал открытый репозиторий Git (upstream/master) в свой собственный репозиторий (origin/master) и разрабатываю его на основе origin/master. Поскольку upstream/master активен, с тех пор как я клонировал репо, в ветвь было помещено много коммитов; upstream/master и ветвь/master будут выглядеть так, как показано ниже.

 --o--o--M--...--N---...--O-----o   <- upstream/master
           
    A------B------C----- ... --D   <- branch/master
 

И если бы я объединил восходящий поток в свою главную ветвь, это выглядело бы следующим образом:

 --o--o--M--...--N---...--O-----o   <- upstream/master
           
    A---M--B----N-C------O--...--D <- master(upstream merged)
 

Однако, поскольку коммиты чередуются при слиянии, если коммит N нарушил мою главную ветвь, коммиты C-D будут нарушены. Хотя я мог бы исправить ветвь с помощью новой фиксации, часть C-D все равно была бы сломана.

Как мне избежать поломки детали? Или есть какая-то лучшая практика для такого рода ситуаций?

Комментарии:

1. Как вы объединяете свои ветви? Обычно вы получаете фиксацию слияния. И если вы снова проверите фиксацию C, у вас не будет никаких изменений в восходящем потоке после M. Весь смысл фиксации заключается в том, что код, на который она указывает, не меняется в ретроспективе. Если у вас один и тот же хэш фиксации, он не может сделать ничего другого после слияния.

Ответ №1:

Слияние не переписывает никакой существующей истории, и на самом деле было бы очень сложно создать «чередующуюся» историю, как вы показываете в git.

Если вы начнете с этого:

 --X-----M-----N-----O-----P   <- upstream
           
    A------B------C------D   <- mybranch
 

Затем прямое слияние восходящего потока в mybranch создаст новую «фиксацию слияния», которая:

  • Применяет изменения, внесенные обеими ветвями со времени их последнего общего предка (помечено X)
  • Имеет два «родительских» коммита, P и D, именно так git записывает историю

Таким образом, результат выглядит следующим образом:

 --X-----M-----N-----O-------P   <- upstream
                            
    A------B------C------D----E   <- mybranch
 

С точки зрения git, все показанные коммиты являются «предками» коммита E, независимо от того, в какой ветви они находились, но прямой связи между, скажем, C и N.

Существует способ объединить код, который воссоздает старые изменения, называемый «перебазированием», который рассматривает каждое внесенное вами изменение и создает новую фиксацию, делая вид, что вы внесли это изменение поверх P вместо X. Однако он не «чередует» коммиты, он приводит все новые в порядок после того, как вы «перебазируетесь», давая что-то вроде этого:

 --X-----M-----N-----O-----P   <- upstream
                           
                            A1------B1------C1------D1   <- mybranch
 

(Заманчиво думать, что коммиты от A до E «переместились», но коммиты в git неизменяемы и представляют состояние всего кода, а не изменение, поэтому коммиты от A1 до E1 должны быть созданы заново с помощью механизма «перебазирования».)

Комментарии:

1. Я вижу, в этом есть большой смысл; спасибо вам за отличное объяснение ! Кстати, если P бы они могли быть объединены , но сломались mybranch , я бы сказал, что mybranch at E также будет сломан после слияния. Есть ли какой-нибудь способ избежать этой ситуации ? (Хотя, конечно , я мог бы это исправить E F .)

2. @wanwan git не знает и не заботится о том, что означает ваш код, он просто знает, как сравнивать и объединять текстовые файлы. Если P содержит дополнительную строку CSS, которая окрашивает вашу домашнюю страницу в красный цвет, то у E будет красная домашняя страница; git не может знать, было ли это ошибкой, и вы хотели сделать ее зеленой. Аналогичным образом, существует то, что вы могли бы назвать конфликтами «подводных лодок» — два изменения в разных частях кода, о которых git не знает, связаны, но которые между ними вызывают ошибку. То же самое может произойти без какого-либо контроля версий, если два человека отредактировали код; по крайней мере, git позволяет вам узнать, когда это произошло.

3. Еще раз спасибо вам. Таким образом, нарушенные коммиты слияния с такими конфликтами «подводных лодок» иногда неизбежны и должны быть исправлены в последующих коммитах, верно ?

4. @wanwan Правильно. Единственный инструмент, который может помочь вам в этом, — это комплексный набор автоматизированных тестов, который поможет вам обнаружить их раньше, но в конечном счете ошибки-это факт жизни.