web-dev-qa-db-ja.com

MercurialとTeam Foundation Serverの実際の使用?

私のショップはTFSを使用しており、ローカルリポジトリのコミット/リバートの欠如を除いて、TFSに概ね満足しています。 Mercurialをローカルで使用して、小さな変更のチャンクを管理し、それらをTFSに投稿し始めています。中央のVCSがSubversionの場合、Subversionにはこれを自動的に有効にする「ブリッジ」コンポーネントがあることがわかります。チームシステム用のものが見つかりません。これは、他の人々がDVCSをCVCSシステムと統合することでこの道を進んだことを私に励まします。

(1)誰か知っていますか?私はそれを疑っています(クイック検索では何も見つかりませんでした)。

(2)この方法でMercurial/TFSを使用している人はいますか?使用している場合、あなたの経験を共有できますか? Mercurialを介した重要なアクティビティの後のTFSへのコミットに関して明確ではない問題が発生する可能性のある洞察を特に探しています。

これまでのところ、私だけが数日間使用した場合は完全に有利なように思えますが、そのように簡単だと思うほど十分に知っています。

68
Kevin Won

これがまだわからないことかどうかはわかりませんが、私はMercurialをローカルでしばらく使用してきましたが、これまでのところ、2つのソース管理システムを管理することによる追加のオーバーヘッドを上回る利点があると思います。ここに私が物事をやっている方法があります:

  1. 私はTFSチェックアウトを、自分の「マスター」と見なすHGリポジトリーにしました。 TFSから更新を取得してこのリポジトリにコミットするため、これにはTFSからのプロジェクトの最新の状態が含まれています。ここで重要なことは、TFSの更新やHgマージ(パート2)とは無関係に行われた変更はないということです。

  2. 変更が必要なときはいつでも、「マスター」リポジトリのクローンを作成して、そこで作業を行います。機能またはストーリーごとのクローンは、実際には管理が非常に簡単で、とてもきれいに感じられることがわかりました。機能を完成させたら、Tgの更新がすべて適用された "マスター"リポジトリにHgマージを行います。これにより、Mercurialsのマージ機能を使用できるようになります。これは、TFSがコードをマージすると主張する方法を疑問視するほど、TFSよりもはるかに優れています。マージが完了したら、Hgでコミットしてから、それらの変更をTFSにチェックインします。これの最も良い部分は、TFSへのチェックインを行うときに、何もマージする必要がないことです。とってもとっても素敵。

さて、これが私がこのアプローチで見つけた問題です:

  1. 最大のものは、TFSが変更を見つけるのにひどいことです。 Mercurialによって更新/マージされたときに変更されたファイルを書き込み可能にするために使用できる make writable プラグインがあります。これには2つのオプションがあります。 TFSを強制的にオフラインにすることができます。その時点で、書き込み可能なものがチェックインされる必要があると想定するか、ソース管理ツールの比較ツールを使用して変更されたファイルを選択し、個別にチェックアウトすることができます。どちらもくだらないIMOです

  2. HgリポジトリからTFSソース管理ファイルを除外した場合でも、ソース管理バインディングはプロジェクトレベルにあります(削除する必要があります)。これは、ソリューションにファイルを追加するまで完全には明らかではありません。その時点で、ファイルをソース管理に追加しようとします。 「保留中の変更を元に戻す」ことができ、ソース管理の追加を取り除くことができますが、それは本当に面倒です。

良い知らせは、私がこのアプローチを使用してかなり大規模なマージを処理したことです。TFSツールを使用することを余儀なくされた場合、何らかの形のハードドラッグを使用するようになったと思います。

私はまだこれをTFS内のブランチの更新に適用していませんが、TFSでマージするために提供されるオプションよりもはるかに優れていると思います。関連する注意点として、一度に機能する機能のチャンクをチェックインできるため、機能に必要なすべての変更が1か所にまとめられるため、TFSマージを使用しても問題が少なくなります。

