としたにあんの左脳

備忘録です.

submodule と subtree-merging

gitのsubmodulesubtree-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_branchmasterにマージされた.

差分は

#    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 の方が良さげかなぁ