ファイル履歴を壊さずに2つのGitリポジトリをマージする 質問する

ファイル履歴を壊さずに2つのGitリポジトリをマージする 質問する

2つのGitリポジトリを新しい3番目のリポジトリにマージする必要があります。サブツリーマージを使用してこれを行う方法については多くの説明を見つけました(たとえばJakub Narębski の回答の上2 つの Git リポジトリをマージするにはどうすればよいですか?) を実行し、その手順に従うと、ほとんどは機能しますが、サブツリー マージをコミットすると、古いリポジトリのすべてのファイルが新しく追加されたファイルとして記録されます。 を実行すると、古いリポジトリからのコミット履歴を確認できますgit logが、git log <file>そのファイルに対してサブツリー マージのコミットのみが表示されます。上記の回答のコメントから判断すると、この問題に気付いているのは私だけではありませんが、公開されている解決策は見つかりませんでした。

リポジトリをマージし、個々のファイル履歴をそのまま残す方法はありますか?

ベストアンサー1

外部依存関係を管理するのではなく、単に 2 つのリポジトリを結合して最初からその状態だったように見せようとしている場合、答えははるかに簡単であることがわかりました。古いリポジトリにリモートを追加し、新しいマスターにマージし、ファイルとフォルダーをサブディレクトリに移動し、移動をコミットし、すべての追加リポジトリに対してこれを繰り返すだけです。サブモジュール、サブツリーのマージ、およびファンシー リベースは、少し異なる問題を解決することを目的としており、私がやろうとしていたことには適していません。

2 つのリポジトリを結合する Powershell スクリプトの例を次に示します。

# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init

# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
git commit --allow-empty -m "Initial dummy commit"

# Add a remote for and fetch the old repo
# (the '--fetch' (or '-f') option will make git immediately fetch commits to the local repo after adding the remote)
git remote add --fetch old_a <OldA repo URL>

# Merge the files from old_a/master into new/master
git merge old_a/master --allow-unrelated-histories

# Move the old_a repo files and folders into a subdirectory so they don't collide with the other repo coming later
mkdir old_a
dir -exclude old_a | foreach { git mv $_.Name old_a }

# Commit the move
git commit -m "Move old_a files into subdir"

# Do the same thing for old_b
git remote add -f old_b <OldB repo URL>
git merge old_b/master --allow-unrelated-histories
mkdir old_b
dir –exclude old_a,old_b | foreach { git mv $_.Name old_b }
git commit -m "Move old_b files into subdir"

もちろん、代わりに old_b を old_a にマージすることもできます (これが新しい結合リポジトリになります)。その場合は、スクリプトを適宜変更してください。

進行中の機能ブランチも移行したい場合は、次のようにします。

# Bring over a feature branch from one of the old repos
git checkout -b feature-in-progress
git merge -s recursive -Xsubtree=old_a old_a/feature-in-progress

これは、プロセスの中で唯一わかりにくい部分です。これはサブツリーのマージではなく、ターゲットの名前を変更したことを Git に伝え、Git がすべてを正しく整列させるのに役立つ、通常の再帰マージの引数です。

もう少し詳しい説明を書きましたここ

おすすめ記事