Git サブモジュールのサブモジュールを解除し、すべてのコードをコア リポジトリに戻すためのベスト プラクティスは何ですか?
13 に答える
サブモジュールコードをメインリポジトリに配置するだけの場合は、サブモジュールを削除して、ファイルをメインリポジトリに再度追加する必要があります。
git rm --cached submodule_path # delete reference to submodule HEAD (no trailing slash)
git rm .gitmodules # if you have more than one submodules,
# you need to edit this file instead of deleting!
rm -rf submodule_path/.git # make sure you have backup!!
git add submodule_path # will add files instead of commit reference
git commit -m "remove submodule"
サブモジュールの履歴も保持したい場合は、小さなトリックを実行できます。サブモジュールをメインリポジトリに「マージ」して、サブモジュールファイルが現在にあることを除いて、結果が以前と同じになるようにします。メインリポジトリ。
メインモジュールでは、次のことを行う必要があります。
# Fetch the submodule commits into the main repository
git remote add submodule_origin git://url/to/submodule/origin
git fetch submodule_origin
# Start a fake merge (won't change any files, won't commit anything)
git merge -s ours --no-commit submodule_origin/master
# Do the same as in the first solution
git rm --cached submodule_path # delete reference to submodule HEAD
git rm .gitmodules # if you have more than one submodules,
# you need to edit this file instead of deleting!
rm -rf submodule_path/.git # make sure you have backup!!
git add submodule_path # will add files instead of commit reference
# Commit and cleanup
git commit -m "removed submodule"
git remote rm submodule_origin
結果のリポジトリは少し奇妙に見えます。複数の初期コミットがあります。ただし、Gitに問題は発生しません。
この2番目のソリューションの大きな利点は、元々サブモジュールにあったファイルをgit blame
引き続き実行できることです。git log
実際、ここで行われるのは、1つのリポジトリ内の多くのファイルの名前を変更するだけであり、Gitはこれを自動的に検出する必要があります。それでも問題が解決しない場合は、名前の変更とコピーの検出を改善するgit log
いくつかのオプション(、、、など)を試して--follow
ください-M
。-C
git 1.8.5 (2013 年 11 月)以降(サブモジュールの履歴を保持せずに):
mv yoursubmodule yoursubmodule_tmp
git submodule deinit yourSubmodule
git rm yourSubmodule
mv yoursubmodule_tmp yoursubmodule
git add yoursubmodule
それは:
- サブモジュール ( 、したがって最初の ) の登録解除とアンロード(つまり、 のコンテンツの削除)、
deinit
mv
- をクリーンアップ
.gitmodules
します (rm
), - 親リポジトリのインデックスにあるそのサブモジュール SHA1 を表す特別なエントリを削除します (
rm
)。
サブモジュールの削除が完了したら (deinit
およびgit rm
)、フォルダーの名前を元の名前に戻し、通常のフォルダーとして git リポジトリに追加できます。
注: サブモジュールが古い Git (< 1.8) によって作成された場合、 Simon Eastがコメントした.git
ように、サブモジュール自体内のネストされたフォルダーを削除する必要がある場合があります。
サブモジュールの履歴を保持する必要がある場合は、を使用するjearsの回答git filter-branch
を参照してください。
git rm --cached the_submodule_path
- ファイルからサブモジュール セクションを削除する
.gitmodules
か、それが唯一のサブモジュールである場合は、ファイルを削除します。 - 「削除されたサブモジュール xyz」をコミットします
git add the_submodule_path
- 別のコミット「xyzのコードベースを追加」
私はまだ簡単な方法を見つけていません。git commit -a
好みの問題で、3〜5を1つのステップに圧縮できます。
ここにはたくさんの答えがありますが、それらはすべて複雑すぎるようで、あなたが望むことをしない可能性があります. 多くの人が自分の歴史を残したいと思っていると確信しています。
この例では、メイン リポジトリは にgit@site.com:main/main.git
なり、サブモジュール リポジトリは になりますgit@site.com:main/child.git
。これは、サブモジュールが親リポジトリのルート ディレクトリにあることを前提としています。必要に応じて指示を調整します。
親リポジトリのクローンを作成し、古いサブモジュールを削除することから始めます。
git clone git@site.com:main/main.git
git submodule deinit child
git rm child
git add --all
git commit -m "remove child submodule"
ここで、子リポジトリをメイン リポジトリの上流に追加します。
git remote add upstream git@site.com:main/child.git
git fetch upstream
git checkout -b merge-prep upstream/master
次のステップでは、ファイル パスを変更することで簡単に場所を変更できますが、merge-prep ブランチのファイルをサブモジュールが上にあったのと同じ場所に移動することを前提としています。
mkdir child
.git フォルダーを除くすべてのフォルダーとファイルを子フォルダーに移動します。
git add --all
git commit -m "merge prep"
これで、ファイルを master ブランチに簡単にマージできます。
git checkout master
git merge merge-prep # --allow-unrelated-histories merge-prep flag may be required
実行する前に周りを見回して、すべてが適切に見えることを確認してくださいgit push
ここで覚えておかなければならないことの 1 つは、デフォルトでは git log は移動したファイルを追跡しませんが、実行git log --follow filename
するとファイルの完全な履歴を確認できるということです。
たまたま、2つのプロジェクト用に2つのリポジトリを作成しましたが、それらを分離しても意味がないほど結合されていたため、それらをマージしました。
最初にそれぞれのマスターブランチをマージする方法を示し、次にこれを取得したすべてのブランチに拡張する方法を説明します。これがお役に立てば幸いです。
サブモジュールを機能させ、それを所定の場所にあるディレクトリに変換したい場合は、次のことができます。
git clone project_uri project_name
ここでは、クリーンクローンを実行して機能させます。このプロセスでは、サブモジュールを初期化または更新する必要がないため、スキップしてください。
cd project_name
vim .gitmodules
.gitmodules
お気に入りのエディター(またはVim)で編集して、置き換える予定のサブモジュールを削除します。削除する必要のある行は、次のようになります。
[submodule "lib/asi-http-request"]
path = lib/asi-http-request
url = https://github.com/pokeb/asi-http-request.git
ファイルを保存した後、
git rm --cached directory_of_submodule
git commit -am "Removed submodule_name as submodule"
rm -rf directory_of_submodule
ここでは、サブモジュールの関係を完全に削除して、他のリポジトリをプロジェクトにインプレースで移動できるようにします。
git remote add -f submodule_origin submodule_uri
git fetch submodel_origin/master
ここでは、マージするサブモジュールリポジトリをフェッチします。
git merge -s ours --no-commit submodule_origin/master
ここでは、2つのリポジトリのマージ操作を開始しますが、コミットする前に停止します。
git read-tree --prefix=directory_of_submodule/ -u submodule_origin/master
ここでは、サブモジュール内のマスターのコンテンツを、ディレクトリ名の前に付ける前のディレクトリに送信します。
git commit -am "submodule_name is now part of main project"
ここで、マージの変更をコミットする手順を完了します。
これが完了したら、プッシュして、マージする他のブランチからやり直すことができます。変更を受け取るリポジトリ内のブランチをチェックアウトし、マージおよびツリーの読み取り操作でブランチを変更します。
私が見つけたこれに対する最良の答えはここにあります:
http://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html
この記事では、手順を非常によく説明しています。
これは、@gyimの回答のわずかに改善されたバージョン(IMHO)です。彼はメインの作業コピーに一連の危険な変更を加えています。個別のクローンを操作して、最後にそれらをマージする方がはるかに簡単だと思います。
別のディレクトリで (間違いを簡単にクリーンアップして再試行できるようにするため)、トップ リポジトリとサブリポジトリの両方をチェックアウトします。
git clone ../main_repo main.tmp
git clone ../main_repo/sub_repo sub.tmp
最初にサブレポを編集して、すべてのファイルを目的のサブディレクトリに移動します
cd sub.tmp
mkdir sub_repo_path
git mv `ls | grep -v sub_repo_path` sub_repo_path/
git commit -m "Moved entire subrepo into sub_repo_path"
HEAD をメモする
SUBREPO_HEAD=`git reflog | awk '{ print $1; exit; }'`
メインリポジトリからサブリポジトリを削除します
cd ../main.tmp
rmdir sub_repo_path
vi .gitmodules # remove config for submodule
git add -A
git commit -m "Removed submodule sub_repo_path in preparation for merge"
そして最後に、それらをマージするだけです
git fetch ../sub.tmp
# remove --allow-unrelated-histories if using git older than 2.9.0
git merge --allow-unrelated-histories $SUBREPO_HEAD
そして完了!安全に魔法をかけずに。
ときのために
git rm [-r] --cached submodule_path
戻り値
fatal: pathspec 'emr/normalizers/' did not match any files
コンテキスト:rm -r .git*
追加したばかりのメインプロジェクトでサブモジュールを解除する必要があることに気付く前に、サブモジュールフォルダーで行いました。すべてではなく一部をサブモジュール化すると、上記のエラーが発生しました。とにかく、実行して修正しました(もちろん、 の後rm -r .git*
)
mv submodule_path submodule_path.temp
git add -A .
git commit -m "De-submodulization phase 1/2"
mv submodule_path.temp submodule_path
git add -A .
git commit -m "De-submodulization phase 2/2"
これは履歴を保持しないことに注意してください。
サブモジュールからローカルコミットデータを(また?)フェッチする方が便利だと思いました。そうしないと、それらが失われるからです。(私はそのリモートにアクセスできないため、それらをプッシュできませんでした)。そこで、submodule / .gitをremote_origin2として追加し、それをフェッチしてコミットし、そのブランチからマージしました。私はまだgitに精通していないので、オリジンとしてサブモジュールリモートがまだ必要かどうかはわかりません。