4

私の現在のプロジェクトでは、gitで興味深い問題に直面しています。

プロジェクトの開始以来、変更はクライアントのリモートサーバー上のSVNリポジトリに保存されていました。開発の進行中に、現在のバージョンを壊すことなく新しい機能をテストしやすくするために、ローカルのgitリポジトリを並行して使用するようになりました。悲しいことに、git-svnが機能しなかったため、私の生活が楽になりました。

これで、クライアントは別のサーバーに切り替え、このプロセスでSVNリポジトリをgitに移動しました(git2svnを使用)。

私はこれについて一般的に満足していますが、私は今2つの問題を抱えています

  1. より大きな機能に取り組んだので、7日間SVNにコミットしませんでした。私はローカル機能ブランチで作業し、それをローカルサーバーにバックアップしましたが、現在リモートgitリポジトリであるSVNコピーは、ローカルバージョンと比較して古くなっています。

  2. リモートリポジトリはgit2svnによって作成されているため、私自身のリポジトリとはまったく異なります(メッセージ:警告:リポジトリには共通のコミットがありません)。これにより、標準のマージが不可能になります。

今私の望ましい目標

  1. 両方のリポジトリをマージして、現在のバージョンを1つにチェックインし、元のバージョンにプッシュして再度機能させます。

  2. 両方のリポジトリの履歴を保持します(SVNからの古いものと私のgitからの過去7日間のもの)

私がこれまでに試したこと

私は(svnから)リモートgitのクローンを作成しようとし、ローカルリポジトリをそれにマージしました。「両方のバージョンで変更」との競合が153回発生しました。「それら」(つまり、私の最新の開発)を受け入れると、ファイルの履歴が失われます(並列gitリポジトリでの初期化から始まります)。

私の考えは、過去7日間のコミットごとにパッチを作成し、対応するコミットメッセージ(つまり「手動マージ」)を使用してこれを新しいリポジトリにコミットできるということです。これを行うためのスクリプトを書く前に、それを行うための組み込みの方法があるかどうかを尋ねたかったのです。

前もって感謝します!

更新:私は多くの解決策を試しましたが、それらのすべてが私に失敗しました。基本的な問題は、共通のコミットが1つではなく、ツリー構造が同じである2つのブランチがあることです。これにより、「両方のブランチに追加」のようなマージの競合が発生します。これは、gitがmyFile.txt" andmyFile.txtが同じであり、マージできることを認識していないためです。代わりに、その週に変更した150個のファイルを手動でマージする必要があります。私にはできませんし、しません。

これまでの私の最善のアプローチは、変更のパッチを作成し、それを「新しい」リポジトリに適用することでした。しかし、ツリーの不一致が原因でまだ失敗しないパッチを作成することはできませんでした。パッチ情報を開始するための正しいコミットをまだ見つけていません。

解像度

TL; DR:ありません。あなたはより小さな悪から選ぶことができます。

  1. ここで説明するマージ方法を使用できますが、SVNの個々のファイル履歴がside-gitのファイル履歴に置き換えられます(つまり、他のリポジトリが2である場合、このファイルが3か月前に変更された理由を検索できません)生後数ヶ月)。しかし、良い面としては、変更がgitlogを介してグローバルヒストリーにマージされます。

  2. 私が最終的に得たもう1つのオプションは、「新しい」(別名SVN)リポジトリ内のすべてのファイルをコピーして、gitリポジトリの現在のステータスに置き換えることでした(ただし、 -folderと生成されたすべてのファイルcp -vruは省略します)。.gitこれにより、1週間分の歴史を失うことができましたが、それでも私が好むプロジェクトの開始まで過去を振り返ることができました。この損失の苦痛を少し和らげるために、コミットメッセージで自分の行動の詳細な要約を作成しました。これを使用git log --date=short --pretty="format:%cd - %s" --name-statusすると、少なくともこのエントリに戻って、説明付きのメッセージを見ることができます。しかしもちろん、これはファイルの削除には機能せず、どの変更が実際にbiiiigコミットメッセージのどの部分に属しているかを知ることはできません。

4

2 に答える 2

3

私はこれを私のリポジトリでテストしました。クライアントの新しいリポジトリを表す新しいクローンを作成しました。次に、古いバージョンのコンテンツを新しいフォルダーにコピーし、その中のリポジトリを初期化しました。コンテンツを追加し、いくつかのコミットを行いました。

そうすれば、共通のコミットがない2つのリポジトリがありました。

ここで、新しいリポジトリに、自分のコピー(以下mine)をリモートとして追加し、その内容をフェッチしました。それから私は私のマスターへの新しいブランチをチェックアウトしました:

git checkout -b new mine/master

そのため、このブランチからアクセス可能な個別のリポジトリのすべての履歴がありました。次に、再帰的なマージ戦略を使用して、更新されたマスターをブランチにマージしましたが、競合に対する(新しい)変更を優先します。

git merge master -s recursive -Xours

これにより、すべてが自動的にマージされ、競合が発生した場合は、バージョンを使用するだけで自動的に解決され、マスターの変更が効果的に破棄されます。

したがって、最終的にはブランチがマージされ、両方のリポジトリからのすべての履歴がまだそこにあるはずです。

于 2012-11-08T12:40:21.693 に答える
1

私が正しく理解していれば、次のような状況になります。

remote repo:
A - B

your repo
C - D - E - F

ここで、コミットAは実際にはCと同じであり、BをDにコミットします(含まれているファイルに関して)。私は、うまくいくかもしれないのは、次のようなことをすることによって、最新のリモートコミットに基づいて作業を単純にリベースすることだと信じています

git rebase --onto B D

これにより、コミットがDからHEAD(Fなど)に移動し、それらをパッチとしてBに適用する必要があります。その結果、次のようになります。

A - B - E' - F'

これは、ローカルの変更と同じである必要があり、リモートリポジトリに快適にプッシュできます。

于 2012-11-06T13:19:18.600 に答える