Реальное использование Mercurial с Team Foundation Server?

Мой магазин использует TFS и, как правило, доволен им, за исключением отсутствия локального репозитория, который совершает/возвращает. Я начинаю использовать Mercurial локально, чтобы помочь управлять небольшими фрагментами изменений, а затем отправлять их в TFS. Я вижу, что Subversion имеет компонент "bridge", чтобы автоматически включить это, если центральный VCS является Subversion. Я не нашел его для Team System. Это побуждает меня, чтобы другие люди пошли по этому пути с интеграцией DVCS с системами CVCS.

(1) Кто-нибудь знает об этом? Я как бы сомневаюсь в этом (быстрый поиск ничего не нашел).

(2) Кто-нибудь использует Mercurial/TFS таким образом? Если да, можете ли вы поделиться своим опытом. Я особенно ищу любую информацию о том, какие проблемы могут возникнуть, которые не очевидны в отношении фиксации TFS после значительного действия через Mercurial.

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

Ответ 1

Не уверен, что это еще что-то, о чем вы еще не знаете, но сейчас я использую mercurial локально на некоторое время, и до сих пор я думаю, что преимущества перевешивают дополнительные накладные расходы на управление двумя системами управления версиями. Вот как я делал:

  • Я сделал мой TFS checkout репозиторием HG, который я считаю своим "мастером". Я получаю обновления от TFS и привязываю их к этому репо, поэтому он содержит самое текущее состояние проекта из TFS. Важно то, что никаких изменений в этом нет независимо от обновления TFS или слияния Hg (которое является частью 2)

  • В любое время, когда мне нужно внести изменения, я клонирую свое "мастерское" репо и выполняю свою работу. Я обнаружил, что клон для каждой функции или истории на самом деле довольно прост в управлении и выглядит довольно чистым. Как только я завершаю функцию, я возвращаю Hg обратно в "master" репо, в котором были применены все обновления TFS. Это позволяет мне использовать возможности Merurials merge, которые до сих пор превосходят TFS, чтобы подвергнуть сомнению, как TFS может претендовать на слияние кода вообще. Как только слияние завершено, я фиксирую его в Hg, а затем проверю эти изменения на TFS. Лучшая часть этого заключается в том, что, когда я делаю checkin для TFS, мне не нужно что-либо слить. Очень, очень приятно.

Теперь вот проблемы, которые я нашел с этим подходом:

  • Самым большим является тот факт, что TFS отвратительна при поиске изменений. Существует make writable плагин, который вы можете использовать, чтобы сделать измененные файлы доступными для записи, когда они обновляются/сливаются Mercurial. Для этого есть два варианта. Вы можете либо заставить TFS выйти в автономный режим, и в этот момент он предположит, что нужно что-либо записывать, или вы можете использовать инструмент сравнения в инструменте управления версиями и выбирать измененные файлы и индивидуально проверять их. Оба являются дрянной ИМО

  • Связи с контролем источника все еще присутствуют на уровне проекта, даже если вы исключаете файлы управления источником TFS из своего репозитория hg (что вам нужно делать). Это не очевидно, пока вы не добавите файл в решение, после чего он попытается добавить его в исходный элемент управления. Вы можете "Отменить ожидающие изменения" и избавиться от добавления элемента управления версиями, но это действительно раздражает.

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

Я еще не применял это для обновления веток в TFS, но я предполагаю, что это будет намного лучше, чем параметры, которые вы даете для слияния в TFS. В соответствующей заметке, поскольку вы можете одновременно проверять куски рабочих функциональных возможностей, использование слияния TFS было бы менее проблематичным только потому, что все изменения, необходимые для функции, были бы объединены в одном месте.

Одна вещь, которую я не пыталась решить, это обмен ею по всей команде. Отчасти причина в том, что это действительно не обязательно для всей команды. Я работаю удаленно, поэтому наличие локального хранилища - это большое дело и экономит много времени. Другие члены моей команды разработчиков могут или не могут получить такую ​​же выгоду от этого подхода, но я нахожу это довольно здорово, что я могу без эффекта, как они работают.

Обновление Я хотел бы некоторое время обновлять этот ответ с дополнительной информацией, основанной на комментариях, и некоторыми из моих опытов, связанных с большими репозиториями TFS.

