sk51.log

The Averageman's web log.

gitで管理対象にならない場合はsubmoduleになっているかも


2015年11月23日 Web制作

バージョン管理にgitを使用していますが、特定のフォルダ内のファイルが管理対象にならないという問題が発生しました。
.gitignoreで管理対象外にしているわけでもありません。

1. 状況

CakePHPでDebugKitをcloneしてきた時、addしたらDebugKitのファイルのみが追加されないという状況でした。

CakePHP
├ .git
├ app
│└ Plugin
│  └ DebugKit
│    ├ .git
│    ├
$ cd /CakePHP/app/Plugin
$ git clone https://github.com/cakephp/debug_kit.git DebugKit
$ cd /CakePHP
$ git add -A
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#	new file:   CakePHP/app/Plugin/DebugKit
#

DebugKitフォルダのみ追加され、中身のファイルは追加されません。

よくよく考えてみる単純で、git cloneしたということはリポジトリをローカルに作ったということ。
つまり、リポジトリの中にリポジトリがある状態となっていました。
同じワークツリーにあっても、2つのリポジトリは全く別物なので、追加されるはずがありません。

2. インデックスに追加するには

DebugKitの.gitを削除して、addすればインデックスに追加されます。

$ cd /CakePHP/app/Plugin/DebugKit
$ rm -rf .git
$ git add -A

こうすることで、単なるフォルダ構成になるのでインデックスに追加することができます。

3. デメリット

しかし、これにはデメリットがあります。
プラグインというものは、開発者により常に更新される可能性があり、.gitを削除してしまうと単なるフォルダ構成になります。
もしプラグインが更新された場合、最新にするには一度削除してまたcloneするしか方法がありません。

4. サブモジュール

これを防ぐにはどうすればいいかというと、submodule(サブモジュール)という機能を使います。

サブモジュール
あるプロジェクトで作業をしているときに、プロジェクト内で別のプロジェクトを使わなければならなくなることがよくあります。サードパーティが開発しているライブラリや、自身が別途開発していて複数の親プロジェクトから利用しているライブラリなどがそれにあたります。こういったときに出てくるのが「ふたつのプロジェクトはそれぞれ別のものとして管理したい。だけど、一方を他方の一部としても使いたい」という問題です。

例を考えてみましょう。ウェブサイトを制作しているあなたは、Atom フィードを作成することになりました。Atom 生成コードを自前で書くのではなく、ライブラリを使うことに決めました。この場合、CPAN や gem などの共有ライブラリからコードをインクルードするか、ソースコードそのものをプロジェクトのツリーに取り込むかのいずれかが必要となります。ライブラリをインクルードする方式の問題は、ライブラリのカスタマイズが困難であることと配布が面倒になるということです。すべてのクライアントにそのライブラリを導入させなければなりません。コードをツリーに取り込む方式の問題は、手元でコードに手を加えてしまうと本家の更新に追従しにくくなるということです。

Git では、サブモジュールを使ってこの問題に対応します。サブモジュールを使うと、ある Git リポジトリを別の Git リポジトリのサブディレクトリとして扱うことができるようになります。これで、別のリポジトリをプロジェクト内にクローンしても自分のコミットは別管理とすることができるようになります。
Git – サブモジュール

これにより、自前のリポジトリの中で、他人が開発したプラグインを管理することができるようになります。

$ cd /Cakephp
$ git submodule add https://github.com/cakephp/debug_kit.git app/Plugin/DebugKit

こうすることで、プラグインをサブモジュールとして管理できるようになります。

5. サブモジュールを含んでいるリモートリポジトリをcloneする場合

リポートリポジトリをcloneすると、サブモジュールはディレクトリのみで中身は空の状態です。
サブモジュールも取りたい場合は、cloneした後、以下のようにします。

$ git submodule init
Submodule 'dist/app/Plugin/DebugKit' (git://github.com/cakephp/debug_kit.git) registered for path 'dist/app/Plugin/DebugKit'
$ git submodule update
Cloning into 'dist/app/Plugin/DebugKit'...
remote: Counting objects: 9704, done.
remote: Total 9704 (delta 0), reused 0 (delta 0), pack-reused 9704
Receiving objects: 100% (9704/9704), 2.08 MiB | 219.00 KiB/s, done.
Resolving deltas: 100% (4514/4514), done.
Submodule path 'dist/app/Plugin/DebugKit': checked out '1a73aeb21df9df8b26baa5b384f4899ca1736975'

こうすることで、DebugKitの最新版を持ってきています。

もしくは、cloneする際に以下のようにします。

$ git clone --recursive remote.git

コメントを残す

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

*

*

CAPTCHA