リモートで利用するGitの話
リモートでgitを使う場合流れとしてgit cloneをおこなってオリジナルからコピーを作成するだけで作業ができる。また、共同で何かを開発している場合はオリジナルとコピーのあいだの変更を送受信することができる。
githubやbitbuketのようなサービスはこの流れをオンライン上でできるようにしたサービスなのだ。
ディレクトリを複製する
リモートで共同作業を行う最初のステップは、ディレクトリの複製だ。
ディレクトリの複製には2つの方法がある。
Linuxコマンドであればのcpなどを使って複製する
git cloneをつかって複製する
どちらもディレクトリを複製することができブランチなども全て複製することができる。この二つの方法の決定的な違いは、複製元と複製されたものとがリンクしているかどうかである。リンクされてることで二つの間で行われる変更の送受信ができるようになる。
git cloneを使う。
git clone source dir
これだけで複製を作成することができる。sourceはコピー元のリポジトリ(urlやローカルディレクトリ)を入力しdirの部分には複製を作る場所を指定する。
git cloneはコピー時にチェックアウトされているブランチをチェックアウトしたままクローンする。他にブランチがある場合git branchのみでは全て見ることができない。見たい場合はgit branch --allを使う必要がある。クローンしたものでブランチを切り替える場合は、git checkout オリジナルの切り替えたいブランチ をすることで切り替えることができるが。
実際はクローンしたものにある--allでみたブランチはリンクのようなものでありクローンした場所にブランチの情報があるわけではないそのためgit branchを使ってもbranch名が表示されなかったのだ。
細かいリモートでのgit checkout 挙動はこうだ。
originに同じなまえのブランチがあるかを参照
同じ名前のブランチがあればgitはそれをユーザーは使おうとしていると解釈しクローン元にブランチを作成する。
このように2段階の動作をおこなっている。
ベアリポジトリ
裸のリポジトリという意味で、作業ディレクトリがないのであらゆるgit操作ができない。しかし、複製、変更の送受信を行うことはできる。
githubなどのオンラインバージョン管理ツールのoriginになるのはこのベアリポジトリなのだ。
ベアリポジトリの作成方法
git clone --bare source dir
git cloneコマンドに--bareオプションをつけることでベアリポジトリを作成することができる。
これで共同作業を行う上での環境は構築できた。
git remote
git remoteは、あまり使わないだろうが共同作業する上で重要な基礎なので書いておく。
git cloneを行うと自動的に複製元とクローンにはリンクができ、クローンにremoteというものが追加される。
git remoteをつかうとリンクされている複製元が表示されgit remote -v showをつかうとその複製元に対して何ができるのかを表示することができる。
また、remoteはクローンしなくても追加することができ、
git remote add リモート名 リンクするファイル
を入力するとそのファイルとリンクされた状態になりファイルの変更を送受信することが可能にな。基本的にはこのような方法は取らずベアリポジトリのみを中心に開発をするめることが多い。
git push
git pushは変更したものを送信するものだ。ローカルでコミットした作業をoriginに追加して変更を加える。要はリモートリポジトリにコミットしてるようなものである。
git push origin originに追加したいbranch名
を入力するとoriginにローカルで変更したmasterブランチの情報が追加される。
git pushができているかどうかを確認する方法は
git remote -v show origin
と入力すると良い。 一番下にup to dateと出るとpushができているということでありoriginと自分の作業ディレクトリは同期された状態であることがわかる。逆に同期されていない場合はlocal out of dateという表記がでる。
複数人で作業する場合にコンフリクトが起きることがある。一人がpushしたのを知らずに変更を取り込まずに同じブランチにpushするとコンフリクトが起こる。変更を取り込む作業は次で説明する。
ちなみに、新しく作ったブランチもgit pushすることができ削除することもできる。
Git pushのコマンドは本来ちゃんと書くと
git push origin src:dest
である。 srcはローカルのブランチ名を入力するところでdestはoriginのブランチ名を入力するところである。
いままでの変更をpushするとは:destを抜いたものなのだ。そして逆にoriginにあるブランチの削除はsrcを抜いたgit push origin :destで削除することができる。
git pull
自分以外の共同開発者がoriginに加えた変更を自分のクローンにも取り込まなければpushするときにエラーが出てしまう。変更を取り込むにはgit pullを利用する。
git pullはgit fetchとgit mergeを同時に行うのものである。
git fetch
git fetchはoriginと自分の作業ディレクトリを比較して違う点があれば、そのリファレンスを持ってくるコマンドである。持ってくるだけで、変更は適用されない。イメージとしてはチェックアウト中のブランチのHEADから伸びた別ブランチ(例えばmasterブランチの変更をfetchした場合、remote/origin/master FETCH_HEAD)が追加される。そこに変更情報が載っているのだ。
変更を適用するにはgit mergeを使ってブランチをマージする。
git merge FETCH_HEAD
これを一気にするのがgit pullである。
git pullにおいてもgit pushと同じようにコンフリクトが発生することがある。pullの場合は、適用したいoriginの情報とローカルでコミットしたものとに差異がある場合にコンフリクトが起こる。その場合は手作業でコードを修正していくことになる。
ちなみに、git pullのマージは特殊である。例えば、二人の開発者が全く同じ変更をおこなって片方がpushしていたとしよう。その場合にpullをするとどうなるのかというと、コンフリクトは起きないのだ。gitは変更が同じであれば、やりたいことが同じだと勝手に解釈して自動でマージを行なってくれる。しかし、このような自動マージは時に混乱を生むことがあるので、git pullよりもgit fetch/mergeを使う方が良いという開発者も多いらしい。