1

以前にも同様の質問をしたことがありますが、この件についてかなり徹底的な分析を行った結果、これgit filter-branchが私が探している主力製品であるという結論に達しました。それか、.gitそれ自体で汚れた作業を行うシェル スクリプトのいずれかです (とにかく、git はその内臓をインターフェイスの一部として公開しているため)。

ビルド スクリプトとビルド構成定義を含むプロジェクト ディレクトリがあります。さらに重要なことはsrc、プロジェクトのあらゆる種類のソース コードを含むフォルダーが含まれており、git リポジトリであることです。

含まれているソース コード フォルダーだけでなく、プロジェクト フォルダー全体を git リポジトリにする必要があることに気付きましたが、ソース コード開発の履歴を保持したいと考えています。実際、履歴が完全に書き直されるmain.c ことを望みますsrc/main.c. 次に、親フォルダー (ビルド スクリプトがある場所) からファイルを移動し、リポジトリでチェックするだけです。

サブツリーのマージや git サブモジュールに煩わされたり、リポジトリが変更された後に何かをマージしたりリセットしたりする必要はありません。私は現在、gits の内部構造についてかなりの知識を持っています。コミットは、ファイル名とペアになったブロブを参照するツリーを参照します。

この知識があれば、すべてのパスにプレフィックスを付けて、履歴を書き換えることができるはずだと思いますsrc/

私は余分な作業をしたくないだけです。それfilter-branchが進むべき道のようですが、使用後の例と必要なハウスキーピングに混乱します。「元の参照」?もう1つの問題は、「裸の」リポジトリで完全に問題がないことです。作業ツリーは必要ありません。また、インデックスが必要な理由もまったくわかりません。

4

1 に答える 1

3

あなたが考えるほど単純ではありません。現在、2 つのリポジトリがあり、それぞれに独自の履歴があります。
各コミットには明確に定義された親があります。

時系列的に正しい履歴を 1 つ取得するには、多くのコミットの親を変更する必要があります。

短いサンプルでこれを示します。

リポジトリの「構成」:

A <- C <- E

リポジトリ「src」

B <- D <- F

コミット B が A の後に発生し、C が B の後に発生したと仮定して、次の結果を得たいとします。

A <- B' <- C' <- D' <- E' <- F'

これを実現するには、 の親を に変更する必要がありB'ますA。の親をからなどC'に変更する必要があります。AB'

それは些細なことではありません。しかし、可能です。

構成リポジトリが「/usr/git/config」にあり、src リポジトリが「/usr/git/config/src」にあるとします。

まず、「src」サブフォルダー内のすべてのファイルを含むように「src」リポジトリーを準備する必要があります。

  1. 「/usr/git/config/src」への CD
  2. このモンスターを実行します。

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

残りは "config" リポジトリ内で行われるため、CD を "/usr/git/config" に移動します。

  1. 「src」リポジトリをリモートとして追加します。git remote add src /usr/git/config/src
  2. 「src」リポジトリのコミットを取得します。git fetch src
  3. 「src/master」からのコミットをローカルの「master」とマージします。git merge src/master master
  4. 2 つのリポジトリの最初のコミットを確認します。git rev-list --max-parents=0 --pretty HEAD
  5. 2つのうち古い方のコミットハッシュに注意してください
  6. 完全なリポジトリのリベースを実行して、マージを取り除きます。git rebase -f <hash from step 5>
  7. リモコンを取り外します:git remote remove src
  8. フォルダー「/usr/git/config/src/src」および「/usr/git/config/src/.git」を削除します
  9. .gitignore を更新して、"src" フォルダーを無視しないようにします。

注意:
これは、両方のリポジトリに master ブランチしかないことを前提としています。

ああ、これを行う前にバックアップを作成してください。それぞれ2つのコミットを持つ小さなテストリポジトリでのみテストしました...


src サブフォルダーにのみリポジトリがある場合は、より簡単です。次を実行するだけです。

  1. 「/usr/git/config/src」への CD
  2. 上からモンスターを処刑する
  3. 「/usr/git/config/src」の名前を「/usr/git/config/src_tmp」に変更します
  4. 「.git」リポジトリを含む「/usr/git/config/src_tmp」の内容全体を「/usr/git/config」に移動します
  5. 空になった「/usr/git/config/src_tmp」を削除します
于 2013-02-14T13:42:56.143 に答える