履歴
この文書では GPhys の Git レポジトリの利用法について書きます.主に ruby グループに入っている開発者むけですが,読み出しだけなら http で誰でもできます (そして git で patch を作って開発者に送るかたちで開発にも参加できます).
Git はレポジトリのコピー(クローン)をローカルに作成して作業します.ク ローンは単なるコピーでなく,一個のレポジトリです.CVS や Subversion と 違って,コミットはまずそのローカルなレポジトリに対して行います.大元の レポジトリへの反映は push という操作で行います.
ローカルなマシンにもし Git がインストールされてなければインストールし, 初期設定をしましょう. Git 本体に加え,GUI でログなどが表示できる gitk, git-gui をインストール することを勧めます.Debian なら,
# apt-get install git git-doc gitk git-gui
でとりあえず足りるでしょう.(他に git-cvs や git-svn などがあります)
まず,個々のレポジトリによらない共通な個人設定設定を行います.以下はそ の例です.設定内容は ~/.gitconfig に保存されます.このファイルを直接編 集しても構いません.
$ git config --global user.name "Taro Yamada" $ git config --global user.email "yamada@hoge.org"
コミットログにはここで設定した名前とemailアドレスが入りますので必ず設定 してください.ChangeLog 等を自動生成する場合,名前だけを入れメールアド レスは入らないようにできます.それでも公開レポジトリに置くためなどでス パムの可能性が気になるようでしたら,user.email で @ 以下は書かないよう にするといったことはできます.
以下の設定は任意です.好みに応じてしてください.
Gitで管理しないファイルを共通に設定するには,以下のような内容で ~/.gitignore をつくります(先頭にスペースは入れない).
$ cat ~/.gitignore *~ *.o *.so *.a
これを読み込むよう設定:
$ git config --global core.excludesfile ~/.gitignore
$ git config --global core.quotepath false
$ git config --global color.ui auto
$ git config --global core.pager 'lv -c'
(lv を使う場合.-c でカラー対応に.)
デフォルトは debian squeeze なら nano です.変えるには
$ git config --global core.editor vim
GPhys の git は http で公開されています. 以下のコマンドでクローンを取得できます.
git clone http://dennou-k.gfd-dennou.org/arch/ruby/products/gphys/git_repos/gphys.git
これでカレントディレクトリに gphys というディレクトリができます. これがあなたのローカルな gphys レポジトリとなります。 ただし http 経由では変更を電脳サーバーに送り込む (pushする) ことはできません。gphys の開発に参加する場合,下記のように ssh でアクセスしてください(see GPhys開発者むけガイド; 電脳サーバーにアカウントがあり ruby グループに入っていることが必要です。 グループへの参加は堀之内に依頼してください)。
http で取得した場合でも,積極的な貢献を歓迎します。 例えば,git diff でパッチを作り,メールで堀之内に送るなどしてください。
ローカルなレポジトリ上(上記のgphysディレクトリ内)で
rake build
とすると,gphys/pkg ディレクトリに gphys-バージョン名.gem という形の名前のファイルができます。そこで,
cd pkg gem install gphys-バージョン名.gem
とすればシステムにインストールされます。バージョン名 は gphys/lib/numru/gphys/version.rb に記述されています。 場合によっては,この中の定数 VERSION を編集して,バージョン名を 既存のバージョンと被らないように編集すると良いかもしれません。 具体的には バージョン番号の付け方 を参照してください。
なお,Gitレポジトリからのインストール法には,他にもいろいろあります。
電脳サーバーに ssh で接続してレポジトリーをコピーして開発し,成果を大元 のレポジトリ(originと呼ぶ)に反映する流れや,必要な設定を説明します.
電脳サーバー上の GPhys のレポジトリは作業ツリーを持たない bare レポジト リとして作成されています.作業するにはまず GPhys の Git レポジトリの clone を作ります.ローカルなマシンから ssh で接続して,適当なディレクト リ (git_reposとします) に作成します:
$ cd git_repos $ git clone -v dennou-k.gfd-dennou.org:/GFD_Dennou_Club/ftp/arch/ruby/products/gphys/git_repos/gphys.git
すると gphys というディレクトリができます.そこが作業ツリー (cvs でいう作業ディレクトリ)兼レポジトリです.レポジトリは gphys の下に .git という名前の(隠し)ディレクトリとして 作られます.
まずは cd して眺めてみましょう.
$ cd gphys $ gitk $ git log --decorate=short
gitk では,GUI によりログが表示できます.そこから git-gui を立ち上げる こともできます.git log はコマンドラインにログを表示しま す.--decorate=short をつけるとタグ情報も表示されます.表示には設定され いる pager (上記では lv -c) が使われます.それを避けたければ cat などに リダイレクトします). git log には他にも多数オプションがあります.
ブランチを確認してみましょう.
$ git branch * master
git branch はオプションなしだとローカルなブランチのみ表示します. master は cvs の trunk に相当するブランチです.初期は master ブランチの みとなります.ブランチ名の前の * は,現在選択(checkout)されてることを示 します.
$ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/master
git branch に -a オプションをつけるとリモートブランチも表示します(-r だ とリモートのみ). clone の元となったレポジトリは origin と呼ばれます. origin の mater ブランチ (origin/master) が clone の元となったブランチ です.
GPhysレポジトリで無視する(Gitで管理しない)ファイルの設定を見てみましょう.
$ cat .gitignore *.[oa] *~ *.so *.log Makefile ChangeLog
他に必要になれば加えてコミットできます(コミットの仕方はあとで説明).
.git ディレクトリにはローカルな設定も収められます:
$ cd .git $ cat config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* url = dennou-k.gfd-dennou.org:/GFD_Dennou_Club/ftp/arch/ruby/products/gphys/git_repos/gphys.git [branch "master"] remote = origin merge = refs/heads/master
この設定はレポジトリごとであり,最初から origin の設定とも異なります. 例えば origin のほうでは変更を受け取ったらメールで開発者に通知するよう になってますが,ここではそうなっていないのがわかるでしょう.また,origin は何であるかなどが設定されています.
バージョン番号は lib/numru/gphys/version.rb 中で定数 VERSION に設定します。リリース版では "1.4.3" などと つけます。開発版では次のようにつけていくものとします。 (後述する rake build では,ここで設定したバージョン番号のついた gem ファイルができます。)
2015年3月24日より,GPhys は Gitレポジトリにおいて gem パッケージを 生成するよう移行しました。Git 上の開発版を利用する際も,gem パッケージ作り,それをインストールして使います。 (従来の make install や ruby install.rb は廃止しました。 なお C による拡張ライブラリは extconf.rb ごと ext/numru/gphys ディレクトリに移しました。)
gemファイルの作成
rake build
による。gemファイルは pkg ディレクトリに gphys-バージョン名.gem といった名前でできます。バージョン名は lib/numru/gphys/version.rb で設定されます。開発版では "1.4.4.alpha" といった名前になっているでしょう (see バージョン番号の付け方)
gem ファイルのインストール
cd pkg gem install gphys-1.4.4.alpha.gem
などとします。
これでシステムにインストールされ,通常通り利用できます。 リリース版が出ると不要になるので gem uninstall gphys-1.4.4.alpha.gem などで削除するとよいでしょう。
CVS 時代は GPhys の ChangeLog は手書きで,コミット時に関係する ChangeLog の内容をメッセージに登録するというローカルルールにしてました. Git では ChangeLog はコミットメッセージから生成することとし,レポジトリ の管理対象からは外しました.
ChangeLog を手動で生成するには,作業ツリーのトップ(gphysディレクトリ) で次のようにします.
$ git log --branches=master --date=short --name-status --pretty=format:"%ad %an %d%n%B" > ChangeLog
ローカルに変更を commit したときや,origin から変更を取り込んで merge したときに ChangeLog が自動生成されるように設定しましょう.次のよう に,.git/hooks/post-commit と .git/hooks/post-merge というスクリプトと して設定します.
$ cd .git/hooks $ cat > post-commit #!/bin/sh git log --branches=master --date=short --name-status --pretty=format:"%ad %an %d%n%B" > ChangeLog ^D (Ctrl-D: 入力終了のため:上の2行のみのファイルとする.)
(先頭にスペースは入れない.)
$ chmod +x post-commit $ cp post-commit post-merge
単に git log だと,各コミットで変更されたファイル名が表示されないので, 次のようにするとよいでしょう.
$ git log --name-status
他に,個数を限る "-n 数字" オプションなどがあります.
暫定版です.変えるかもしれません.
基本は master. リリース専用のブランチは特に必要がなければ作らないことに します.手元での実験にはブランチは好きに作ってよいです(トピックブラン チ).実験がうまくいけば master に merge します.その際(masterが進んで いれば),rebase してからコミットするのがよいでしょう.Git は merge が 賢いので,気軽にトピックブランチが作れます.
トピックブランチをシェアしたりレビューしてもらうために origin に push するのは構いません. 「こんな開発をしてみたんだけど,どうなんだろう(いいんだろうか)」 という場合に役立つでしょう. トピックブランチの名前は feature/hoge などと, "feature/" を先頭に付けることを推奨します(Gitではブランチ名に / を挟めます). push されたトピックブランチは,検討の後,適宜 merge します。
トピックブランチ topic1 を master に merge します。
git checkout master git merge topic1
リリース版にはタグをつけます.命名規則は CVS 時代と同じです:
バージョンが 1.3.0 なら,タグは gphys-1_3_0
なお,cvs 時代のタグはそのまま残ってます.また,cvsにimportした スナップショット(ver 1.3.0)にcvsimportというタグをつけてあります.
作業ツリーで開発します.
ファイルを新しく作った場合(subdir/new.rbとします),
$ git add subdir/newe.rb $ git commit
こうするとエディターが立ち上がりますのでコミットメッセージを書いてくだ さい(必ず書いてください).エディター内には,コミットされるファイルが 表示されますので確認してください.なお,コミットされるファイルは自動的 に記録されますので,メッセージには書く必要ありません.
コミットメッセージは,-m オプションで与えることもできますが,コミットさ れるファイルの勘違いや,前のコミットのを間違えてそのまま使ってしまった りといった間違いが起きやすいので,もしも使うなら慎重にお願いします.
既存のファイルを更新した場合(subdir/hoge.rbとします),
$ git commit subdir/hoge.rb
または,引数なしで
$ git commit -a
こうすると Git 管理対象で変更されているファイルはすべてコミットされます.
なお,次で変更の登録だけしておいて
$ git add subdir/hoge.rb
あとでコミットしてもよいです:
$ git commit
変更の内容を具体的に書いてください.複数行で書いていいです.ChangeLog には改行も含めそのまま取り込みます.メッセージには内容だけを書けばよ く,日付や変更者は書かなくていいです.コミットに関わるファイルの名前も git log の --name-status を使って自動抽出します.
例えば次のようにします.(-m オプションを使う場合正しい内容になるよう注意.)
$ git tag -a gphys-1_3_1 -m "Version 1.3.1"
ローカルにつけたタグは .git/refs/tags にファイルとして保存されます. 上の場合,.git/refs/tags/gphys-1_3_1 というファイルができます.
ローカルなレポジトリの master ブランチを,origin の master ブランチに 反映するには,次を実行します.
$ git push origin master
デフォルトではタグは送信されないので,タグをつけた場合は
$ git push --tags origin master
でコミットします.これで通常のコミットの送信も一緒に行われます. --tags では(未送信の)タグがすべて送信されます.タグは次で一覧 できます.
$ ls .git/refs/tags/
もしも特定のタグ (名前を gphys-1_3_1 とします) だけ送信したければ,
$ git push origin master refs/tags/gphys-1_3_1
のようにします.
例えば feature/hoge という名前のトピックブランチを origin に送るにはこうします.
$ git push origin feature/hoge
もしもcommit してない更新があればcommitしておきましょう. さて git status で例えば以下のような状態になった場合
$ git status # On branch master # Your branch is ahead of 'origin/master' by 1 commit. # nothing to commit (working directory clean)
見掛け上はローカルな master は origin の master より 進んでる一方ですが,実は origin のほうも進んでいるかもしれません. git status やgit diff は通信をしませんので,比較対象はあくまで ローカルに取り込まれている origin の状態ということのようです. (なお,gphys の場合originが更新されると開発者にはメールが行きますので, 変更されてるかどうかは知っていることが多いでしょう.)
origin の本当の状態と比較するには,まず origin の変更を取得(fetch)します:
$ git fetch
例えば実際には(真の)origin は2つ進んでいたとすると次のようになります.
$ git status # On branch master # Your branch and 'origin/master' have diverged, # and have 1 and 2 different commit(s) each, respectively. # nothing to commit (working directory clean)
"have 1 and 2 different commit(s)" の前者(1個のコミット) とはローカルのもの,後者(2個のコミット)は origin に対するコミットです.
ここから先はブランチ間のやりとりの作業になります. いろいろやり方はありますが,まずはシンプルなパターンを (コンフリクトはないものとします).
現在編集中のブランチが master の場合に, origin の master の変更をローカルにマージします
$ git merge origin/master
コンフリクトがなければ成功します.手元の変更はもちろん保持され,status は次のようになります.
$ git status # On branch master # Your branch is ahead of 'origin/master' by 2 commits. # nothing to commit (working directory clean)
ローカルのコミットが 1つでなく2つ進んでると表示されましたが, 今回の merge 操作により,「マージコミット」が生じたためです.
この時点でもしも origin にアップしたければ
$ git push
とします.
(未作成)
実験的な(もしかしたら失敗するかもしれない)開発から単なるテストまで, とりあえず手元でブランチを切って開発し,うまく行けば master に取り込むというスタイルでの開発を行う場合について書きます.
以下,trial1 というブランチを作成する例です.
ブランチ作成:
$ git branch trial1
中身は master と一緒です.
そのブランチをチェックアウト:
$ git checkout trial1
確認
$ git branch master * trial1
この状態で編集しコミットしていくとブランチ trial1 が 更新されます(masterはそのまま).
ブランチ間の差分は次のように調べます
$ git diff --name-only master trial1 $ git diff master trial1
オプション --nane-only を指定すると,ファイル名だけ表示されます.
変更を master にマージするには,まず master をチェックアウトします:
$ git checkout master
このとき作業ツリーも master のものに戻ります.そして,ブランチの変更を マージします:
$ git merge trial1
その後はトピックブランチは消して構いません:
$ git branch -d trial1
トピックブランチを編集している間に分岐元のmasterブランチ (トランク相当) にコミットがあれば取り込みたいものです.もしも更新されたファイルが 重ならなければ衝突はないので,"rebase" します.すると masterブランチ の最新のコミットから分岐したようにトピックブランチがつなぎかわります. やり方は ( $ git checkout trial1 などでそのブランチに移行した上で)
$ git rebase master
です.
$ get fetch
をすると,origin にあるブランチはすべて取り込まれるので, 取り込みについては特にブランチを意識する必要はありません。 例えば,origin に新たに rubygems というブランチが作られると, 上記のコマンド実行のあとでブランチを調べると
$ git branch --all * master my_topic1 my_topic2 remotes/origin/HEAD -> origin/master remotes/origin/rubygems remotes/origin/master
のように表示されます。ここで注目するのは,当該ブランチは remotes/origin/rubygems として表示されますが, ローカルに rubygems はないということです。
差分をみるなど中身を調べるだけなら,この状態でできます。
$ git diff master remotes/origin/rubygems
もしもファイルの変更状況だけを知りたいなら次が便利でしょう。
$ git diff --name-status master remotes/origin/rubygems
このブランチを編集するには,まず checkout します。
$ git checkout rubygems Branch rubygems set up to track remote branch rubygems from origin. Switched to a new branch 'rubygems' $ git branch * rubygems master my_topic1 my_topic2
checkout 時のメッセージからわかるように,rubygems という ブランチが,rubygems と関連付けて作成されました。 すると,rubygems が手元で編集可能になりcommit 等出来ます。 origin に反映するには,git push します。
バージョン設定.ここはリリースするバージョンにあわせて変えて実行してださい:
$ version=1.4.0 $ tag=gphys-1_4_0
lib/numru/gphys/version.rb の更新。定数 VERSION の内容を 1.4.0 等と更新し,commitし,push する:
cat lib/numru/gphys/version.rb # 確認用 git commit lib/numru/gphys/version.rb -m "To release version $version (git tag $tag)" git push
タグ付け
$ echo git tag -a $tag -m "Version $version" (上のechoは次にすることの確認用。) $ git tag -a $tag -m "Version $version" $ git push --tags
ChangeLog生成
$ git log --branches=master --date=short --name-status --pretty=format:"%ad %an %d%n%B" > ChangeLog
Gem作成
$ rake build
リリース
rake release で行うはずだが未確認。