2017-05-19 11 views
0

私はsvnリポジトリに3年以上の履歴を持つプロジェクトを持っています。これはgitに移行されましたが、これをやった人は、最後のバージョンをとり、これらの3年間の歴史をすべて破棄します。ルートコミット親を別のコミット(2つの独立したgitリポジトリを接続する)を指すように変更します

プロジェクトは過去3〜4ヶ月の履歴を1つのリポジトリに持ち、残りの3年間のsvn履歴を新しいgitリポジトリにインポートしました。

2番目のリポジトリのルートコミットを最初のコミットに最後にコミットする方法はありますか?

* 2017-04-21 - last commit on master 
    | 
    * 2017-03-20 - merge branch Y into master 
    |\ 
    | * 2017-03-19 - commit on branch Y 
    | | 
    * | 2017-03-18 - merge branch X into master 
/| * 2017-02-17 - commit on another new branch Y 
* |/ 2017-02-16 - commit on branch X 
| * 2017-02-15 - commit on master branch 
* | 2017-01-14 - commit on new branch X 
\| 
    * 2017-01-13 - first commit on new repository 
    | 
    * 2017-01-12 - init new git project with the last version of the code in svn repository 
    . 
    . 
There is no relationship between the two different repositories yet, this is what I wanna 
do. I want to connect the root commit of 2nd repository with the last commit of the first 
one. 
    . 
    . 
    * 2017-01-09 - commit 
    | 
    * 2017-01-08 - commit 
    | 
    * 2017-01-07 - merge 
/| 
* | 2016-01-06 - 2nd commit the other branch 
| * 2016-01-05 - commit on trunk 
* | 2016-01-04 - commit on new branch 
\| 
    * 2015-01-03 - first commit 
    | 
    * 2015-01-02 - beggining of the project 

更新:

それはこのようなものである

私はちょうど私がgit rebaseを行う必要があることを学ぶが、どのように? SHA-1コードのようなコミット日付を考えてみましょう...答えは--parent-filterののオプションで、git rebaseではなくgit filter-branchを使用していました。

アップデート2:

PS D:\git\rebase-test\rep2cc> git filter-branch --parent-filter 'test $GIT_COMMIT = 443aec8880e898710796a1c4fb4decea1ca5ff66 && echo "-p 98e2b95e07b84ad1e40c3231e66840ea910e9d66" || cat' HEAD 
fatal: ambiguous argument '98e2b95e07b84ad1e40c3231e66840ea910e9d66 || cat': unknown revision or path not in the working tree. 
Use '--' to separate paths from revisions, like this: 
'git <command> [<revision>...] -- [<file>...]' 

アップデート3:私はコマンドgit filter-branch --parent-filter 'test $GIT_COMMIT = 443aec8880e898710796a1c4fb4decea1ca5ff66 && echo "-p 98e2b95e07b84ad1e40c3231e66840ea910e9d66" || cat' HEADを試み、それが動作しませんでした

これは、WindowsのCMD上で動作しませんでしたかPowerShellは、WindowsのGit Bashで動作しました。

+2

さて、同じリポジトリ内で両方をフェッチしてから別のものの上に1つの履歴をリベースすると考えましたか?これはもちろん、リベースしている履歴のすべてのコミットを書き換えます。 –

+1

ラッセはそれを正しく得た。ちょうどsvnでクローンされた新しいリポジトリをセットアップし、この破棄されたリポジトリをリモートに追加し、フェッチし、チェリーピックアップして、svnから複製した後にgitで行われた履歴を正しくクローンされたsvnリポジトリに入れます。 – eftshift0

+0

私はgitで新しいです、私はちょうど私が探していた魔法の単語が 'rebase'であることを学ぶ – lmcarreiro

答えて

2

最初にまず最初に、利用可能なすべての履歴を持つ単一のレポが必要です。

最近の履歴でリポジトリのクローンを作成します。古い履歴を含むレポをリモートとして追加します。私はこのクローンを "ミラー"にすることをお勧めします。そして、あなたは原点レポをこれで置き換えることで終わります。しかし、代わりに--mirrorをオフにしておくと、すべての参照が元に戻ります(使用するアプローチに応じて強制的に押すことも可能です)。

