アリスとボブのサーバー、git pushをちゃんと理解したい!
アリスとボブのGitシリーズが本になりました!
アリスとボブのGit入門レッスン
上記の日記から続く、アリスとボブの記録。
前提条件
- アリスとボブは同じマシンにログインする異なるユーザー。
- ファイルシステムからアクセスする分には、サーバーの設定は不要になるので、これで話がシンプルになる。
共通gitリポジトリの準備
最近、アリスにはちょっとした悩みがあった。
- 現在、このプロジェクトはアリスとボブの二人で、修正したら連絡を取り合って、お互いの変更をダウンロードする(git pullする)ことで同期をとっていた。
- しかし、プロジェクトメンバーが増えた場合、このやり方では同期する手間が煩雑になってしまう...。
- 理想は、サーバーとなるgitリポジトリを決めて、作業前にそこからダウンロード、修正したらそこにアップロードを繰り返す方式にしたい。
アリスがボブに相談すると、ボブはアリスのマシンで操作して、あっという間に実現してくれた。
alice/project$ git clone --bare /Users/alice/project /Users/Shared/project.git
Initialized empty Git repository in /Users/Shared/project.git/
- 上記コマンドで作成されたフォルダのアクセス権を、everyone読み/書きOKにして、内包している項目すべてに適用した。(Finderから操作した。)
- git cloneはgit管理のフォルダをコピーするコマンドなのだが、--bareオプション*1を指定することで...
- /Users/alice/project/.gitフォルダを/Users/Shared/project.gitフォルダへコピーしてくれる。(gitが管理するスナップショットと設定だけがコピーされる。完全に同じではなく、サーバーとして必要な設定になるようだ)
- gitにとって重要なのは、変化の履歴をスナップショットとして保存したデータとその設定、つまり.gitフォルダであり、
- ユーザーが操作するテキストファイルは、作業結果を記録する一時的なファイルでしかない。(...と思う。)
これで、/Users/Shared/project.gitという共通のgitリポジトリが出来た。
- アリスとボブは今後、作業の前後に/Users/Shared/project.gitと同期することによって、お互いの作業を確認し合うことになる。*2
- 具体的には以下の操作。(今はコピーした直後なので、同期された状態だ。)
alice/project$ git pull /Users/Shared/project.git master From /Users/Shared/project * branch master -> FETCH_HEAD Already up-to-date. alice/project$ git push /Users/Shared/project.git master Everything up-to-date
- git pushによって、/Users/Shared/project.gitのmasterブランチへアップロードしている。
ボブの作業
- ボブは前回修正したaboutメソッドにバグを見つけた。早速、新しい運用方法でgitを操作してみる。
- まず最初にボブは、/Users/Shared/project.gitにsharedという略称を設定した。(この方が簡潔に入力できる)
- ボブはその後、共通リポジトリsharedのmasterブランチからプル。
bob/myrepo$ git remote add shared /Users/Shared/project.git bob/myrepo$ git pull shared master From /Users/Shared/project * branch master -> FETCH_HEAD Already up-to-date.
- 式展開を含む文字列をシングルクォートで囲っていたので、ダブルクォートに変更した。
# About git Class WhatIsGit def show puts 'Git is easy, if you understand the basis.' end def about(lang = 'en') puts "http://#{lang}.wikipedia.org/wiki/Git" end end
- ボブはその後、コミット
bob/myrepo$ git commit -a -m "changed to double quotation marks"
Created commit f85e8dc: about URL changed3
1 files changed, 1 insertions(+), 1 deletions(-)
- ボブはその後、プッシュ
bob/myrepo$ git push shared master
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 291 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /Users/Shared/project.git
52cfe0d..16150ca master -> master
無事、共通gitリポジトリに反映されたようだ。
アリスの作業
- ところで、アリスが作業する前にプルすると...
alice/project$ git pull /Users/Shared/project.git master
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /Users/Shared/project
* branch master -> FETCH_HEAD
Updating 52cfe0d..16150ca
Fast forward
what_is_git.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
- 何らかの変更がダウンロードされたようだ。アリスは履歴を確認してみた。
alice/project$ git log commit 16150ca79dc873b972edb6570bf750a99ddf80fe Author: bobDate: Wed Sep 10 16:36:59 2008 +0900 changed to double quotation marks commit 52cfe0de979425dbf1dcef3d081e06ea40a68965 Merge: 616c5cb... fb7c82f... Author: alice Date: Mon Sep 8 17:44:48 2008 +0900 Merge /Users/bob/myrepo Conflicts: what_is_git.rb commit fb7c82fda542762554792fc9b198428a3e6ae5b3 Author: bob Date: Mon Sep 8 16:11:45 2008 +0900 git is easy! ...(中略)...
- アリスはさらに詳細を確認すると...
$ git show commit 16150ca79dc873b972edb6570bf750a99ddf80fe Author: bobDate: Wed Sep 10 16:36:59 2008 +0900 changed to double quotation marks diff --git a/what_is_git.rb b/what_is_git.rb index 103a58e..ac3f723 100644 --- a/what_is_git.rb +++ b/what_is_git.rb @@ -5,6 +5,6 @@ Class WhatIsGit end def about(lang = 'en') - puts 'http://#{lang}.wikipedia.org/wiki/Git' + puts "http://#{lang}.wikipedia.org/wiki/Git" end end
アリスは「ボブもたまには間違うのね!」と呟いた。
所感
- 当初、git pushはgit pullとはデータの流れが反対の動きをするだけで、あとは同じと考えていた。
- しかし、実際に使ってみると、それ以外に大きな違いがあることに気付く。
- git pullは履歴データを受け取る人が、自分の好きなタイミングで実行することが出来る。
- git pushでは、データを受け取る人は、外部からいつのタイミングで送信されてくるのか予想できない。
- そのため、git pullは自分の作業ディレクトリ*3でそのまま実行し、同期された内容に作業ファイルの状態も即更新されるが、
- git pushは、git push専用の.gitフォルダを用意して、その専用フォルダに対してのみgit pushする仕様となっているようだ。
- もし、ファイルを修正中に外部から次々プッシュされ最終のコミットが変化てしまったら、そのユーザーは混乱してしまうことになるだろう。
- /Users/alice/projectフォルダに対してgit psuhすることも可能なようだが、運用としてgit pushしないようにするのが一般的なようだ。
- フォルダにアクセス権を設定しておけば、勘違いのgit pushも防止できるはず。