2010-02-07 3 views
56

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

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

tf.exe движение $/ProjectA $/ProjectB

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

Любые советы или советы были бы высоко оценены!

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

ответ

37

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

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

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

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

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

Это не так просто, как сказать ТФ переименовывать $/Projecta $/projectB. Папки верхнего уровня в дереве управления версиями зарезервированы для мастера создания Team Project; вы не можете запускать стандартные команды 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 предполагают версию = «последняя». Любой из этих вариантов будет полная история вы хотите:

  • ТФ история $/Projecta/somefile.cs; 1234 где 1234 был ревизии до переезда
  • ТФ история $/ProjectB/somefile.cs ; 5678, где сменой 5678 было после переезда. Или вы можете просто опустить версию.

Окончательный вариант для полноты & целей отладки:

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

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

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

+0

Вау, Ричард. Абсолютно фантастическая информация. Я постараюсь это в моей тестовой лаборатории завтра. Вы упоминали сценарии, потому что корень зарезервирован Если я делал переименование из папки, которая была ниже уровня корня, я мог бы опустить скрипт, а затем - правильно? В любом случае - удивительный ответ. Спасибо за ваше время! –

+0

Да. Основная идея - переименовать ProjectA \ folder1 -> ProjectB \ folder1, ProjectA \ folder2 -> ProjectB \ folder2 и т. д. Сценарий просто позволяет сэкономить время и усилия, если у вас есть 50 файлов и папок. –

+0

Отлично. Большое вам спасибо за то, и легко понимать! –

16

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

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

tf history $/ProjectB/somefile.cs 

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

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

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

+2

Спасибо, что указали на опасность удаления «ProjectA» и того, как она влияет на визуальную историю. –

+0

Благодарим за указание «наименее недавнего» списка с помощью маленькой стрелки слева от идентификатора набора изменений. Я думал, что потерял всю свою историю :-( –

1

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

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

  • Clone папку TFS:

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

  • разъединить мерзавец 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

Вы должны получить сообщение в этой точке «ГИТ-ТФ: это вновь сконфигурированный хранилище Из tfs ничего не вышло ».

git commit -a -m "merge commit"

git tf checkin --deep

+0

Уважаемый david004. Я пробовал это, и история кода поддерживается, но все временные метки установлены на сегодняшний день, и все пользователи меняют. Является ли это тем, как это работает, или мне не хватает что-то? – AllWorkNoPlay

+0

Да, это неприятность. Я не знаю, как этого можно избежать, хотя я подозреваю, что какой-то элемент управления версиями ninja может написать сценарий для TFS, который извлекает и вставляет дату и информацию об авторе. – david004

0

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

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 } 

Также обратите внимание, что требует использования кавычки `, чтобы избежать"

Смежные вопросы