TFS: слияние с основной веткой

У нас есть текущая ветка, где происходит основное развитие. Какое-то время работаю над чем-то вроде экспериментального в отдельной ветке. Другими словами, я разделил то, что мне нужно, из текущей ветки в экспериментальную. Во время работы я регулярно объединял Current с Experimental, чтобы у меня были изменения, внесенные другими, так что я уверен, что то, что я делаю, работает с их изменениями.

Теперь я хочу снова слиться с Current. Сначала я объединил Current в Experimental, скомпилировал и убедился, что все работает. Так что в моей голове экспериментальный и текущий должны быть «синхронизированы». Но когда я пытаюсь объединить Experimental с Current, я получаю целый ряд конфликтов. Но я думал, что уже решил их, когда объединил Current в Experimental.

Что здесь происходит? Я что-то совершенно не понял? Как я могу сделать это плавно? На самом деле не хочу проходить через все эти конфликты ...


person Svish    schedule 16.09.2009    source источник


Ответы (3)


Что говорится в итоговом сообщении, когда вы нажимаете «Разрешить отдельный конфликт»? Если ваши слияния из Current -> Experimental были выполнены без серьезной ручной работы, это должно быть что-то вроде «X источник, 0 цель, Y оба, 0 конфликтуют». Другими словами, в целевом (текущем) файле нет блоков содержимого, которых нет в копии исходной ветки (экспериментальный). Вы можете смело использовать кнопку AutoMerge All.

Примечание. AutoMerge должен быть безопасным в любом случае. Он оптимизирован для консервативного подхода к ранним предупреждениям, а не для того, чтобы разрешить все случаи. Но я понимаю, что многие из нас, в том числе и я, любят запускать инструмент слияния, когда возникают какие-либо вопросы. В описанном сценарии, ИМО, даже самые пугливые могут отдыхать спокойно.


Почему вообще возникает конфликт? А что, если итоговое сообщение не настолько банально? Рад, что вы спросили :) Короткий ответ - потому что вычисление, которое определяет общего предка («базу») связанных файлов, сильно зависит от того, как были разрешены предыдущие конфликты слияния между ними. Простой пример:

  1. создать два филиала, A и B.
  2. вносить правки в A \ foo.cs и B \ foo.cs в отдельных частях файла
  3. объединить A -> B
  4. AutoMerge конфликт
  5. слить B -> A

TFS должна пометить эту последовательность событий как конфликтующую. Ближайший общий предок между B \ foo.cs; 4 и A \ foo.cs; 2 находится на шаге 1, и с тех пор обе стороны, очевидно, изменились.

Заманчиво сказать, что A и B синхронизированы после шага 4. (Точнее: общим предком для слияния шага 5 является версия №2). Несомненно, успешное слияние контента подразумевает, что B \ foo.cs содержит все изменения, внесенные на сегодняшний день? К сожалению, есть ряд причин, по которым вы не можете этого предполагать:

  • Общее: не все конфликты можно объединить с помощью AutoMerged. Вам нужны критерии, применимые к обоим сценариям.

  • Корректность: даже если AutoMerge завершается успешно, он не всегда генерирует действительный код. Классический пример возникает, когда два человека добавляют одно и то же поле в разные части определения класса.

  • Гибкость: у каждого пользователя системы управления версиями есть свои любимые инструменты слияния. И им нужна возможность продолжить разработку / тестирование между первоначальным решением Resolve [«когда-нибудь нужно как-нибудь объединить содержимое»] и окончательной проверкой [«здесь, это работает»].

  • Архитектура: в централизованной системе, такой как TFS, сервер просто не может доверять ничему, кроме своей собственной базы данных + требований проверки API. Пока входные данные соответствуют спецификации, серверу не следует пытаться различать, как выполнялись различные типы слияния контента. (Если вы думаете, что сценарии до сих пор легко различимы, подумайте: что, если в движке AutoMerge есть ошибка? Что, если мошеннический клиент вызывает веб-службу напрямую с произвольным содержимым файла? Здесь только поверхностно ... серверы должны быть скептически настроены по какой-то причине!) Все, что он может безопасно вычислить, - это вы отправили мне результирующий файл, который не соответствует исходному или целевому.