私が取り組んだことのない1つのことは、これをチーム全体で共有することです。その理由の1つは、それがチーム全体のものである必要がないことです。私はリモートで作業するので、ローカルリポジトリを用意することは非常に重要であり、多くの時間を節約できます。私の開発チームの他のメンバーは、このアプローチから同じ利益を得るかもしれないし、得ないかもしれませんが、私はそれらが動作する方法に影響を与えずに私ができることがかなりクールだと思います。

Updateこの応答をしばらくの間、コメントに基づいた追加情報と、大規模なTFSリポジトリでのいくつかの経験に基づいて更新したいと思っていました。

最初に@ Eric Hexter がコメントで指摘しているように、 [rebase extension ]を使用して、作業リポジトリからのコミットをメインのTFSリポジトリに適切に統合できます。ただし、コミットをTFSにどのように表示するかによっては、 collapse extension を使用して変更を1つのコミットに圧縮することができます(これにより、TFSでのロールバックが容易になります)。 TFS PowerTools からの「オンライン」コマンドもあります。これにより、TFSに変更点を簡単に知らせることができます(Ericの彼の ブログ投稿 で言及してくれたことに感謝します) )

さて、私が最初にこれを書いたとき、私は開発者が使用しているTFSブランチが1つだけあり、かなり小さいプロジェクトに取り組んでいたため、リポジトリのクローン作成は大したことではありませんでした。後で、チェックアウト後のレポジトリが約1.5GBで、ビルド後のサイズがはるかに大きく、TFSのブランチ間の切り替えを頻繁に伴うプロジェクトに取り組んでいることに気付きました。明らかに、このアプローチはこの環境にはあまり適していません(特に、任意のディレクトリでソリューションを構築することが一時的に不可能だったため)。

サイズの問題は、リポジトリを新しいディレクトリに複製するのではなく、gitsトピックブランチと同様の手法を使用することで最も適切に処理されます。これにはいくつかのオプションがあります。最良の方法は、実際には bookmark extension を使用して、トピックのブランチではなくトピック「ブックマーク」を作成することです。名前付きブランチを使用することもできますが、永続的であり、クローンと一緒に移動できるというわずかな欠点があります(同僚と気の利いたTFS-Hgハイブリッドを共有したい場合)。ブックマークはあなたのリポジトリにローカルであり、コミットを指し、頭と一緒に移動します。それらは、Hgがリビジョンを期待している場所(マージ、更新など)で使用できるように実装されています。これらを使用して、TFSからの更新のみを取得し、トピック作業からマージする主要な「ブランチ」としてTFSブックマークを作成できます。トピックの作業はそれぞれ独自のブックマークを持ち、TFSにコミットすると削除できます。名前付きブランチを使用したい場合は、まったく同じテクニックを適用でき、便利です。

特に、TFSの「ブランチ」は実際には元のブランチからのすべてのファイルのコピーであるため、複数ブランチの問題はよりトリッキーです。つまり、TFSからブランチをプルするたびに、リポジトリはそれだけ大きくなります。これに対処する1つの可能な方法は、名前付きのHgブランチとブックマークの組み合わせを使用して、TFSブランチごとにブランチを作成し、それらのブランチから作業用のブックマークを作成することです。これらのシナリオにおける本当の頭痛の種は、これらすべてを通じて実際にTFSワークスペースを処理することです。ワークスペース内のマッピングを削除してかなり遠くまで行くことができますが、作業ディレクトリにマップし直すと、TFSがファイルを踏むことに注意する必要があります(これが実際にTF PowerToolsが役立つ場所です)。ブランチを切り替えながら作業スペースをアタッチしたままにしようとすると、見苦しくなります。 toolbeltで便利な2つのツールは、Hg purge extension とTF PowerToolsの "scorch"コマンドです。どちらも、バージョン管理されていないファイルを効果的に削除します(技術的には、 "scorch"でTFSとローカルの作業ディレクトリが一致していることを確認して、ファイルも更新できるようにします)。

