今まで何となく使っていたGitだけど、自分でリポジトリを作ろうとしてハマったので今さらながら勉強してみた。

まず何にハマったかと言えば、ローカルでコミットした内容をサーバー側にプッシュしようとしたときに次のようなエラーが出て、何のことだかサッパリわからなかったということ。

まずnone-bareリポジトリって何? と思ったんだけど、わかってしまえば実に簡単なことだった。
none-bareリポジトリは普通にgit initして作られるリポジトリで、例えば

として作る。
そしてbareリポジトリを作る場合は

となる。違いはgit init--bareオブションを付けるかどうかだけ。bareリポジトリの場合、ディレクトリ名に.gitを付けるのが慣習になっているらしい。

じゃあ実際にnon-bareとbareのリポジトリの違いは何なのかと言えば、次の図のように、non-bareリポジトリの場合はMyProjectディレクトリの下に.gitディレクトリが作られて、そこにリポジトリの本体がある。一方のbareリポジトリの場合はMyProject.gitがそのままリポジトリ本体となる。つまりリポジトリが裸のまま剥き出しになっているから「bare」というわけだ。そして.gitの代わりなので慣習としてディレクトリ名の最後に.gitを付けるのだろう。

git-nonbare

non-bare リポジトリ

git-bare

bare リポジトリ

次にギモンに思うのが、なんでbareとnon-bareのリポジトリがあるのか? ということ。これはGitとSVNの違いを考えるとよくわかる。

git-svn

SVNでの作業の流れ

SVNの場合、上の図のようにリポジトリはサーバー側にしかない。そして、クライアント側はチェックアウトしてファイルをローカルの作業ディレクトリに取得する。そして作業ディレクトリに変更を加えたら、それをコミットしてサーバー上のリポジトリに反映させる。

これがGitになると次の図のように変わる。

git-git

Gitでの作業の流れ

サーバー上のリポジトリを取得するのは「クローン」であって「チェックアウト」ではないのがミソ。つまりローカルにもリポジトリを複製するのである。そしてローカルのリポジトリをチェックアウトして作業フォルダにファイルを展開する。そう、non-bareなリポジトリというのは、そのまま作業フォルダになっていて、リポジトリはそこにチェックアウトされた状態になる。

これが最初に出てきたエラーの原因。つまり、サーバー上にもnon-bareなリポジトリを作ってしまったから、そのリポジトリは作業フォルダにチェックアウトされた状態になっていたのである。そこに誰かがプッシュしてしまうと、チェックアウトしたときとリポジトリの状態が変わってしまう。もし、サーバー上で作業フォルダの変更をコミットしたら、プッシュされた変更は上書きされてしまうことになるので、エラーを出してプッシュを受け付けてくれなかったのだ。解決策は簡単で、サーバー上のリポジトリをbareなリポジトリにすればいい。bareなリポジトリは作業フォルダを持たないので、チェックアウトされることはなくなるのだ。エラーの中にごちゃごちゃ書いてある ‘receive.denyCurrentBranch’ は気にしなくて良い。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Anti Spam Code *