git clone --mirror url/of/current/repo 
cd repo 
git remote add history url/of/historical/repo 
git fetch history 

次は、スプライシングの履歴を把握するだけです。これを説明する用語はちょっとあいまいだと思います...あなたが望むのは、両方の履歴がコミットしている最新のSVNリビジョンに対応する2つのコミットを見つけることです。たとえば、あなたのSVNのレポは、今、あなたはAは、バージョン1を表し、Bはバージョンを表すバージョン2、CC'バージョン3を表し、そしてDD'を表し

Recent-History Repo 

C --- D --- E --- F <--(master) 

Old-History Repo 

A --- B --- C' --- D' 

を持っていたバージョン1、2、3、および4を含んでい4. EおよびFは、元の移行後に作成された作業です。したがって、親がD(この例ではE)のコミットをD'にスプライスしたいとします。

ここでは、賛否両論の2つのアプローチが考えられます。あなたは(あなたが彼らのすべてがすべての未処理の仕事があることに同意した時間を手配意味新しいレポに、すべての開発者のカットオーバーを調整することができるかどうIMO最善の方法最近の履歴に

を書き換え

プッシュしてクローンを破棄した後、変換を行い、再クローン化する)は、最近の履歴を古い履歴に(効果的に)再分類することです。

本当にただ単一の分岐がある場合、あなたは文字通り(DD'は、コミットのSHA IDに置き換えられます)

git rebase --onto D' D master 

リベース使用することができます。

最近の履歴では、いくつかの分岐やマージがある可能性があります。その場合、リベース操作は非常に迅速に問題になるであろう。一方、DにはD'と同じツリーがあることを利用することができます。そのため、リベースとリ親は多かれ少なかれ同等です。

git filter-branch--parent-filterを使用して書き換えを行うことができます。 https://git-scm.com/docs/git-filter-branchでのドキュメントの例をもとに、あなたは(DD'は、コミットのSHA IDに置き換えて再び)

git filter-branch --parent-filter 'test $GIT_COMMIT = D && echo "-p D'" || cat' HEAD 

ような何かをするだろう。

これは、クリーンアップする必要がある "バックアップ"の参照を作成します。最後に、あなたはそれはFは、ハードカットオーバー(多かれ少なかれ)の必要性を作成しF'に置き換えたという事実だ

A --- B --- C' --- D' --- E' --- F' <--(master) 

取得します。

ステップ1でミラークローンを元に戻した場合は、reflogのワイプ、リモートのドロップ、およびgcの実行を検討することができます。これはすぐに使用できる新しい起点レポです。

通常のクローンを作成した場合は、push -fが原点へのすべての参照を必要とします。これは原点レポに混乱を来たす可能性があります。使用

を「交換がコミット」他のオプションは、ハードカットオーバーを作成しませんが、それは永遠に対処するために、小さな頭痛であなたを残します。 git replaceを使用できます。ログ出力または何を生成するときにGitがDを見つけた場合、あなたの組み合わせレポデフォルトで

git replace `D` `D'` 

では、、、それは出力にD'(とその歴史)を代用します。

既知の不具合がいくつかあります。不明な不具合があるかもしれません。そして、デフォルトでは、これをすべて動作させる「置換リファレンス」は共有されないので、意図的にプッシュして取り出さなければなりません。

+0

私はgit replaceを試しました、それは私が望むものではありません。そして私は歴史上多くの支店や合併をしているので、あなたが言ったように、リベース操作は問題になりました。 – lmcarreiro

+0

この3番目のオプションは、私は理解していない... 'P'と' P''は何ですか?そしてコマンド 'git filter-branch --parent-filter 'test $ GIT_COMMIT = D && echo" -p D' "|| cat 'HEAD'はウィンドウズで動作しますか? – lmcarreiro

+0

申し訳ありませんが、「P」と「P」は「D」と「D」であったはずです。私は更新しました。コマンドは 'git bash'シェルのウィンドウで動作します。 'D'と' D''を適切なコミットリファレンス(SHA idsなど)で置き換えることを忘れないでください。 –

関連する問題