しかし、私にとっては、このプロセスは非常に面倒でエラーが発生しやすくなりました。 git-tfs と一緒にgitを使用するように最近切り替えました。TFSワークスペースを管理し、その側に関連する多くの負担を取り除くからです。悲しいことに、どこにも「hg-tfs」が存在しないように見えるか、おそらく私はそれを選択したでしょう。

53
ckramer

Mercurialにこだわっていない場合は、私が使用してきたgit-tfsと呼ばれる甘いgit/tfs統合プロジェクトがあります。 git-svnとよく似ていますが、代わりにTFSからプッシュ/プルします。 http://github.com/spraints/git-tfs で確認してください。

9
jonfuller

@Eric、 lostechies への投稿が最も役に立ちました。 VS2010では、オプション/ diffおよび/ deletestftp onlineコマンドを使用して、TFSにチェックインされる変更および削除されたファイルを取得します。最初に(-workingから)ファイルが削除されたときにPushからエラーが発生しましたhg update
"削除できませんFileXyz:アクセスが拒否されました"。
MakeWritable.py拡張機能をインストールしましたが、これはファイルを開いたときにのみ機能し、削除されません。そこで、attribへの呼び出しを追加して、プロジェクト内のすべてのファイルから読み取り専用を削除し、後でそれを復元します(.hgフォルダーを除く)。また、/ diffオプションを追加して、READ-ONLY属性に依存する代わりに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

タスクバーにプッシュショートカットとプルショートカットを配置したので、TFSとの間のプッシュ/プルはシングルクリックです

5
JonN

Subversionブリッジでhgsubversionを使用している人がいることは知っています。私はそれがどれほどうまく機能したか知りません、そして私はTFSを使う必要がありませんでした。

私の知る限り、TFS-> Subversion Bridge-> hgsubversionを使用する以外に「よりネイティブな」ブリッジはありませんが、かなりうまく機能すると聞いています。 TFSに関する私の非常に限られた理解は、hgsubversionなどが本当にうまく機能するためには、その内部モデルがSubversionに十分に類似している必要があることを示唆しています。

3
durin42

MercurialとTFSリポジトリを同期するという目標を達成しようとする小さなツール、HgTfsを組み立てました。これは本当にシンプルで、クローン、プル、プッシュの3つのコマンドしかありません。これが私のBitbucketリポジトリです:

https://bitbucket.org/thepretender/hgtfs

ワークフローと使用シナリオを説明するブログ投稿もあります(実際、wikiページはこのブログエントリの一部にすぎません)。

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

コードはハッキーですが、仕事を成し遂げたようです。私は本当にフィードバックやフォークに感謝します:)

2
Oleg Tarasov

TFSとhgを操作するために使用してきたPowerShellスクリプトを次に示します。使用するには、TFSフォルダーにhgリポジトリを作成し(TFSからのファイルをそこにコミットする)、このリポジトリのクローンを作成して、新しいリポジトリで作業する必要があります。満足したら、「hgtfs.ps1 Push」を実行して、変更をMercurialリポジトリから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
Ben

DVCSとTFSを使用できるようにしたい場合、TFSに SVNBridge をインストールし、 Bazaar を使用するのが最善の方法だと思います。つまり、AFAIK SVNと簡単に統合できる唯一のDVCS。TFSがSVNのように見えるため、魔法のようにBazaar/TFS統合を取得できます。

2
Luxspes

私はそれを機能させるのに良い試みをしました。 GitとTFSを一緒に( link )でsvnbridgeを介して再生することはできましたが、srcbridgeを介してMercurialを動作させることができなかったため、終わりがありませんでした。私が個人的にgitではなくMercurialを好むので、それを機能させることができたら私に知らせてください(両方とも素晴らしいですが)

1
Richard Banks