1

2年前にいくつかのディレクトリがサブモジュールとして抽出されたリポジトリがあります。

git サブモジュールは頭痛の種になるため、サブモジュールとしての抽出を元に戻し、ディレクトリを親リポジトリに戻すことにしました。

ここで問題は、すべての履歴を保持しながら、これを行うための最良の方法は何かということです

サブモジュールをリモートとして追加してから、cherry-pickすべての変更を行うことを考えていました。しかし、そのためには、親リポジトリのルートではなく、現在のディレクトリに相対的なコミットのパスを処理しないように git に指示する必要があります。

それを行う方法cherry-pickや他の賢い方法はありませんか?

どうもありがとう!

4

1 に答える 1

1

git filter-branchman ページの例またはこの回答のわずかに変更されたバージョンを使用して、これを行うことができます。これは git v1.8.2 の man ページ バージョンです。

To move the whole tree into a subdirectory, or remove it from there:

git filter-branch --index-filter \
    'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
        git update-index --index-info &&
        mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

まず、各サブモジュールをリモートとして親リポジトリに追加し、次に各サブモジュールのmasterブランチをローカル追跡ブランチ (例: submoduleA-mastersubmoduleB-masterなど) としてチェックアウトします。ブランチは履歴を共有しないため、Git は警告をスローしますが、それ以外の場合は続行できます。サブモジュール ブランチの履歴を適切なサブディレクトリに書き直し、それを親の にマージしmasterます。最終的に、これらのサブディレクトリに対する一連のマージ コミットと、親リポジトリにまとまりのある単一の履歴が作成されます。

実際よりもはるかに複雑に聞こえます。万一の場合に備えて、必ずバックアップを作成してください。すべてをスクリプト化して、正しく理解できるまで試してみてください。各サブモジュールの大まかな実行順序は次のとおりです。

git remote add submodule submodule_remote
git checkout -b submodule-master submodule/master
git filter-branch ...        # With the index-filter described above.
                                 # Depending on length of history, this could
                                 # take quite a while to process/
git checkout master          # Get back on parent's master.

今、あなたは選択を迫られています。サブモジュールのすべての痕跡を削除するために親を書き直しますか? 後者の場合は、git バージョンに適したソリューションを使用して親リポジトリからサブモジュールを削除してから、 . 履歴からすべてのサブモジュールのコミットも消去したい場合は、親も同様に書き換えることができます。git merge submodule-mastergit filter-branch

私はかつて、35 の異なるリポジトリに対してこれを行いました。ヒントは次のとおりです。AWS での数時間のクラスター コンピューティングに 10 ドルを費やしてください。git filter-branch非常にRAMバウンドです。ラップトップでは 20 時間以内に実行できなかったことが、AWS クラスター コンピューティング インスタンスでは昼食中に完了する可能性があります。このような操作を行うには、美しくシンプルで安価な方法です。

最後に 1 つ。BSD を使用している場合、man ページsedの置換が失敗する可能性がかなりあります。\tJeff King のperl バージョンは、この問題を回避します。

git filter-branch --index-filter '
  git ls-files -s |
    perl -pe "s{\t\"?}{$&newsubdir/}" |
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
  mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD
于 2013-05-06T01:59:00.093 に答える