意図せずリポジトリが入れ子になった場合の対処方法

発生した問題

リポジトリの特定のサブディレクトリ以下の編集が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を持つオブジェクトは存在しなかった。

原因

ポジトリが入れ子になってたのが原因。サブディレクトリの.git1は削除してあった。しかし、削除前にそのディレクトリでコミットしたため(サブディレクトリは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.

参考


  1. frontディレクトリはcreate-react-appで生成したReactのテンプレートのため自動で.gitが生成された。