GPhysのGitレポジトリの利用法

履歴

概要

この文書では GPhys の Git レポジトリの利用法について書きます.主に ruby グループに入っている開発者むけですが,読み出しだけなら http で誰でもできます (そして git で patch を作って開発者に送るかたちで開発にも参加できます).

Gitをはじめて利用する場合

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 "[email protected]"

コミットログにはここで設定した名前と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
Pager(端末に表示するプログラム)の設定:
$ git config --global core.pager 'lv -c'

(lv を使う場合.-c でカラー対応に.)

editor の設定

デフォルトは debian squeeze なら nano です.変えるには

$ git config --global core.editor vim

一般向けGPhysのGitレポジトリ利用ガイド

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レポジトリからのインストール法には,他にもいろいろあります。

GPhys開発者むけガイド

電脳サーバーに 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 uninstall gphys-1.4.4.alpha.gem などで削除するとよいでしょう。

ChangeLog 生成(設定説明有り)

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

logのチェック

単に 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 というファイルができます.

大元のリモートレポジトリ(origin)への反映

ローカルなレポジトリの 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

大元のレポジトリ(origin)の変更の取り込み

もしも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 に対するコミットです.

ここから先はブランチ間のやりとりの作業になります. いろいろやり方はありますが,まずはシンプルなパターンを (コンフリクトはないものとします).

マージ例1

現在編集中のブランチが 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

とします.

マージ例2

(未作成)

トピックブランチ

実験的な(もしかしたら失敗するかもしれない)開発から単なるテストまで, とりあえず手元でブランチを切って開発し,うまく行けば 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の更新をトピックブランチに取り込む

トピックブランチを編集している間に分岐元のmasterブランチ (トランク相当) にコミットがあれば取り込みたいものです.もしも更新されたファイルが 重ならなければ衝突はないので,"rebase" します.すると masterブランチ の最新のコミットから分岐したようにトピックブランチがつなぎかわります. やり方は ( $ git checkout trial1 などでそのブランチに移行した上で)

$ git rebase master

です.

originとトピックブランチをやり取り

origin上のブランチ

$ 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 で行うはずだが未確認。