無効なコミットを指しているサブモジュールを持つプロジェクトがあります。サブモジュールのコミットはローカルのままで、別のリポジトリから取得しようとすると次のようになります。
$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'
サブモジュールHEADがどうあるべきかを知っていますが、することなくリポジトリからプッシュせずにローカルにこれを変更できる方法はありますかコミット2d7cfbd09fc96c04c4c41148d44ed7778add6b43
がありますか?
私がはっきりしているかどうかわからない… これは似たような状況だ 私は見つけた。
サブモジュールのリポジトリに使用したいコミットが含まれていると仮定して(スーパープロジェクトの現在の状態から参照されるコミットとは異なり)、それを行うには2つの方法があります。
最初の方法では、使用したいサブモジュールからのコミットを知っておく必要があります。サブモジュールを直接調整してからスーパープロジェクトを更新することで、「内側から外側へ」動作します。 2つ目は、サブモジュールを変更したスーパープロジェクトのコミットを見つけ、別のサブモジュールコミットを参照するようにスーパープロジェクトのインデックスをリセットすることによって、「外から」の作業を行います。
サブモジュールにどのコミットを使用したいかがすでにわかっている場合は、サブモジュールにcd
を付けて、必要なコミットをチェックアウトしてから、git add
およびgit commit
をスーパープロジェクトに戻します。
例:
$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
サブモジュールsub
で未公開のコミットを参照するスーパープロジェクトのコミットを行った人がいます。どういうわけか、サブモジュールをコミット5d5a3ee314476701a20f2c6ec4a53f88d651df6c
にしたいということはすでにわかっています。そこに行き、直接それをチェックしてください。
$ cd sub
$ git checkout 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
Note: moving to '5d5a3ee314476701a20f2c6ec4a53f88d651df6c' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
git checkout -b <new_branch_name>
HEAD is now at 5d5a3ee... quux
$ cd ..
コミットをチェックアウトしているので、これはサブモジュールに切り離されたHEADを生成します。サブモジュールがブランチを使用していることを確認したい場合は、コミット時にgit checkout -b newbranch <commit>
を使用してブランチを作成またはチェックアウトするか、必要なブランチをチェックアウトします(たとえば、先端に必要なコミットを持つもの)。
サブモジュールでのチェックアウトは、作業ツリーへの変更としてスーパープロジェクトに反映されます。そのため、スーパープロジェクトのインデックスを変更して結果を検証する必要があります。
$ git add sub
$ git submodule update
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
サブモジュールはすでに指定されたコミットになっているため、サブモジュールの更新はサイレントでした。最初の差分は、インデックスとワークツリーが同じであることを示しています。 3番目の差分は、段階的な変更がsub
サブモジュールを別のコミットに移動することだけを示しています。
git commit
これは修正されたサブモジュールエントリをコミットします。
サブモジュールからどのコミットを使用するべきかわからない場合は、スーパープロジェクト内の履歴を調べてガイドすることができます。スーパープロジェクトから直接リセットを管理することもできます。
$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
これは上記と同じ状況です。しかし今回は、サブモジュールに入るのではなく、スーパープロジェクトから修正することに焦点を当てます。
$ git log --oneline -p -- sub
ce5d37c local change in sub
diff --git a/sub b/sub
index 5d5a3ee..e47c0a1 160000
--- a/sub
+++ b/sub
@@ -1 +1 @@
-Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
+Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
bca4663 added sub
diff --git a/sub b/sub
new file mode 160000
index 0000000..5d5a3ee
--- /dev/null
+++ b/sub
@@ -0,0 +1 @@
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
OK、ce5d37c
でうまくいかなかったように見えますので、サブモジュールをその親(ce5d37c~
)から復元します。
あるいは、パッチテキスト(5d5a3ee314476701a20f2c6ec4a53f88d651df6c
)からサブモジュールのコミットを取得し、代わりに上記の "inside、out"プロセスを使用することもできます。
$ git checkout ce5d37c~ -- sub
これにより、sub
のサブモジュールエントリが、スーパープロジェクトのコミットce5d37c~
の状態にリセットされます。
$ git submodule update
Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'
サブモジュールの更新は問題なく行われました(分離HEADを示します)。
$ git diff ce5d37c~ -- sub
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
最初のdiffは、sub
がce5d37c~
でも同じであることを示しています。 2番目の差分は、インデックスとワークツリーが同じであることを示しています。 3番目の差分は、段階的な変更がsub
サブモジュールを別のコミットに移動していることを示しています。
git commit
これは修正されたサブモジュールエントリをコミットします。
これを試して:
git submodule sync
git submodule update
このエラーは、サブモジュールにコミットがないことを意味します。すなわち、リポジトリ(A)はサブモジュール(B)を有する。 Aが特定のコミットを指し示すようにBをロードしたい(B内)。そのコミットがどういうわけか欠けているなら、あなたはそのエラーを得るでしょう。考えられる原因:コミットへの参照がAにプッシュされましたが、実際のコミットはBからプッシュされませんでした。そこで、ここから始めます。
それほど可能性は低いですが、パーミッションの問題があり、コミットすることはできません(git + sshを使っているなら可能です)。
サブモジュールのパスが.git/configと.gitmodulesで問題ないように見えるようにしてください。
最後に試すべきこと - サブモジュールディレクトリの中:git reset HEAD --hard
これが発生する可能性があります。
例えばこんなことが起こった:
$ cd submodule
$ emacs my_source_file # edit some file(s)
$ git commit -am "Making some changes but will forget to Push!"
この時点でサブモジュールをプッシュする必要があります。
$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git Push Origin master
その結果、まだコミットされていないコミットはまだローカルディスク上にあるため、リモートユーザーが見つけることはできませんでした。
サブモジュールをPushに変更した人に通知します。
$ cd submodule
$ git Push
私がやったとき私はこのエラーを得ました:
$ git submodule update --init --depth 1
しかし、親プロジェクトでのコミットは以前のコミットを指していました。
サブモジュールフォルダを削除して実行します。
$ git submodule update --init
問題を解決しませんでした。リポジトリを削除し、深度フラグなしでもう一度試してみましたが、うまくいきました。
このエラーはUbuntu 16.04 git 2.7.4では発生しますが、Ubuntu 18.04 git 2.17では発生しません。TODOは正確な修正コミットまたはバージョンを見つけます。
これは、リベースされたリポジトリを指すサブモジュールがあり、指定のコミットが「なくなった」場合にも発生する可能性があります。コミットはまだリモートリポジトリにある可能性がありますが、ブランチにはありません。もしあなたが新しいブランチを作成できない場合(例えばあなたのリポジトリではない)、あなたは新しいコミットを指すようにスーパープロジェクトを更新しなければならないことに行き詰まっています。あるいは、サブモジュールのコピーの1つを別の場所にプッシュしてから、代わりにそのリポジトリを指すようにスーパープロジェクトを更新することもできます。
この回答は、限られた端末gitの経験しかないSourceTreeのユーザーのためのものです。
Gitプロジェクト(スーパープロジェクト)内から問題のあるサブモジュールを開きます。
「すべてのタグを取得」が選択されていることを確認します。
Gitプロジェクトを引っ張り直します。
これは「参照は木ではない」問題を10回のうち9回解決します。その1回はそれがしない、トップの答えで説明されているように端末の修正です。
Gitリポジトリをサブモジュールの頭と同期させるために、それが本当に望んでいることである場合には、サブモジュールを削除し、次にそれを読むことが履歴のいじりを避けることを発見しました。残念ながら、サブモジュールを削除するには、単一のgitコマンドではなくハッキングが必要ですが、実行可能です。
https://Gist.github.com/kyleturner/156315 にヒントを得た、サブモジュールを削除するための手順
繰り返しになりますが、これはあなたが望むのがサブモジュールの頭を再び指すことだけであり、サブモジュールのローカルコピーをそのままにしておくことによって物事を複雑にしていない場合に役立ちます。その起源がどこであっても、あなたはそれ自身のリポジトリとしてあなたが "正しい"サブモジュールを持っていると仮定して、あなたはサブモジュールとしてそれを適切に含めることに戻りたいだけです。
注意:この種の操作や単純なコミットやプッシュ以外のgitコマンドを実行する前に、必ずプロジェクトのフルコピーを作成してください。私は他のすべての答えと同様に、そして一般的なgitガイドラインとしてそれをお勧めします。
サブモジュールの履歴はとにかくサブモジュールgitに安全に保存されています。
それでは、なぜサブモジュールを削除して再度追加しないのでしょうか。
それ以外の場合は、サブモジュールrefs/master/head
内のHEAD
または.git
を手動で編集してみましたか?
私の場合、上の答えのどれも、それらが良い答えであるとしても問題を解決しません。そこで私は自分の解決策を投稿します(私の場合は2つのgitクライアント、クライアントAとBがあります):
サブモジュールのディレクトリに移動します。
cd sub
マスターへのチェックアウト:
git checkout master
両方のクライアントが見ることができるコミットコードにリベース
親のディレクトリに戻ります。
マスターする
他のクライアントに変更してください。再度rebase
を実行してください。
ついにそれは今うまく働きます!たぶんいくつかのコミットを失うかもしれませんが、それはうまくいきます。
参考までに、あなたのサブモジュールを削除しようとしないでください、それはそこに.git/modules
を残すでしょう、そして反応的なローカルのものでなければ、このサブモジュールを再び読むことはできません。
この問題につまずいただけで、これらの解決策はどれも私にとってはうまくいきませんでした。私の問題の解決策であることが判明したのは、実際にははるかに簡単です。Gitをアップグレードします。私のものは1.7.1で、私が2.16.1(最新)にアップグレードした後、問題は跡形もなく消えました!私はそれをここに残していると思います、それが誰かに役立つことを願っています。
ブランチは最新ではないかもしれませんが、簡単な解決策ですが、git fetch
を試してください
念のため、git
バイナリを更新してみてください。
GitHub for Windowsにはバージョンgit version 1.8.4.msysgit.0
があり、私の場合はこれが問題でした。更新することで解決しました。