ホーム DoRuby git-svnによる実プロジェクトでのチーム開発

git-svnによる実プロジェクトでのチーム開発

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、SHIMADAです。Gitネタはたろちゃんに先を越されてしまいましたが、自分の環境でも、実際のプロジェクトでGitを実用的に使える状況になってきたので、そのへんについて書こうと思います。

 前提

前提条件として、

1. プロジェクトのためのsvnリポジトリがサーバーに用意されていること

2. リポジトリが

PROJECT_NAME/
 `- trunk/
 `- branches/
 `- tags/

というSubversionの標準的なディレクトリ構成となっていること

3. ローカルに最新のgitがインストールされていること

が条件となります。

前者が揃っていないという人は、まずSubversionを導入できるように社内での推進をがんばってください。

申請書とUSBメモリがないとコミットできないんだよ……、という人は、残念ながらあきらめてください。

(あれはネタだと信じていますが……)

後者が揃っていない人は、がんばってググってインストールして下さい。

 下ごしらえ

さて、条件が揃ったところで、下ごしらえです。

まずローカルで、gitの設定をしましょう。

$ git config --global user.name "your name"
$ git config --global user.email account@example.com
$ git config --global color.ui auto
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.br branch

git config だと カレントワーキングツリーの .git/config に書き込まれます。

  • global オプションをつけると、 ~/.gitconfig に書き込まれます。

このへんは適宜使い分けてください。

あと、 ~/.gitconfig をエディタで開いて直接編集してもいいと思います。

 リポジトリのClone

次に、プロジェクトのリポジトリからローカルのgitリポジトリにcloneしてきます。

git svn clone -s --prefix svn/ [svnリポジトリのURL] [作成したいGitリポジトリのPATH]

svnリポジトリのURLは、/trunk をつけないプロジェクトのルートまでを書くのが注意点です。

git svn の -s オプションが、自動的に trunk と branch を見分けて git のリポジトリにとりこんでくれます。

名前がないと説明に不便なので、リポジトリの名前を仮に決めておきたいと思います。プロジェクトのリポジトリURLhttps://example.com/svn/repos/myproj/ローカルのリポジトリPATH/home/me/src/myproj-git/

この場合、上記のコマンドはこうなります。

$ git svn clone -s --prefix svn/ https://example.com/svn/repos/myproj/ ~/src/myproj-git

これで、 myproj のgitリポジトリが myproj-git/ に作成されました。

内容を見てみましょう。

$ cd ~/src/myproj-git
$ find .
$ git br -a
$ git svn info

find すると、ローカルのファイルシステムになにがあるか一覧できます。

うまくいっていれば、チェックアウトされたワークツリーと、.git/ 以下のローカルリポジトリが見えるはずです。

git br -a は、リポジトリに含まれるブランチを一覧できます。

git clone に –prefix svn/ をつけたので、リモートブランチは remotes/svn/hogehoge という風に見えているはずです。

git svn info で、カレントのローカルブランチがsvn上のどのブランチに対応しているかが分かります。

clone直後はローカルブランチはmasterのはずです。これが、svn/trunkに対応していない場合は、masterを作り直してみてください。

手順は、

  1. リモートのtrunkに対応したブランチを仮の名前で作成してそこに移動する
  2. 現在のmasterブランチを削除
  3. 仮の名前をmasterにリネーム

です。具体的なコマンドは、下記のようになります。

$ git co -b master2 remotes/svn/trunk
$ git br -D master
$ git br -m master2 master
$ git co master

(この項目の情報源はこちら

全部ローカルでの作業なので、上流のsvnリポジトリには一切影響が出ません。

うまくいかなくても怖がらずに、何度でも繰り返して試せるので安心してやってみてください。

 作業用ブランチの作成

さて、これでプロジェクトのsvnリポジトリの完全なクローンが、手元にgitリポジトリとして作成されました。

もし、自分の割り当てられているタスクにsvnのブランチが割り当てられているなら、まずそちらに移動しましょう。

仮にブランチ名が ver02 だったとすると、手順はこうなります。

$ git co -b ver02 remotes/svn/ver02

このコマンドでやったことは、

https://example.com/svn/repos/myproj/branches/ver02 にあるブランチを元にしたローカルブランチ ver02 を作成してワーキングツリーにチェックアウト

です。

git svn dcommit は、デフォルトの動作としてローカルブランチと同じ名前のリモートブランチにコミットしに行きます。

ブランチ名 ver02 を合わせるのは、自分の分かりやすさと同時にgit-svnのためでもあります。

 開発環境の準備

つぎにやることは開発開発の整備です。

まず、必要なgemやライブラリをそろえた後、チェックアウトしたワークツリーで開発ができる状態になるまでコードや設定ファイルを修正することになるでしょう。

Railsならdatabase.ymlやenvironment.rbの修正などです。

いろいろ環境を設定して、script/serverが動くようになったら、ワークツリーがどうなっているか確認してみましょう。

$ git st

いろいろ表示が出てきたと思います。

既存の変更したファイルは

# Changed but not updated:

というセクションに、新しく作成したファイルは

# Untracked files:

というセクションに表示されます。

 開発

開発をはじめましょう。

新しいコードを書き始める前に、まずブランチをきってそちらに移ります。

$ git co -b new_feature

すると、

M  ファイル名

というなにか見慣れた表示が出てくると思います。

これは、git st で

# Changed but not updated:

に表示されていたファイルです。

ワーキングツリー上では変更されているけど、リポジトリにはまだ反映されていないという状態です。

そのまま開発を続けて、一段落ついたらコミットします。

まず git st してみましょう。

# Changed but not updated:
# Untracked files:

両方のセクションに、自分がコードを書いたファイルが表示されています。

まず、Untracked files: の中にある、コミットすべきファイルをgitに教えてあげましょう。

$ git add ファイル名

次に、

$ git diff

として、自分の作業を思い返しながら変更点を見返していきます。

ここで思わぬ見落としや、作業の抜け、ミススペルなどを見つけることができます。

この「作業の振り返り」はなかなかあなどれないものがありますので、忘れずにやっておきましょう。

間違いを見つけたらすぐに diff を抜けてエディタを起動し、直してまた git diff に戻ります。

出てきたファイルごとに、これで大丈夫という状態になったら、

$ git add ファイル名

します。addされたファイルは、

# Changes to be committed:

というセクションに表示されます。また、addすると次から git diff には現れません。

git diff して確認 → OKならgit addというサイクルでひとつづつ片付けていくのがおすすめです。

あと、environment.rb など、リポジトリに変更をコミットしたくないファイルもありますね。

これは、git addをしないで

# Changed but not updated:

に置いたままの状態にします。

ここが、svnなどの普通のバージョン管理システムと違うgitの大きなメリットのひとつです。

すべての必要なファイルを git add したら、ローカルの new_feature ブランチにコミットしましょう。

$ git ci -m 'コミットメッセージ'

ここで記入するコミットメッセージは、特別なことをしない限りsvnのりビジョンログにそのまま送信されますから、

開発チームのルールに沿ったメッセージを書くようにしてください。

 作業ブランチからのマージと上流へのコミット

new_featureの作業が一通り終わってうまく動いているようなら、ver02ブランチに作業内容をフィードバックしましょう。

$ git co ver02
$ git merge new_feature

マージが終わったら、ver02 に new_feature で行った作業が反映されているはずです。

テストも通って、チームのコミット基準に達しているようなら、リモートのsvnリポジトリにコミットしましょう。

まず、

# Changed but not updated:

にあるファイルをワーキングツリーから片付けないといけません。

$ git stash

これで、stashと呼ばれるリポジトリ内の格納場所に、これらのファイルの変更が保存されました。

もう一度 git st してみると、ワーキングツリーがきれいになっていることが分かります。

さっきの消えてしまった変更はどこに行ったのか?

$ git stash list

これで表示される場所にあります。元に戻したい場合は、

$ git stash pop

でいつでも戻りますから安心です。

では改めて、コミット作業に戻りましょう。

$ git stash
$ git svn fetch
$ git svn rebase

まず、fetch/rebaseでリモートリポジトリの最新の状態を持ってきます。

ここでコンフリクトなどが起きていたらリポートされますので、 >>>>> ====== <<<<< のようないつものマーカーをみつけて衝突を解消してください。

衝突したファイルは、git上では unmerged な状態になっていますので、解消したら git add して、解消したことをgitに教えてやります。

衝突がすべて解決したら、あらためてコミットします。

$ git svn dcommit

これでうまくいけば、svnリポジトリに今回の作業 new_feature が反映されているはずです。

trac/redmineやほかのsvnクライアントツールなどで、無事反映されているか確認してみて下さい。

うまくいったようなら、また開発に戻るために、さきほどstashに片付けた変更を手元に戻しておきましょう。

$ git stash pop

もし、dcommit しようとしてエラーメッセージが出てしまっても大丈夫です。

作業内容はすべて git の new_feature ブランチに残っていますし、リモートのsvnリポジトリには迷惑がかかっていません。

深呼吸して落ち着いて、エラーメッセージを読んで、ググって、試して…体で git を覚えて行って下さい。

have a nice git hacking!

記事を共有

最近人気な記事