Подтвердить что ты не робот

Team Foundation Server - перемещение источника с историей

Мне было интересно, какой лучший подход может быть при перемещении исходного кода с историей из одного Team Project в другой Team Project. Меня не интересуют рабочие элементы, отчеты или сайты SharePoint, поскольку система, которую мы собираемся восстановить, не использовала эти функции. Причина желания перейти к другому проекту Team также обусловлена ​​тем фактом, что первоначальная реализация (восстанавливаемая из резервной копии, которая поддерживалась сторонней стороной), использовала сторонний шаблон процесса, который мы не хотим использовать идти вперед. Мы хотим начать использовать отслеживание рабочих элементов и отчетность после завершения миграции.

TFS Integration Platform, по-видимому, является одним из вероятных сценариев. Он может быть использован для изменения шаблона процесса в соответствии с документацией. Однако мне было любопытно, может ли работать синтаксис tf.exe move? Что-то вроде:

tf.exe move $/ProjectA $/ProjectB

Насколько я понимаю, эта команда работает так же, как операция переименования, тогда как перемещение с помощью контекстного меню "Переместить" в "Источнике управления версиями" больше похоже на операцию удаления и добавления. Кроме того, будет ли путь перемещения tf.exe фактически ассоциировать код под папками с соответствующим Team Project, предполагая, что $/ProjectA является корневой папкой управления исходным кодом для одного проекта, а $/ProjectB является корневой папкой управления источником для другого? Ключ должен быть в состоянии сохранить историю, если это возможно.

Мы будем благодарны за любые советы или советы!

Изменить. Может ли разветвление на другой проект обрабатывать этот сценарий - как Microsoft обсуждает в документации Ветвление руководства? Я думаю, что это может быть ответом, поскольку история, вероятно, сохранится с веткой. Однако на данный момент у меня нет доступа к экземпляру Team Foundation Server 2008, чтобы проверить его.

4b9b3361

Ответ 1

Перемещение и переименование - это псевдонимы. В любой версии TFS нет никакой разницы из командной строки или пользовательского интерфейса.

Оба сохраняют историю. По крайней мере, в 2005/2008 году вы сохраняете один и тот же физический элемент в таблице VersionedItem независимо от того, насколько часто или насколько сильно изменяется имя и/или родительский путь. На самом деле нет способа получить "поддельное" переименование (удалить + добавить) без большой ручной работы с вашей стороны.

Однако, хотя эта модель версий очень чиста в теоретическом смысле, она имеет некоторые практические ошибки. Поскольку разные элементы могут занимать одно и то же имя в разные моменты времени, TFS требуется полное имя + версия, чтобы однозначно идентифицировать любые входы, которые вы отправляете. Обычно вы не заметили этого ограничения, но как только вы переименовали элементы в системе, если вы скажете tf [doSomething] $/newname -version: oldversion, то он будет запутан и либо выбросит ошибку или работать с предметом, который вы, возможно, не планировали. Вы должны быть осторожны, чтобы передавать действительные комбинации (newname + newversion или oldname + oldversion), чтобы обеспечить поведение команд так, как вы хотите.

TFS 2010 несколько изменяет историю: это ветка + удалить под обложками, в результате чего элементID изменится. Тем не менее, ежедневные команды, такие как Get и History, "подделаны" очень хорошо; старые клиенты примерно на 95% совместимы. Преимущество состоит в том, что когда у вас есть несколько переименований в системе, и поиск на основе пути начинает становиться двусмысленным, как указано выше, сервер просто примет имя, которое вы укажете и запустите с ним. Это улучшает общую производительность системы и устраняет несколько ловушек, к которым часто приходили незнакомые пользователи, ценой не столь гибкой и не сохраняющей историю со 100% -ной точностью (например, при столкновении имен при объединении двух ветвей).

Возвращаясь к проблеме...

Это не так просто, как сказать tf переименовать $/projectA $/projectB. Папки верхнего уровня в дереве управления версиями зарезервированы для мастера создания Team Project; вы не можете запускать стандартные команды tf против них. Вам нужен script как:

Get-TfsChildItem $/ProjectA |
    select -Skip 1 |  # skip the root dir
    foreach {
        tf rename $_.serveritem $_.serveritem.replace("$/ProjectA", "$/ProjectB")
    }

[конечно, вы можете сделать это вручную, если не так много детей в $/ProjectA]

Насколько я уже упоминал, я расскажу об этом прямо сейчас, так как поиск старой истории кажется вам очень важным. Когда вы проверите переименование, tf history $/ProjectA/somefile.cs НЕ будет работать. По умолчанию команды tf предполагают версию = "последняя". Любой из этих альтернатив будет иметь полную историю, которую вы хотите:

  • tf history $/ProjectA/somefile.cs; 1234, где changeet 1234 был до перемещения
  • tf history $/ProjectB/somefile.cs; 5678, где changeet 5678 был после перемещения. Или вы можете просто опустить версию.