Сначала, как @Эрик Хекстер указывает в комментариях, вы можете использовать расширение переадресации, чтобы лучше интегрировать фиксации из ваших рабочих репозиториев в основной репозиторий TFS. Хотя, в зависимости от того, как вы хотите, чтобы ваши коммиты появлялись в TFS, вы можете использовать свернуть расширение, чтобы вырезать ваши изменения в единую фиксацию ( это может сделать откаты в TFS проще). Существует также "онлайн-команда" из TFS PowerTools, которая может сделать работу, позволяющую TFS знать, что изменилось легче (еще раз спасибо Эрику за отметив, что в его блоге)

Теперь, когда я изначально написал это, я работал над проектом, у которого была только одна ветвь TFS, которую использовали разработчики, и была довольно маленькой, поэтому клонирование репозиториев было неважным. Позже я обнаружил, что работаю над проектом, у которого было репо, которое составляло около 1,5 ГБ после проверки, и намного больше после сборки, и часто включало переключение между ветвями в TFS. Очевидно, что этот подход плохо подходит для этой среды (в частности, поскольку в какой-то момент невозможно было создать решения в произвольном каталоге.

Проблема размера лучше всего обрабатывать, используя технику, аналогичную ветвям ветвей gits, а не клонирование репозиториев в новые каталоги. Для этого есть пара вариантов. Я считаю, что лучше всего использовать расширение и создать тему "закладки", а не ветки темы. Вы также можете использовать именованные ветки, но у них есть небольшой недостаток - быть постоянным и путешествовать с любыми клонами, которые вы можете делать (если вы хотите поделиться своим отличным гибридом TFS-Hg с коллегой). Закладки локальны для вашего репо и эффективно указывают на фиксацию и перемещение с головой. Они реализованы так, чтобы их можно было использовать в любом месте, где Hg ожидает ревизии (поэтому объединяет, обновляет и т.д.). Вы можете использовать их для создания закладки TFS в качестве основной "ветки", которая получает только обновления от TFS и сливается с работой темы, каждая из которых имеет свои собственные закладки, и вы можете удалить ее после того, как вы вернетесь в TFS. Если вы предпочитаете использовать именованные ветки, тогда вы можете применять точно такие же методы, которые удобны.

Теперь проблема с несколькими ветвями сложнее, тем более что "ветки" TFS являются фактически копиями каждого файла из исходной ветки, а это означает, что каждый раз, когда вы тянете ветки с TFS, ваше репо собирается получить намного больше, Один из возможных способов справиться с этим - использовать комбинацию названных ветвей Hg и закладок, так что у вас есть ветвь для каждой ветки TFS, а затем создайте закладки для вашей работы из этих ветвей. Настоящая головная боль в этих сценариях фактически связана с рабочими пространствами TFS через все это. Вы можете удалить сопоставления в своих рабочих пространствах и получить довольно далеко, но как только вы вернетесь в свой рабочий каталог, вы должны быть осторожны с TFS, топая файлами (на самом деле это полезно, когда TF PowerTools пригодится). Попытка оставить рабочую область при подключении, когда ваши ветки переключения становятся уродливыми. Парой инструментов, которые приятно иметь в вашем наборе инструментов, являются Hg расширение очистки и команда TF PowerTools "scorch". Оба эффектно удаляют файлы, которые не находятся в управлении версиями (технически "scorch" гарантирует соответствие TFS и вашей локальной рабочей директории, поэтому он также может обновлять файлы).

Для меня, однако, этот процесс стал довольно обременительным и подверженным ошибкам. Недавно я переключился на использование git с git-tfs, так как он управляет рабочими пространствами TFS для меня и снимает большую нагрузку связанных с этой стороной. К сожалению, там нигде нет "hg-tfs", иначе я бы выбрал это.

Ответ 2

Если вы не застряли в mercurial, есть сладкий проект интеграции git/tfs, который я использовал под названием git -tfs. Он очень похож на git -svn, но вместо этого нажимает/тянет из TFS. Проверьте это на http://github.com/spraints/git-tfs

Ответ 3

@Eric, ваше сообщение в lostechies было наиболее полезным. С VS2010 мне пришлось добавлять опции /diff и /удалять в команду tftp online в push script, чтобы получить измененные и удаленные файлы для проверки в TFS. Первоначально я получал ошибку от нажатия, когда файл был удален (из -working), что hg update - это msgstr "невозможно удалить FileXyz: доступ запрещен".
Я установил расширение MakeWritable.py, но это работает только при открытии файлов, которые не были удалены. Поэтому я добавил вызов attrib, чтобы удалить READ-ONLY из всех файлов в проекте, а затем восстановить его (исключая папку .hg). Я также добавил /diff, так что различия обнаруживаются контрольной суммой MD5 вместо зависимости от атрибута READ-ONLY. Кажется, теперь он работает нормально.

=====FILE: push.ps1=====
$projName = "TicTacToeCMMI"
$tftp = "C:\Program Files\Microsoft Team Foundation Server 2010 Power Tools\TFPT.exe"
$tf = "C:\Program Files\Microsoft Visual Studio 10.0\Common7\ide\tf.exe"

hg push
cd ..\$projName-tfs  
"Syncing -tfs workspace with TFS server"  
&$tftp scorch /noprompt /exclude:.hg',_Resharper*',*.user  
"Making all files in -tfs writable"
attrib -R /S /D *
"Updating -tfs with latest push from Mercurial"
hg update -C -y
attrib +R /S /D *
attrib -R /S /D .hg\*
"Resyncing Mercurial changes with TFS Server"  
&$tftp online /adds /deletes /diff /exclude:'.hgignore,.hg,bin,obj,*.ps1,_Resharper*,*.lnk,*.user,*.suo,*.vspscc'  
"Checkin"  
&$tf checkin  
cd ..\$projName-working  
cmd /c pause  

====FILE: pull.ps1=====
$projName = "TicTacToeCMMI"
$tf = "C:\Program Files\Microsoft Visual Studio 10.0\Common7\ide\tf.exe"
$username = cmd /c set USERNAME
$username = $username.SubString($username.IndexOf("=")+1)

function pull {
    cd ..\$projName-tfs
    &$tf get
    hg commit -A -m "from tfs" --user $username
    cd ..\$projName-working
    hg pull --rebase
}
pull  
cmd /c pause  

У меня была небольшая кривая обучения с сценариями PowerShell, которые я раньше не использовал. Для других, подобных мне, сценарии запускаются с ярлыком следующим образом:

TARGET: C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe C:\dev\TicTacToeCMMI-working\push.ps1
START IN: C:\dev\TicTacToeCMMI-working

Я нажимаю на панели задач push и pull, поэтому push/pull to/from TFS - это один клик

Ответ 4

Я знаю, что некоторые люди использовали hgsubversion с мостом Subversion. Я не знаю, как хорошо это работает, и мне никогда не приходилось использовать TFS.

Насколько мне известно, нет "более родного" моста, чем использование TFS → Subversion Bridge → hgsubversion, но я также слышал, что он работает достаточно хорошо. Мое чрезвычайно ограниченное понимание TFS предполагает, что его внутренняя модель должна быть достаточно подобрана для Subversion для таких вещей, как hgsubversion, чтобы работать очень хорошо.

Ответ 5

Если вы хотите работать с DVCS и TFS, я считаю, что лучший способ - установить SVNBridge для TFS и использовать Bazaar, который является AFAIK единственным DVCS, который легко интегрируется с SVN, и поскольку ваша TFS теперь выглядит как SVN, вы волшебным образом получаете интеграцию Bazaar/TFS

Ответ 6

Здесь используется powershell script, который я использовал для работы с TFS и hg. Для использования вам нужно создать hg-репозиторий в вашей папке TFS (зафиксировать в нем файлы из TFS), клонировать этот репозиторий и работать в новом репозитории. После того, как вы счастливы, вы можете запустить "hgtfs.ps1 push", чтобы вернуть изменения в TFS из вашего ртутного хранилища.

hgtfs.ps1:

param([parameter(Position=0, Mandatory=$true)][string] $action)

$HGDirectory = Get-Location
$TfsDirectory = @(hg paths | where-object { $_.StartsWith("default = ") })[0].SubString(10)

# Pull from TFS
function pull
{
    # Todo pull changes one by one brining who did it and the comment into HG
    # tf history . /recursive /format:brief /noprompt /version:300~1000 /sort:ascending
    # tf properties . /recursive

    # Add the changes from TFS into the TFS HG repository
    Set-Location $TfsDirectory
    tf get . /recursive
    hg commit -A -m "Update from TFS"  

    # Pull / merge the changes from TFS HG repository
    Set-Location $HGDirectory
    hg pull
    hg merge --tool internal:fail
    hg commit -m "Merged from TFS"

    ""
    "The you have the following conflicts which need resolving"
    hg resolve -l | write-host -foregroundcolor "red"
    #thg commit
}

# Push to TFS
function push 
{
    Set-Location $HGDirectory
    hg push
    Set-Location $TfsDirectory

    $FilesModified = @()
    $FilesRenamed = @{} # Key: old file name .... Val: new file name
    $FilesRemoved = @()
    $FilesAdded = @()

    # Work out what changes have taken place
    "Calculating the changes which have been made in HG..."
    tfpt scorch /exclude:.hg,*.user | out-null
    $AllChanges = hg status --rev .:tip -A 
    for($i = 0; $i -lt $AllChanges.length ; $i++)
    {
        $type = $AllChanges[$i].SubString(0, 2)
        $fileName = $AllChanges[$i].SubString(2)

        switch($type)
        {
            "M " # Modified files  
                { 
                    $FilesModified += $fileName
                } 

            "A " # New Files
                {  
                    $nextType = $null
                    $nextFileName = $null
                    if($AllChanges.length -gt ($i+1))
                    {
                        $nextType = $AllChanges[$i+1].SubString(0, 2)
                        $nextFileName = $AllChanges[$i+1].SubString(2)                
                    }

                    if($nextType -eq "  ")
                    {
                        # we have a rename
                        $FilesRenamed[$nextFileName]=$fileName
                        $i++
                    }
                    else
                    {
                        # we're adding the file
                        $FilesAdded += $fileName
                    }
                 }

            "R " # Removed
                {
                    if($FilesRenamed.ContainsKey($fileName))
                    {
                        continue
                    }

                    $FilesRemoved += $fileName
                }

            "C " # Same 
                { 
                    continue 
                }

            default 
                { 
                    "Unknown HG status line: "+$AllChanges[$i] 
                    return -1
                }
        }
    }

    # perform the TFS operations 
    "Renaming files in TFS..."
    foreach($file in $FilesRenamed.Keys) {   
        tf checkout $file | out-null
        tf rename $file $FilesRenamed[$file] | out-null
    }

    "Checking out for edit in TFS..."
    foreach($file in $FilesModified) { tf checkout $file | out-null }

    "Removing files from TFS..."
    foreach($file in $FilesRemoved) { tf delete $file | out-null }

    # perform the Mercural update
    "Pulling changes out of HG...."
    hg update --rev .:tip --clean

    # perform any POST TFS operations
    "Adding new files to TFS..."
    foreach($file in $FilesAdded) { tf add $file }

    "Cleaning up..."
    tfpt uu /noget
    tf checkin
}


if ($action -eq "push") { push }
elseif ($action -eq "pull") { pull }
else { "Unknown action ... please supply 'push' or 'pull'" }

# return to our starting point
Set-Location $HGDirectory

Ответ 7

Я только что собрал небольшой инструмент HgTfs, который пытается достичь цели синхронизации хранилищ Mercurial и TFS. Это очень просто и имеет только три команды: клонировать, тянуть и нажимать. Вот мой ретранслятор Bitbucket:

https://bitbucket.org/thepretender/hgtfs

Существует также сообщение в блоге, описывающее сценарий рабочего процесса и использования (на самом деле, страницы вики - только части этой записи в блоге):

http://www.olegtarasov.me/Post/2013/07/Mercurial-to-TFS-bridge-(hgtfs)

Код взломан, но, похоже, он выполняет свою работу. Я был бы очень признателен за любую обратную связь или вилки:)

Ответ 8

У меня была хорошая попытка заставить его работать. Я мог бы получить Git и TFS, играя вместе (ссылка) через svnbridge, но я не мог получить меркурий для работы через svnbridge, что расстроило меня Нет конца. Если вам удастся заставить его работать, дайте мне знать, потому что я лично предпочитаю mercurial над Git (хотя оба они замечательные)