Team Foundation Server - перемещение источника с историей - PullRequest
57 голосов
/ 07 февраля 2010

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

Платформа интеграции TFS представляется одним из вероятных сценариев. Его можно использовать для изменения шаблона процесса в соответствии с документацией. Тем не менее, мне было любопытно, может ли работать синтаксис перемещения tf.exe? Что-то вроде:

tf.exe move $ / ProjectA $ / ProjectB

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

Любой совет или советы будут с благодарностью!

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

Ответы [ 4 ]

38 голосов
/ 07 февраля 2010

Move и Rename являются псевдонимами. В любой версии TFS нет абсолютно никаких отличий от командной строки или пользовательского интерфейса.

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

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

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

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

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

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 , где набор изменений 1234 был до переезда
  • tf history $ / ProjectB / somefile.cs; 5678 , где changeset 5678 был после перемещения. Или вы можете просто опустить версию.

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

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

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

РЕДАКТИРОВАТЬ - нет, ветвление не является хорошей альтернативой. Хотя ветвление оставляет достаточно метаданных в системе для отслеживания полной истории в ProjectB и из ProjectB, это не очень удобно для пользователя в 2008 году. Планируйте потратить много времени на изучение команды tf merges (без эквивалента пользовательского интерфейса) , В 2010 году значительно улучшена ваша способность визуализировать изменения в нескольких ветвях, но это по-прежнему непростая единая среда, которую вы получили бы от переименования.

17 голосов
/ 15 февраля 2011

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

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

tf history $/ProjectB/somefile.cs

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

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

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

2 голосов
/ 30 января 2014

Другой вариант (и мне кажется, проще) - импортировать в 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

0 голосов
/ 02 июня 2014

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

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

Имена источника, и цели должны быть заключены в кавычки, если в полном имени пути есть пробелы. Мне было трудно сделать это на $ _. 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 }

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...