#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
atE
также будет сломан после слияния. Есть ли какой-нибудь способ избежать этой ситуации ? (Хотя, конечно , я мог бы это исправитьE
F
.)2. @wanwan git не знает и не заботится о том, что означает ваш код, он просто знает, как сравнивать и объединять текстовые файлы. Если P содержит дополнительную строку CSS, которая окрашивает вашу домашнюю страницу в красный цвет, то у E будет красная домашняя страница; git не может знать, было ли это ошибкой, и вы хотели сделать ее зеленой. Аналогичным образом, существует то, что вы могли бы назвать конфликтами «подводных лодок» — два изменения в разных частях кода, о которых git не знает, связаны, но которые между ними вызывают ошибку. То же самое может произойти без какого-либо контроля версий, если два человека отредактировали код; по крайней мере, git позволяет вам узнать, когда это произошло.
3. Еще раз спасибо вам. Таким образом, нарушенные коммиты слияния с такими конфликтами «подводных лодок» иногда неизбежны и должны быть исправлены в последующих коммитах, верно ?
4. @wanwan Правильно. Единственный инструмент, который может помочь вам в этом, — это комплексный набор автоматизированных тестов, который поможет вам обнаружить их раньше, но в конечном счете ошибки-это факт жизни.