初めに
みなさんはサブモジュールをご存知でしょうか?
Gitでプロジェクトを管理している場合、基本的には1つのリポジトリ内で全てを管理するケースが一般的です。しかし、オープンソースソフトウェア(OSS)や外部のライブラリを利用する場合、特定のディレクトリを別のリポジトリとして切り離して管理する「サブモジュール」という機能を活用することがあります。
サブモジュールを利用すると、外部プロジェクトの依存関係を管理しやすくなる一方で、運用や統合の際にいくつかの課題が発生することもあります。例えば、複数のリポジトリを扱うことで管理が煩雑になり、コンフリクトが発生しやすいといった問題が挙げられます。
この記事では、サブモジュールを利用していたが後ほど辞めたいと行った場合に「サブモジュールを履歴を保持したまま親リポジトリに統合する」 方法の具体的な手順を説明します。
それでは、手順を詳しく見ていきましょう。
実行手順
1. サブモジュールの削除
まず、既存のサブモジュールを削除します。以下のコマンドを順に実行します。
git submodule deinit -f <サブモジュール名>
git rm -f <サブモジュール名>
rm -rf .git/modules/<サブモジュール名>
例: サブモジュールが submodule_repo という名前の場合
git submodule deinit -f submodule_repo
git rm -f submodule_repo
rm -rf .git/modules/submodule_repo
これにより、サブモジュールの設定がリポジトリから完全に削除されます。
2. サブモジュールのリモートリポジトリを親リポジトリに追加
次に、サブモジュールのリモートリポジトリを親リポジトリにリモートとして追加します。
git remote add <リモート名> <サブモジュールのリポジトリURL>
git fetch <リモート名>
例:サブモジュールが submodule_repo という名前の場合
git remote add submodule_repo_remote git@github.com:example-org/submodule_repo.git
git fetch submodule_repo_remote
3. サブモジュールで取り込みたいブランチをチェックアウト
親リポジトリ内で、サブモジュールで取り込みたいブランチに一時的に切り替えます。
git switch --track <リモート名>/<ブランチ名>
例:サブモジュールが submodule_repo という名前の場合
git switch --track submodule_repo_remote/feature-branch
4. 親リポジトリのマージ対象ブランチに切り替える
マージを行う親リポジトリのブランチに切り替えます。適切なブランチに切り替えてください。
git switch <親リポジトリのブランチ名>
5. サブモジュールの内容を親リポジトリにマージする
以下の手順でマージを実行します。
ブランチ間の関係がないため、特殊なマージオプションを使用します。
git merge --strategy=ours --no-commit --allow-unrelated-histories <サブモジュールブランチ名>
サブモジュールの内容を親リポジトリに展開します。
git read-tree --prefix=<サブモジュールディレクトリ名>/ -u <サブモジュールブランチ名>
最後にコミットを作成します。
git commit -m "サブモジュールを親リポジトリに取り込み"
例:
git merge --strategy=ours --no-commit --allow-unrelated-histories feature-branch
git read-tree --prefix=submodule_repo/ -u feature-branch
git commit -m "サブモジュールを親リポジトリに取り込み"
これで、サブモジュールが親リポジトリに統合され、履歴が保持された状態で取り込みが完了します。
最後に
いかがでしたでしょうか?
あまり似たような状況の方はいないと思いますが、備忘録として記しておきます。
これが皆様の助けになれば幸いです。
参考資料