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


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

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

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

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

8 68

8 ответов:

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

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

  2. в любое время, когда мне нужно внести изменения, я клонирую свой "мастер" РЕПО и делаю свою работу там. Я обнаружил, что Клон для каждой функции или истории на самом деле довольно прост в управлении и чувствует себя довольно чистым. После завершения функции я выполняю слияние Hg обратно в репо "master", в котором были применены все обновления TFS. Это позволяет мне использовать ртути возможности слияния, которые настолько превосходят TFS, что ставят под сомнение, как TFS может претендовать на слияние кода вообще. После завершения слияния я фиксирую его в Hg, а затем проверяю эти изменения в TFS. Лучшая часть этого заключается в том, что когда я делаю регистрацию в TFS, мне не нужно ничего объединять. Очень, очень мило.

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

  1. самым большим является тот факт, что TFS паршиво находит изменения. Там есть сделать записи плагин, который вы можете использовать, чтобы сделать измененные файлы доступными для записи, когда они обновляются/объединяются Mercurial. Есть два варианта, которые я нашел для этого. Вы можете либо заставить TFS перейти в автономный режим, и в этот момент он будет предполагать, что все записываемое должно быть возвращено, либо вы можете использовать инструмент сравнения в средстве управления версиями и выбрать измененные файлы и индивидуально проверить их. Оба дерьмовые ИМО

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

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

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

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

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

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

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

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

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

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

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

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

=====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 - это один клик

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

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

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

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

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's 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

i'he просто собрал небольшой инструмент HgTfs, который пытается достичь цели синхронизации репозиториев Mercurial и TFS. Это действительно просто и имеет только три команды: клонировать, тянуть и толкать. Вот мой Bitbucket РЕПО:

https://bitbucket.org/thepretender/hgtfs

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

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

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

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