Конечная альтернатива для полноты и отладки:

  • tf history $/ProjectA/somefile.cs -slotmode. Вы увидите только изменения, произошедшие до переезда; однако вы также увидите историю любых других элементов, которые могли прожить в слоте $/ProjectA/somefile.cs "до или после элемента, который вы перемещали под B.

(В TFS 2010 режим "слот" - это поведение по умолчанию, есть опция -ItemMode, чтобы запросить отслеживание вашего поиска в истории, как это было в 2008 году, а не на основе путей.)

EDIT - нет, разветвление не является отличной альтернативой. В то время как разветвление оставляет достаточно метаданных в системе для отслеживания полной истории в ProjectB и из ProjectB, это не очень удобно для пользователей в 2008 году. Планируйте потратить много времени на изучение команды tf merges (нет эквивалента пользовательского интерфейса). 2010 значительно улучшает вашу способность визуализировать изменения в нескольких ветвях, но это еще не чистый унифицированный опыт, который вы получите от переименования.

Ответ 2

Ответ Ричарда выше хорошо написан и хорошо объясняет ситуацию. Однако у меня была еще пара практических вопросов, которые нужно добавить.

В TFS2010 поведение по умолчанию делает его показаться похожим на перемещение файла, заставляя вас потерять всю историю до перемещения. Команда, которую мои пользователи могут использовать (и тот, который используется, по-видимому, графическим интерфейсом VS2010):

tf history $/ProjectB/somefile.cs

Мои пользователи намерены получить всю историю somefile.cs, как до, так и после перемещения. Они хотят "историю кода, который в настоящее время хранится в $/ProjectB/somefile.cs", независимо от имени файла в любой момент времени. Возможно, другие люди видят это по-другому.

Первый способ заключается в том, что GUI, который появляется для меня в VS2010 с использованием TFS2010, начинается с истории только с момента перехода. Наименее недавний элемент в списке - это операция переименования. Его можно расширить с помощью тонкой стрелки раскрывающегося списка. Ниже представлена ​​история из предыдущего места. Если вы не знаете, как это искать, может показаться, что ваша история ушла.

Вторая проблема заключается в том, что если вы позже удалите ProjectA (потому что вы закончили переход к ProjectB, скажем), история действительно исчезла. Расширение раскрывающегося списка в истории для $/ProjectB/somefile.cs не создает более старую историю.

Ответ 3

Другой вариант (и, я думаю, проще) - импортировать в Git, а затем экспортировать обратно в TFS, используя команду Git -TF линейных инструментов.

  • Установите Git -TF из двоичного кода, Choclatey или исходного кода.

  • Клонировать папку TFS:

git tf clone https://myAcc.visualstudio.com/mycollection $/TeamProjectA/Main --deep

  • Отсоедините Git Repo от сервера TFS, удалив папку .Git/tf и .Git/git-tf.

  • Настройте новый Git Repo для подключения к пустой папке TFS.

git tf configure https://myAcc.visualstudio.com/mycollection $/TeamProjectB/Main --deep

  • Не забывайте --deep

git tf pull

В этот момент вы должны получить сообщение "git -tf: это вновь настроенный репозиторий. Из tfs нечего извлекать".

git commit -a -m "merge commit"

git tf checkin --deep

Ответ 4

Относительно исходной команды выше: -

Get-TfsChildItem $/ProjectA |
select -Skip 1 |  # skip the root dir
foreach {
    tf rename $_.serveritem $_.serveritem.replace("$/ProjectA", "$/ProjectB")
}

И исходные, и целевые имена должны быть окружены кавычками в случае, если в полном пути pathfilename есть пробелы. Мне было трудно сделать это на $_. ServerItem, как окружающий его с экранированным ", возвращает весь дочерний объект, а не только строку .serverItem. Или, если мне удалось получить строку, я получил нежелательные возвращения каретки, такие как

"
$ Проектируемых/папки/файлы
"

В конце концов я получил команду для работы со следующим, но я обнаружил, что история по-прежнему не передается, что было целым! Поэтому я считаю, что эта команда является прямым эквивалентом простого щелчка правой кнопкой мыши в проводнике источника и выбора переименования (или перемещения).

$tfsServerString = "http://machine:8080/tfs/DefaultCollection"
$tfs = Get-TfsServer $tfsServerString
Get-TfsChildItem -server $tfs "$/Dest Project/MyTestProject" | select -Skip 1 | foreach { $sourceName = $_.serveritem; $targetName = $_.serveritem.replace("$/Dest Project/MyTestProject/", "$/Dest Project/Source/StoreControllers/dSprint/dSprint2/") ; ./tf rename `"$sourceName`" `"$targetName`" /login:myUser }

Также обратите внимание, что для этого требуется использовать обратный ход `escape '