submodule と subtree-merging
gitのsubmoduleとsubtree-mergingがどう違うか実験してみた.
やりかたは,calcモジュールとcalcモジュールを使うcomplicated_calcっていうプロジェクトを作る.
calcモジュールとcomplicated_calcプロジェクトは別のリポジトリで管理する.
submoduleとsubtree-mergingの両方を使ってモジュールを取り込んでみたり,Pullしたり,Pushしたりしてみる.
calcリポジトリを作る.
└─ calc └── __init__.py
__init__.py
の中身
class Calc(object): def plus(self, l, r): return l + r def minus(self, l, r): return l - r
こんな感じ.
続いて,complicated_calcリポジトリを作る. calcモジュールを使いたい.
└── complicated_calc ├── main.py └── calc └── __init__.py
とりあえず main.py
の中身
from calc import Calc def main(): c = Calc() print c.plus(1, 1) print c.minus(10, 4) if __name__ == "__main__": main()
超複雑!
ここで,calcモジュールをsubmodule
で使うか,subtree-merging
で使うかを検証.
とりあえず取り込んでみる.
submodule
calcモジュールをサブモジュールとして追加する
$ git submodule add git@bitbucket.org:foo/calc.git calc
calcディレクトリ以下にcloneされてくる.
$ python mian.py 2 6
複雑な計算ができた!!!
submodulesの差分
# new file: .gitmodules # new file: calc
calcはバージョン管理される時には,ディレクトリだけ管理されて,中身は管理されない.
他のマシンでcloneした時は
$ git submodule init $ git submodule update
をすると,.gitmodules
を見て,モジュールのcloneをしてくれる.
subtree-merging
$ git remote add calc_remote git@bitbucket.org:foo/calc.git calc $ git fetch calc_remote $ git checkout -b calc_branch calc_remote/master
これで,現在のリポジトリのcalc_branch
にはcalcモジュールのファイルが,master
にはcomplicated_calcのファイルがある状態になる.
ここで,master
のサブディレクトリにcalc_branch
を取り込む.
$ git read-tree --prefix=calc/ -u calc_branch
見事にcalcモジュールができた!
$ python main.py 2 6
複雑な計算(ry
subtreeの差分
# new file: calc/.gitignore # new file: calc/__init__.py
submoduleとは異なり,calcの中身もバージョン管理される.
公開されてるモジュールを使う場合など,自分のプロジェクトで手を加えることが無いなら,正直どちらでも大差ないと思う.(人様のモジュールを自分のリポジトリに入れるのもあれなんでsubmoduleを使うべきなんですかね)
Pullする
Calcクラスにmulメソッドを追加してみる. この変更をsubmoduleとsubtree-mergingでどうやって取り込むかを見てみる.
class Calc(object): def plus(self, l, r): return l + r def minus(self, l, r): return l - r def mul(self, l, r): return l * r
main.pyに追加
print c.mul(3, 4)
submodule
git submodule foreach 'git pull origin master'
calcディレクトリ内は親プロジェクトとは独立してバージョン管理されているので,これだけでpull作業は完了.
差分は
# modified: calc (new commits)
こんな感じになってる.
この段階で
$ git submodule update #前のリビジョンに戻ってしまう
すると,前のリビジョンのcalcにリバートされてしまう.
親プロジェクト側でcalcをコミットすると,そのコミットに記録されたcalcのリビジョンを使うようになる.
subtree-merging
$ git checkout calc_branch $ git pull
ここでcalc_branch
のCalcクラスはmulメソッドを持った状態になる.
$ git checkout master
この時点では,master
ブランチのCalcクラスはmulメソッドを持たない.
$ git merge --squash -s subtree --no-commit calc_branch
これで,calc_branch
がmaster
にマージされた.
差分は
# modified: calc/__init__.py
Pushする
親プロジェクトでCalcクラスの変更を行う.divメソッドの追加
class Calc(object): def plus(self, l, r): return l + r def minus(self, l, r): return l - r def mul(self, l, r): return l * r def div(self, l, r): return l / r
submodule
親プロジェクト内で
$ cd calc $ 編集 $ git add . $ git commit -m "added div"
これで,Pushしたらcalcリポジトリは更新される.calcディレクトリは親プロジェクトとは別にバージョン管理されているため.
親プロジェクトの差分は
# modified: calc (new commits)
親プロジェクトでもコミットして,使用するcalcのリビジョンを記録すれば完了.
subtree-merging
$ cd calc $ 編集 $ calcの変更履歴をコミット
ここまでで,親プロジェクトのバージョン管理は完了.
calcのリポジトリに変更を反映しなければならない.
$ git checkout calc_branch $ git merge --squash -s subtree --no-commit master
マージが終わったら,公開リポジトリにPushしてあげれば終わり! 割と簡単に差分が取り込めて感動!
ここまでやってみて
submoduleとsubtree-mergingの使い分け
ここに詳しい説明がある.
1回実験をしてみると,何を言っているのかわかる!
subtree-merging の方が良さげかなぁ