意図せずリポジトリが入れ子になった場合の対処方法
発生した問題
リポジトリの特定のサブディレクトリ以下の編集がGitに管理されなかった。リポジトリのディレクトリ構成は以下の通り。
./ ├─ .git ├─ .gitignore ├─ front/ // frontディレクトリがGitに管理されない └─ server/
gti cat-file -p
でGitのデータ構造を見てみると以下のような結果になった。
$ git cat-file -p HEAD tree 50007e590683eb6c28149a8ce034e8844eaad78d parent f3b00e429aa0ac688d531b7bd6aa4ee2e10a4e6a author ... committer ... $ git cat-file -p 50007e590683eb6c28149a8ce034e8844eaad78d 100644 blob 1761c01d0571f991ca5b544e490766b936946180 .gitignore 160000 commit bb84439791592e7db3491d58eaf19ffce9469371 front 040000 tree 959eaa356045c4f60752dbb6306806509373f993 server
対象のディレクトリがtreeでなく、commitと表示されている。treeオブジェクトがcommitオブジェクトを参照することはありえないはず。また .git/objects
にハッシュ値bb84439791592e7db3491d58eaf19ffce9469371
を持つオブジェクトは存在しなかった。
原因
ポジトリが入れ子になってたのが原因。サブディレクトリの.git
1は削除してあった。しかし、削除前にそのディレクトリでコミットしたため(サブディレクトリは1つのリポジトリとして完結してるので可能)、ディレクトリではなくサブモジュール扱いになってたらしい。
サブモジュールはgit cat-fiile -p
だとcommitとして表示されるようだ。一方でモード情報の表示は160000でGitlinkの番号になってる。Gitlinkはサブモジュールとなっているリポジトリのコミットへの参照であるが、今回の場合、参照先のリポジトリの.git
はすでに削除されているので、対象のコミットは存在していない。
対処方法
Gitlink を削除してadd & commit
$ git rm --cached front $ git commtit -am "delete front gitlink"
その他
同じ状況を再現してやってみると(サブディレクトリで先にコミット)、リポジトリが入れ子になった状態でaddしたときに丁寧な警告が出ていた。
$ ls front server $ git add . warning: adding embedded git repository: front hint: You've added another git repository inside your current repository. hint: Clones of the outer repository will not contain the contents of hint: the embedded repository and will not know how to obtain it. hint: If you meant to add a submodule, use: hint: hint: git submodule add <url> front hint: hint: If you added this path by mistake, you can remove it from the hint: index with: hint: hint: git rm --cached front hint: hint: See "git help submodule" for more information.