TFS: слияние с основной веткой - PullRequest
18 голосов
/ 16 сентября 2009

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

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

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

Ответы [ 3 ]

23 голосов
/ 18 сентября 2009

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

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


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

  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 содержит все изменения, сделанные на сегодняшний день?К сожалению, есть ряд причин, по которым вы не можете принять это:

  • Общие положения: не все конфликты могут быть автоматически разрешены.Вам нужны критерии, применимые к обоим сценариям.

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

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

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

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

FWIW, у этой истории есть много других концовок. Если на шаге 4 вы выбрали «Копировать из исходной ветви [aka AcceptTheirs]», то на шаге 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

3 голосов
/ 16 сентября 2009

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

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

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

0 голосов
/ 16 сентября 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-й комментарий ---- Вы автоматически объединяетесь или используете инструмент объединения? Что является примером чего-то, что находится «в конфликте»?

...