325

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

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

サブモジュール HEAD がどうあるべきかはわかっています。 commit を持つレポからプッシュせずに、これをローカルで変更できる方法はあります2d7cfbd09fc96c04c4c41148d44ed7778add6b43?

私が明確に言っているかどうかはわかりません...これは私が見つけた同様の状況です。

4

13 に答える 13

391

サブモジュールのリポジトリに使用したいコミットが含まれていると仮定すると (スーパープロジェクトの現在の状態から参照されるコミットとは異なります)、それを行うには 2 つの方法があります。

最初の方法では、使用するサブモジュールからのコミットを既に知っている必要があります。サブモジュールを直接調整してからスーパープロジェクトを更新することにより、「内外」から機能します。2 つ目は、サブモジュールを変更したスーパー プロジェクトのコミットを見つけてから、別のサブモジュールのコミットを参照するようにスーパー プロジェクトのインデックスをリセットすることによって、「外側から内側」に働きかけます。

インサイド、アウト

サブモジュールで使用するコミットが既にわかっている場合は、サブモジュールに対してcd、必要なコミットをチェックアウトしてから、スーパープロジェクトに戻しますgit addgit 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 番目の diff は、ステージングされた唯一の変更が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代わりに上記の「インサイド アウト」プロセスを使用することもできます。

スーパープロジェクトでチェックアウト

$ 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 番目の diff は、インデックスと作業ツリーが同じであることを示しています。3 番目の差分は、段階的な変更のみがsubサブモジュールを別のコミットに移動していることを示しています。

専念

git commit

これにより、修正されたサブモジュール エントリがコミットされます。

于 2010-01-29T10:53:49.490 に答える
192

これを試して:

git submodule sync
git submodule update
于 2010-10-17T13:50:10.387 に答える
17

このエラーは、サブモジュールにコミットがないことを意味している可能性があります。つまり、リポジトリ(A)にはサブモジュール(B)があります。Aは、特定のコミット(B内)を指すようにBをロードしたいと考えています。そのコミットが何らかの理由で欠落している場合は、そのエラーが発生します。考えられる原因:コミットへの参照はAにプッシュされましたが、実際のコミットはBからプッシュされませんでした。そこで始めます。

可能性は低いですが、権限の問題があり、コミットをプルできません(git + sshを使用している場合は可能です)。

.git/configおよび.gitmodulesでサブモジュールパスが正常に表示されることを確認します。

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

于 2011-11-15T21:25:13.260 に答える
10

考えられる原因

これは、次の場合に発生する可能性があります。

  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

その結果、不足しているコミットはローカル ディスク上に残っているため、リモート ユーザーが見つけられない可能性があります。

解決

サブモジュールをプッシュするように変更した人に通知します。つまり、

$ cd submodule
$ git push
于 2014-09-04T10:21:26.807 に答える
7

私がしたときにこのエラーが発生しました:

$ git submodule update --init --depth 1

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

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

$ git submodule update --init

問題を解決しませんでした。レポを削除し、深さフラグなしで再試行しましたが、うまくいきました。

このエラーは Ubuntu 16.04 git 2.7.4 で発生しますが、Ubuntu 18.04 git 2.17 では発生しません。

@pavan kumar はコメントで次のように述べています。

古いコミットを含めるように深度カウントを増やしただけで、うまくいきました。

于 2014-09-16T17:43:41.297 に答える
5

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

于 2012-01-29T09:19:20.483 に答える
2

この回答は、ターミナル git の経験が限られている SourceTree のユーザー向けです。

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

取得し、[すべてのタグを取得] がオンになっていることを確認します。

Git プロジェクトをリベースしてプルします。

これにより、「参照はツリーではない」という問題が 10 回中 9 回解決されます。その1回は、一番上の回答で説明されているように、端末の修正です。

于 2016-10-26T23:40:54.363 に答える
1

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

では、サブモジュールを削除して再度追加してみませんか?

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

于 2010-01-29T07:22:28.393 に答える
1

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

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

于 2014-02-13T17:27:16.603 に答える
1

私の場合、上記の答えはどれも問題を解決しませんが、良い答えです。そこで、ソリューションを投稿します (私の場合、クライアント A と B の 2 つの git クライアントがあります)。

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

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

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

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

  5. マスターにコミットする

  6. 他のクライアントに変更し、rebaseやり直してください。

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

  8. 参考までに、サブモジュールを削除しようとしないでください.git/modules。リアクティブなローカルのものでない限り、サブモジュールはそこに残り、このサブモジュールを再度読み取ることはできません。

于 2015-10-20T05:15:26.897 に答える
1

git リポジトリをサブモジュールのヘッドと同期するには、それが本当に必要な場合に備えて、サブモジュールを削除してから再読み込みすると、履歴をいじる必要がなくなることがわかりました。残念ながら、サブモジュールを削除するには、単一の git コマンドではなくハッキングが必要ですが、実行可能です。

https://gist.github.com/kyleturner/1563153に触発された、サブモジュールを削除するための手順:

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

繰り返しますが、これは、サブモジュールの先頭をもう一度ポイントするだけで、サブモジュールのローカル コピーをそのままにしておく必要があるために複雑なことをしていない場合に役立ちます。サブモジュールの起源がどこであっても、独自のレポとして「正しい」サブモジュールを持っていると想定し、それをサブモジュールとして適切に含めることに戻りたいだけです。

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

于 2015-10-29T11:48:11.617 に答える