Реальное использование Mercurial с Team Foundation Server? - PullRequest
68 голосов
/ 25 февраля 2010

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

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

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

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

Ответы [ 8 ]

53 голосов
/ 28 февраля 2010

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

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

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

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

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

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

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

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

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

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

Сначала как @ Эрик Хекстер указывает в комментариях, вы можете использовать расширение rebase , чтобы лучше интегрировать коммиты из ваших рабочих репозиториев в ваш основной репозиторий 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 и команда TF PowerTools "scorch". И те, и другие эффективно удаляют файлы, которые не находятся под контролем версий (технически «палящий» обеспечивает соответствие TFS и вашего локального рабочего каталога, поэтому он также может обновлять файлы).

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

9 голосов
/ 24 июня 2010

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

5 голосов
/ 02 июня 2011

@ Эрик, твой пост на lostechies был самым полезным. В VS2010 мне пришлось добавить опции / diff и / delete к команде tftp online в сценарии push, чтобы получить измененные и удаленные файлы, которые будут проверены в TFS. Первоначально я получал ошибку от push, когда файл был удален (из -working), что hg update равно
"невозможно удалить 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 в / из TFS можно было одним щелчком мыши

3 голосов
/ 27 февраля 2010

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

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

2 голосов
/ 28 июля 2013

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

https://bitbucket.org/thepretender/hgtfs

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

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

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

2 голосов
/ 29 мая 2012

Вот скрипт powershell, который я использовал для работы с 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'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
2 голосов
/ 09 июня 2010

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

1 голос
/ 11 марта 2010

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

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