web-dev-qa-db-ja.com

Gitサブモジュールヘッドの '参照はツリーではありません'エラー

無効なコミットを指しているサブモジュールを持つプロジェクトがあります。サブモジュールのコミットはローカルのままで、別のリポジトリから取得しようとすると次のようになります。

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'

サブモジュールHEADがどうあるべきかを知っていますが、することなくリポジトリからプッシュせずにローカルにこれを変更できる方法はありますかコミット2d7cfbd09fc96c04c4c41148d44ed7778add6b43がありますか?

私がはっきりしているかどうかわからない… これは似たような状況だ 私は見つけた。

294

サブモジュールのリポジトリに使用したいコミットが含まれていると仮定して(スーパープロジェクトの現在の状態から参照されるコミットとは異なり)、それを行うには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は、subce5d37c~でも同じであることを示しています。 2番目の差分は、インデックスとワークツリーが同じであることを示しています。 3番目の差分は、段階的な変更がsubサブモジュールを別のコミットに移動していることを示しています。

コミット

git commit

これは修正されたサブモジュールエントリをコミットします。

371
Chris Johnsen

これを試して:

git submodule sync
git submodule update
184
Lonre Wang

このエラーは、サブモジュールにコミットがないことを意味します。すなわち、リポジトリ(A)はサブモジュール(B)を有する。 Aが特定のコミットを指し示すようにBをロードしたい(B内)。そのコミットがどういうわけか欠けているなら、あなたはそのエラーを得るでしょう。考えられる原因:コミットへの参照がAにプッシュされましたが、実際のコミットはBからプッシュされませんでした。そこで、ここから始めます。

それほど可能性は低いですが、パーミッションの問題があり、コミットすることはできません(git + sshを使っているなら可能です)。

サブモジュールのパスが.git/configと.gitmodulesで問題ないように見えるようにしてください。

最後に試すべきこと - サブモジュールディレクトリの中:git reset HEAD --hard

15
Daniel Tsadok

考えられる原因

これが発生する可能性があります。

  1. サブモジュールは適切に編集されています
  2. サブモジュールがコミットされ、が指しているサブモジュールのハッシュが更新されます
  3. サブモジュールプッシュされていない.

例えばこんなことが起こった:

$ 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
9
chriskelly

私がやったとき私はこのエラーを得ました:

$ git submodule update --init --depth 1

しかし、親プロジェクトでのコミットは以前のコミットを指していました。

サブモジュールフォルダを削除して実行します。

$ git submodule update --init

問題を解決しませんでした。リポジトリを削除し、深度フラグなしでもう一度試してみましたが、うまくいきました。

このエラーはUbuntu 16.04 git 2.7.4では発生しますが、Ubuntu 18.04 git 2.17では発生しません。TODOは正確な修正コミットまたはバージョンを見つけます。

5
Plato

これは、リベースされたリポジトリを指すサブモジュールがあり、指定のコミットが「なくなった」場合にも発生する可能性があります。コミットはまだリモートリポジトリにある可能性がありますが、ブランチにはありません。もしあなたが新しいブランチを作成できない場合(例えばあなたのリポジトリではない)、あなたは新しいコミットを指すようにスーパープロジェクトを更新しなければならないことに行き詰まっています。あるいは、サブモジュールのコピーの1つを別の場所にプッシュしてから、代わりにそのリポジトリを指すようにスーパープロジェクトを更新することもできます。

4
pasamio

この回答は、限られた端末gitの経験しかないSourceTreeのユーザーのためのものです。

Gitプロジェクト(スーパープロジェクト)内から問題のあるサブモジュールを開きます。

「すべてのタグを取得」が選択されていることを確認します。

Gitプロジェクトを引っ張り直します。

これは「参照は木ではない」問題を10回のうち9回解決します。その1回はそれがしない、トップの答えで説明されているように端末の修正です。

1
ericTbear

Gitリポジトリをサブモジュールの頭と同期させるために、それが本当に望んでいることである場合には、サブモジュールを削除し、次にそれを読むことが履歴のいじりを避けることを発見しました。残念ながら、サブモジュールを削除するには、単一のgitコマンドではなくハッキングが必要ですが、実行可能です。

https://Gist.github.com/kyleturner/156315 にヒントを得た、サブモジュールを削除するための手順

  1. Git rm --cachedを実行します。
  2. .gitmodulesファイルから関連する行を削除します。
  3. .git/configから関連セクションを削除します。
  4. 追跡されていないサブモジュールファイルを削除します。
  5. ディレクトリ.git/modules /を削除します。

繰り返しになりますが、これはあなたが望むのがサブモジュールの頭を再び指すことだけであり、サブモジュールのローカルコピーをそのままにしておくことによって物事を複雑にしていない場合に役立ちます。その起源がどこであっても、あなたはそれ自身のリポジトリとしてあなたが "正しい"サブモジュールを持っていると仮定して、あなたはサブモジュールとしてそれを適切に含めることに戻りたいだけです。

注意:この種の操作や単純なコミットやプッシュ以外のgitコマンドを実行する前に、必ずプロジェクトのフルコピーを作成してください。私は他のすべての答えと同様に、そして一般的なgitガイドラインとしてそれをお勧めします。

0
matanster

サブモジュールの履歴はとにかくサブモジュールgitに安全に保存されています。

それでは、なぜサブモジュールを削除して再度追加しないのでしょうか。

それ以外の場合は、サブモジュールrefs/master/head内のHEADまたは.gitを手動で編集してみましたか?

0
Lakshman Prasad

私の場合、上の答えのどれも、それらが良い答えであるとしても問題を解決しません。そこで私は自分の解決策を投稿します(私の場合は2つのgitクライアント、クライアントAとBがあります):

  1. サブモジュールのディレクトリに移動します。

    cd sub
    
  2. マスターへのチェックアウト:

    git checkout master
    
  3. 両方のクライアントが見ることができるコミットコードにリベース

  4. 親のディレクトリに戻ります。

  5. マスターする

  6. 他のクライアントに変更してください。再度rebaseを実行してください。

  7. ついにそれは今うまく働きます!たぶんいくつかのコミットを失うかもしれませんが、それはうまくいきます。

  8. 参考までに、あなたのサブモジュールを削除しようとしないでください、それはそこに.git/modulesを残すでしょう、そして反応的なローカルのものでなければ、このサブモジュールを再び読むことはできません。

0
kimimaro

この問題につまずいただけで、これらの解決策はどれも私にとってはうまくいきませんでした。私の問題の解決策であることが判明したのは、実際にははるかに簡単です。Gitをアップグレードします。私のものは1.7.1で、私が2.16.1(最新)にアップグレードした後、問題は跡形もなく消えました!私はそれをここに残していると思います、それが誰かに役立つことを願っています。

0
An Phan

ブランチは最新ではないかもしれませんが、簡単な解決策ですが、git fetchを試してください

0
kittycatbytes

念のため、gitバイナリを更新してみてください。

GitHub for Windowsにはバージョンgit version 1.8.4.msysgit.0があり、私の場合はこれが問題でした。更新することで解決しました。

0
Gman