2

作成したばかりのgit-to-svnセットアップで、ここで終わりです。2つのリモートリポジトリを使用してリポジトリをセットアップしました。1つはsvnベースで、もう1つはリモートgitです。

svn-remote.svn.url=https://subversion.acme.com/svn/sales/portal/trunk
svn-remote.svn.fetch=:refs/remotes/git-svn
remote.origin.url=mottinger@git.tkknow.com:/gitroot/acme-gtm-2-0.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

これを設定すると、次のようにコミットをgitリポジトリからsvnリポジトリに移動できました。

git fetch origin
git rebase origin/master (linearizes commits to svn)

git svn rebase
git svn dcommit

競合をどのように処理するかをテストすることを決定するまで、すべてが順調でした。foo.datファイルを作成し、svn側からその中に行を追加し、git側に対応するファイルを作成しました。この行には、gitからのものであるという効果を示す行が含まれています。実行git fetch origingit rebase origin/masterて、foo.datファイルを停止しました。それは問題ありませんでしたが、実行しようとするgit svn rebaseと競合が発生しました。完全に期待されているので、競合を編集してsvnrebase--continueを使用する手順を実行します。しかし、その後、混乱が始まります。実行しようとした後git rebase origin/masterリポジトリから他の変更をプルダウンするために、同じfoo.datファイルで競合します。svnの競合を解決すると、gitで失敗し、その逆も同様の状態になりました。すべての中で最も苛立たしいことは、この混乱を元に戻すためにリポジトリを元の状態に戻す方法を見つけることができないようです。今のところ、レポを完全に吹き飛ばしてやり直すことができるという贅沢がありますが、将来的には開発者がこれを使用するので、このような状態になった場合は、どうやって抜け出すかを本当に知りたいです。何が起こっているのか、そして一定のマージを終了する方法についてのヒントは大歓迎です。

ありがとう!

4

1 に答える 1

4

これらの競合はgit-svnとは何の関係もありません。

remote1とremote2の2つのリモートがあり、これらのリモートの履歴が異なる場合、リベース操作は常に最初のリモートの履歴を別のリモートの上に書き換えます。

マスターブランチによって参照される単一のコミットAがあるとします。

$ git log master
* commit A
Initial commit

そして、異なる歴史を持ついくつかのリモコン:

$ git log remote1/master
* commit R1
Added conflict.txt at remote1
* commit A
Initial commit

$ git log remote2/master
* commit R2
Added conflict.txt at remote2
* commit A
Initial commit

ここで、ローカル履歴を次のようにリベースします。

$ git rebase remote1/master
$ git log master
* commit R1
Added conflict.txt at remote1
* commit A
Initial commit

ここで、remote2 / masterの上にローカル履歴をリベースしようとし、競合を取得して解決します。

$ git rebase remote2/master
$ git log master
* commit R1
Added conflict.txt at remote1
* commit R2
Added conflict.txt at remote2
* commit A
Initial commit

気がついた?リベース操作は、コミットR1をR2の上に置きます。ご想像のとおり、remote1 / masterに基づいて特定の履歴をリベースすると、コミットR1とR2がスワップされ、まったく同じ競合が発生します。

それを修正する方法は?さて、あなたは両方のリモコンの履歴を同じにする必要があります。これを行う最も安全な方法は、コミットR1とR2をマージし、結果のマージコミットをremote1とremote2の両方にプッシュすることです。

ここでgit-svnに戻ります。あなたの場合、git-svnは実行時に常にローカル履歴を書き換えるため、分岐した履歴のマージは機能しませんgit svn dcommit。代わりに、次のことを行う必要があります。

  1. Gitリポジトリからコミットをフェッチしてリベースします。

     $ git fetch origin
     $ git rebase origin/master (linearizes commits to svn)
    
  2. 変更をSVNリポジトリに送信します。

     $ git svn rebase
     $ git svn dcommit
    
  3. SVNからフェッチされたコミットを元にプッシュバックします。

     $ git push -f origin master:master
    

3番目のステップは非常に危険であり、履歴が失われる可能性があります。したがって、これを行うことはお勧めしません—git-svnはそのようなワークフローをサポートしていません。

代わりに、SubGitを試すことができます。SubGitは、SVNおよびGitリポジトリ用の双方向サーバーサイドミラーツールです。

Subversionリポジトリへのローカルアクセスがある場合は、それにSubGitをインストールできます。

$ subgit configure $SVN_REPOS
# Adjust $SVN_REPOS/conf/subgit.conf to specify your branches and tags
# Adjust $SVN_REPOS/conf/authors.txt to specify git & svn authors mapping
$ subgit install $SVN_REPOS
...
$ INSTALLATION SUCCESSFUL

その結果、元のSVNリポジトリと自動的に同期される変換されたGitリポジトリを取得します。

SVNリポジトリへのローカルアクセスがない場合は、まもなく早期アクセス段階に入るSubGit2.0の使用を検討してください。SubGit 2.0を使用すると、GitリポジトリとリモートSVNリポジトリの間に双方向ミラーを設定できます。

SubGitは商用製品です。オープンソースおよびアカデミックプロジェクト、および最大10人のコミッターがいるプロジェクトは無料です。

詳細については、SubGitのドキュメントgit-svnの比較ページを参照してください。

完全開示:私はSubGit開発者の1人です。

于 2012-10-03T01:01:38.110 に答える