Собрав эти требования вместе, вы получите дизайн, который объединяет наши действия на шаге 4 в довольно широкую категорию, которая также включает ручные слияния, возникающие в результате перекрывающихся правок, слияния контента [автоматически или нет], предоставляемые сторонними инструментами, и файлы вручную. отредактировал постфактум. В терминологии TFS это разрешение AcceptMerge. Будучи записанными как таковые, Правила слияния (TM) должны предполагать худшее в погоне за исторической целостностью и безопасностью будущих операций. В процессе ваши семантические намерения для Шага 4 («полностью включить в B каждое изменение, которое было внесено в A в # 2») были упрощены до нескольких байтов чистой логики («дать B следующее новое содержимое + кредит за обработку # 2 "). К сожалению, это «просто» проблема UX / образования. Люди сильно злятся, когда Правила слияния делают неверные предположения, которые приводят к поломке кода и потере данных. Напротив, все, что вам нужно сделать, это нажать кнопку.

FWIW, у этой истории есть много других концовок. Если вы выбрали «Копировать из исходной ветки» [aka AcceptTheirs] на шаге 4, на шаге 5 не возникнет конфликта. То же самое, если вы выбрали разрешение AcceptMerge, но случайно зафиксировали файл с тем же хешем MD5, что и A \ foo.cs; 2 . Если вместо этого вы выберете Keep Target [aka AcceptYours], последующие последствия снова изменятся, хотя я не могу вспомнить детали прямо сейчас. Все вышеперечисленное становится довольно сложным, когда вы добавляете другие типы изменений (особенно Rename), объединяете ветки, которые гораздо более несинхронизированы, чем в моем примере, вишня выбирает определенные диапазоны версий и обрабатывает сироты позже и т. Д.


РЕДАКТИРОВАТЬ: по воле судьбы кто-то другой задал точно такой же вопрос на форуме MSDN. Как обычно, я написал им еще один длинный ответ, который оказался совершенно другим! (хотя, очевидно, затрагивая те же ключевые моменты) Надеюсь, это поможет: http://social.msdn.microsoft.com/Forums/en-US/tfsversioncontrol/thread/e567b8ed-fc66-4b2b-a330-7c7d3a93cf1a

person Richard Berg    schedule 18.09.2009
comment
Ого, хорошее и подробное объяснение. Не уверен, что я полностью понял все это, но я думаю, именно поэтому я не в команде TFS: P В любом случае, имеет смысл, что это не так просто, как я хотел, чтобы это было: PI в конечном итоге пришлось пройти через все . Некоторые из них были конфликтами переименования, когда меня просто просили выбрать одну из альтернатив. Остальные были немного сложнее. Но вроде работает сейчас :) - person Svish; 18.09.2009
comment
Я опубликовал другое объяснение, надеюсь, менее запутанное :) - person Richard Berg; 19.09.2009

Со мной такое случалось раньше. Когда TFS объединяет Experimental с Current, он делает это, используя рабочие области на вашем жестком диске. Если текущая рабочая область на вашем локальном компьютере устарела, в TFS возникнут конфликты слияния.

(Экспериментально на HD)! = (Текущая версия в TFS)! = (Старая версия на HD)

Попробуйте выполнить принудительное получение Current, чтобы обновить локальную копию Current, и повторите попытку слияния.

person Ryan Michela    schedule 16.09.2009
comment
Пробовал, но, похоже, ничего не помогло. - person Svish; 17.09.2009
comment
Тем не менее, хорошее предположение. Это определенно может вызвать симптомы, подобные симптомам Свиша. - person Richard Berg; 18.09.2009

У вас, вероятно, есть такие строки, прежде чем вы начнете слияние ...

  • Основная ветвь - содержит коды A, B, C
  • Текущая ветка - содержит код A, B, C, D, E
  • Экспериментальная ветвь - содержит коды A, B, C, D, F, G, H

Когда вы переходите от Current к Exp, вы объединяете функцию E с экспериментальной веткой.

Когда вы затем переходите от Exp к Current, вам все равно придется объединить F, G и H. Вот где, вероятно, коренятся ваши конфликты.

---- Ответ на 1-й комментарий ---- Вы автоматически объединяете или используете инструмент слияния? Каков пример того, что «находится в конфликте»?

person StingyJack    schedule 16.09.2009
comment
У меня всего две ветки. И, чтобы продолжить ваш пример, я уже объединил Current в Experimental, так что Experimental также содержит E. Так что конфликтов быть не должно, только новый код. Если это имело смысл ... - person Svish; 17.09.2009
comment
Пытался выполнить автоматическое слияние, когда это было возможно, но это было не всегда. - person Svish; 18.09.2009