ラベル 開発ツール の投稿を表示しています。 すべての投稿を表示
ラベル 開発ツール の投稿を表示しています。 すべての投稿を表示

2010/01/07

git リポジトリを HTTP で公開する設定でハマリました

私の関係しているプロジェクトで、空 git リポジトリを作成し、HTTP 経由でアクセス出来るように設定する必要がありました。

git リポジトリ HTTP 経由でアクセスできるように公開する設定方法に関しては、「Setting up a git repository which can be pushed into and pulled from over HTTP(S).が大変参考になります。また、ありがたい事に、このドキュメントは、Yuanyingさんによって日本語訳も公開されています。

既に過去何回か行った案件であり、且つドキュメントが整備されているにも関わらず、情けないことに再びハマってしまったので、いくつかポイントを整理しておこうと思います。

まずサーバ側の設定作業ですが、setup-git-server-over-http.txtに書かれている通り、概要は次のような手順になります。

1. HTTP サーバを用意する
2. 認証を含めた WebDav の設定を行う
3. リポジトリを準備する

「リポジトリを準備する」は、コマンドライン的にはこんな感じです。

% su
# cd /var/www  # HTTPサーバで設定したリポジトリの公開場所
# mkdir sample_rep.git
# cd sample_rep.git
# git init --bare
Initialized empty Git repository in /var/www/sample_rep.git/
# git update-server-info
# chown -R www . # HTTPサーバを動作させる user が www である場合

ポイントは「git update-server-info を実行すること」「パーミッションを正しく設定しておくこと」の2点で、非常にシンプルです。

このリポジトリを pull/push するクライアント側の設定手順は、以下の通りです。ここで、git クライアントは MacOS X 上の 1.6.6 を想定していますが、特に OS 依存の箇所はないかと思います。またサーバとクライアントの間には firewall は存在しないことを仮定しています。
  1. ~/.netrc を適切に設定する
  2. ユーザ名の含まれていない URL を用いて、リポジトリを clone する
  3. ローカルリポジトリへファイルを commit する
  4. リモート側のリポジトリとローカル側の参照を指定して push する
以下、これらの作業に関係して、私がハマってしまった事例とともにを説明します。

1. ~/.netrc を使うのであれば、URL へユーザ名を埋め込んではならない

認証の必要な http URL へ git でアクセスするには2つの指定方法があります。1つは、ユーザ名をURL内へ埋め込む方法で、もう1つは curl経由でのアクセスを利用し curl が参照する .netrc へ認証情報を書いておく方法です。

前者は、例えば、こんな感じになります。

% git clone http://username:password@server.example.com/sample_rep.git

とはいえ、URLへパスワードを直接書いてしまう方法は好ましい方法ではなく、あまり現実には使われないかと思います。

パスワードを埋め込まない指定も可能です。

% git clone http://username@server.example.com/sample_rep.git

この場合、別途パスワードの入力が求められます。

% git clone http://username@server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
Password: 

この方式の問題は、頻繁にパスワードの入力を求められることです。何度もパスワードを入力することは、危機意識が薄くなるので、あまり好ましいことではありません。

一方、ホームディレクトリへ .netrc というファイルを作成し、その中に認証情報を書いておく、という方式も利用可能です。HTTP アクセスで利用される libcurl がこの情報を参照し、適切に認証情報を送り出してくれます。

.netrc の記述方法に関しては、MacOS X では ftp(1) のマニュアルページに詳しいですが、基本的には、machine 行へ該当ホスト情報、login へユーザ名、password へパスワードを書いておきます。

% cat ~/.netrc
machine server.example.com
login n-miyo
password PASSWORD

このファイルが読まれてしまわないよう、パーミッションを 600 へ設定するなど、十分気を付けましょう。

.netrc を使う方法であれば、URL へユーザ名やパスワードを埋め込む必要はありません。

% git clone http://server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
% 

さて、~/.netrc が適切に設定されている状態で、前者の様に URL 内へユーザ名を埋め込んだ場合はどうなるのでしょうか。この場合、まずはパスワードの入力が求められることになります。もし、return を空打ちするなどにより、パスワードへ空文字が入力された場合には .netrc の設定が使われることになります(パスワードを入力した場合には、そのパスワードが利用されます)。

私は、はじめにユーザ名付きの URL でサーバへの接続性を確認をし、その後、~/.netrc を設定する、という手順を踏んでしまったため、どんなに正しく ~/.netrc を設定しても Password 入力プロンプトが表示され続けてしまうことになり、悩んでしまいました。

もし、.netrc を適切に設定したにも関わらず、Password を求められる状況になった場合には、リモートリポジトリの URL を確認してみてください。git remote -v で確認できます。

% git remote -v
origin http://server.example.com/sample_rep.git (fetch)
origin http://server.example.com/sample_rep.git (push)


2. 空リポジトリから clone した場合、初回 git push へは引数指定が必要

既に commit の存在する git リポジトリを clone した場合、この clone 元へローカルの変更を push する場合、特に引数を指定する必要はありません。

% git push
Fetching remote heads...
refs/
...

一方、今回のように、空の git リポジトリから clone により作成したリポジトリへ push する場合には、push 先と、push 対象の branch を明示的に指定しなければなりません。例えば、.git/config で「origin」として命名されているリモートリポジトリへ、ローカルの「master」ブランチを push する場合には、次の通りです。

% git push origin master

ただし、もちろん push する前には、ローカルのリポジトリへ何らかの commit が必要です。commit が存在しない場合、push はエラーになります

% git push origin master
error: src refspec master does not match any.
error: failed to push some refs to 'http://server.example.com/sample_rep.git'

私は git push の引数を正しく理解していなかったため、「clone 出来ているのだから、push できない筈はない」と、サーバの認証設定ばかりを疑い、時間をとられてしまいました。

空リポジトリから clone した場合、 git push へ失敗する場合には、push の引数で明示的に push に必要な情報が指定されているか、または、ローカルリポジトリへ commit が存在するかを確認しましょう。


3. 認証の失敗メッセージへ注意する

認証の必要な URL に対して git clone や push を行い、その動作が認証エラーになると、その旨を示すエラーが表示されます。

% git clone http://server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
error: The requested URL returned error: 401 while accessing http://server.example.com/sample_rep.git/info/refs?service=git-upload-pack

fatal: HTTP request failed

しかし、特定条件では、一見認証エラーなのか、設定エラーなのか戸惑うエラーが表示される場合もあります。

例えば HTTP サーバの WebDAV で「clone は誰でも可能だが push は禁止する」というような、すなわち clone 時には認証は必要ない、という設定がなされていたとします。この状態で、ローカルで行った変更を push しようとした場合、例えば .netrc の認証情報が誤っていると、git push は次のようなエラーを表示します。

% git push origin master
Unable to create branch path http://server.example.com/sample_rep.git/info/
error: cannot lock existing info/refs
fatal: git-http-push failed

先ほどと異なり、HTTP のステータスコードは表示されず、lock の獲得に失敗したことを示すエラーです。一見、HTTPサーバ側でのファイルパーミション設定誤りを疑いたくなりますが、実際パーミションの設定が誤っていた場合のエラーは次のようになります。

% git push origin master
Fetching remote heads...
 refs/
 refs/heads/
 refs/tags/
updating 'refs/heads/master'
 from 0000000000000000000000000000000000000000
 to   94d642b7e985ae90956700855e158d0e885628ba
Unable to lock remote branch refs/heads/master
Updating remote server info
PUT error: curl result=22, HTTP code=403
fatal: git-http-push failed

同じくロックに関するエラーメッセージが表示されていますが、こちらは最後に、HTTPステータスコードの403(Forbidden)も示されています。

私は、「lock が獲得出来ないのは、ファイルのアクセス権が問題だ」と誤った思い込みへ陥り、本来いじる必要のない、サーバ側のパーミション設定と格闘するハメになりました。

HTTPサーバへ Apache を使っている場合、例えば、httpd-access.log を見るとこの両者の判別がつけやすくなります。例えば認証が失敗している場合、MKCOL コマンドに対するステータスコードとして 401 が返ります。

192.168.1.1 - - [07/Jan/2010:21:26:47 +0900] "MKCOL /var/www/sample_rep.git/info/ HTTP/1.1" 401 401 "-" "git/1.6.6"

一方、HTTPサーバの設定を誤って書き込めない場合には、PUT のステータスコードが 403 を示します。

192.168.1.1 - n-miyo [07/Jan/2010:21:27:04 +0900] "PUT /var/www/sample_rep.git/info/refs HTTP/1.1" 403 234 "-" "git/1.6.6"

この差を頭の片隅に置いておくと、git push でエラーになった場合、原因究明の一助にはなるかもしれません。

一度設定できてしまえば http 経由での git アクセスは、快適に利用することが可能です。
これらの情報がトラブルシュートのお役に立てばと思います。

2009/11/15

変更コードが手元にある場合の git svn dcommit 方法

git は大変使い勝手の良い分散バージョン管理システムです。

様々な利点がありますが、私にとっては Subversion との連携機構が、標準機能とも呼べる位置づけで提供されている点が、いぶし銀のような渋さで、git の魅力を引き立てています。この機能のおかげで、Subversion を利用しているプロジェクトでも、手元では git を使って開発をすすめることが可能です。

さて git svn で Subversion リポジトリからコードを取得し、手元のコードを変更したとします。一部改変したコードを残したまま、つまり git add などで staging することなしに 既に git へ commit とした改変点を Subversion リポジトリへ push ようと、svn dcommit コマンドを使うと、
% git svn dcommit
Cannot dcommit with a dirty index.  Commit your changes first, or stash them with `git stash'.
 at /opt/local/libexec/git-core/git-svn line 485
とエラーになり dcommit できません。

この場合、エラーメッセージにも出ている通り、一旦 stash コマンドで現在の改変内容を脇へ押しやり、その後に dcommit、そして stash apply で押しやった内容をもとに戻す、という手順を経る事で問題へ対処できます。

% git stash
% git svn dcommit
% git stash apply

svn dcommit 時のエラーメッセージそのままなのですが、エラー発生時には動転するのか、心が読み飛ばしてしまうことが多いように感じます。

stash は svn との連携時以外でも大変便利なコマンドですので、頭の片隅においておくと良いのでは、と思いました。

2008/08/24

Enterprise Architect入門

勤務先でEnterprise Architectを使う必要が出てきたので、Amazon で検索して「はじめての ENTERPRISE ARCHITECT」と「UMLモデリングツール Enterprise Architect入門 〜基本操作完全マスター〜」を購入。

届いて中身を見て、後者は、前者のアップデート版だということに気がつきました。ぎゃー。って、上記Webサイトでは、しっかりと情報を公開して下さっているのですけれど (^^;。

内容は、うーん、もう少し踏み込んでもらえると嬉しかったかな、と言う感じ。本当に基礎的な点に注力して書かれているので、これを足がかりに自分で試して学習して行く、という位置づけなのかもしれませんね。

2008/08/13

Git - SVN Crash Course 邦訳

先日公開したSubversion FAQの邦訳は本家サイトのトップページへリンクを作成していただくと共に(有り難うございます!)、また、英語版ページとの相互リンクを張りました。

さて、今回は、GIT - SVN Crash Courseを翻訳してみました。

この春くらいから、ネットワーク的に切り離された幾つかの場所で開発を行う必要が生じた、そんな制約を支えてくれたのがGitです。「Subversionには馴染んでいるけど、Gitも触ってみたいな」という方のご参考になれば、と思います。もし、より深く使い方を知りたい方は、是非、Git ユーザマニュアル (バージョン 1.5.3 以降用)などを御参照下さい。なお、SVKではなくGitを使ったのは、環境的制約 & 趣味です (^^;

この邦訳、本当はSubversion FAQとの同時公開を目指していたのですが、なかなか時間が取れず、こんなに間隔が空いてしまいました。一方、忙しい中にありながら、精力的にコードやドキュメントを次々に公開するべく努力して下さっている方々もいるわけで、本当に頭が下がります! 有り難うございます。

2008/07/13

Subversion FAQ邦訳、本家サイトへ移動

Subversion FAQの邦訳を公開していますが、本家サイトに置かせて頂けることになったので、先ほど commit しました。

まだ暫定ではありますが<URL:http://subversion.tigris.org/faq.ja.html>から参照可能です。

修正案、コメントなど、何時でもお待ちしております。もちろん今後は、Subversionの開発者MLへ投稿していただいても構いません。

よろしくお願いいたします。

2008/06/24

Subversion FAQの邦訳を公開しました

Subversion 1.5がリリースされました。RCになってから何度も再パッケージが繰り返され、どうなるか、と思いましたが、無事に公開されて良かったです。開発者の方々、どうもお疲れさま
でした。

それに併せて、というわけではないのですが、Subversion FAQの邦訳を公開
しました。

語学力の無さで誤訳多数&なるべく日本語的な読みやすさを優先という感じで意訳も多数ですが、解釈間違いや誤訳、改訂案などありましたら、お気軽にご連絡下さい。宜しくお願いいたします。

2008/06/04

FreeBSD、Subversion へ移行開始

FreeBSD Project が SCM を CVS から Subversion への移行開始しを表明しました。

FreeBSDでは、public な箇所では CVS を、より内部的な開発では Perforce を使っていましたが、今回の移行は移行はこの public 用のリポジトリです。「少なくとも stable 系に関しては、support lifetime 中は、CVS tree を維持するからね」という堅実なアナウンスが、FreeBSDっぽいなぁ、と感じます。

基盤は CVS から Subversion へ、と、ある意味、順当な変更となりました。一方「ports などに関しては未定」と書かれていますので、これらがどうなるのかも、興味があります。いっそのこと、全部 SCM を変えてくれると、楽しいのですが(おぃ)。

しかし、14年間の歴史が詰まったCVSの移行は、本当に大変だったのでは、と思います。これを実現したこと、また、cvs2svnがこの作業に耐えたことは、両者とも、賞賛されるべきだなぁ、と感じました。

お疲れさまでした。

2008/05/17

NFS + FreeBSD で Subversion を使うときには、1.5.0 以降を利用しよう

Subversion のリポジトリをNFSサーバ上に置き、その領域を FreeBSD から mount して使う場合、1.4.x の Subversion が では問題が起きる場合があります。

具体的には、
  • Subversion のリポジトリが NFS サーバ上にあり、FreeBSD からは mount_nfs している。
  • mount_nfs をしている FreeBSD には、Subversion 1.4.x 以前がインストールされている。
  • 適当なクライアント(バージョン/OSは問わない)から、一定個数以上のファイルを commit する(schemeは、file、svn+ssh、httpを問わない)。
という条件がそろうと、
svn: Can't remove 'db/transactions/1-1.txn': Directory not empty 
というエラーメッセージが表示され、commit が fail してしまうことがあります。実際には commit 自体は成功し、ファイルの後片付けに失敗しているだけなのですが、ディレクトリ使用量が無駄に増加します (^^;。

原因は、FreeBSD の getdirentries(2) が、open されているディレクトリ内のエントリが削除された場合、それを上手くハンドリングできないためです。

この現象は、当初MacOS X上の問題として報告され、MacOS Xでのみ対策が施されました。

その後、同じ問題がFreeBSDでも発生することが報告され、それを受け、r20459では、修正範囲がOS非依存の形式へと拡張されました。但し、残念ながら、この修正は、当時の trunk へのみ commit されており、1.4.xには反映されていません。

幸いにして、上記修正の取り込まれたSubversion 1.5.0のリリースが間近に迫っています。もし上記現象で困っている場合には、1.5.0の利用を試してみてはいかがでしょうか?

2008/05/12

SubversionのリポジトリをNFS上で

Subversion の repository を NAS 上へと移行させ、その領域を NFS として export し、FreeBSD で NFS mount して運用することにしてみました。勿論、Subversion のバックエンドは FSFSです(BerkeleyDB で NFS は危険だよ)。

可動実験として commit を試してみたところ、
svn: Can't get exclusive lock on file '/foo/bar/reps/db/transactions/0-1.txn/rev-lock': Operation not supported
というメッセージが。しばし、悩んでしまいました。

原因は、FreeBSD側で lockd/statd をあげていなかったこと。今まで、この NFS サーバは、暫定的試用でしか使っていなかったため、設定が漏れていたようです。うーん、間抜けだ。lockd に頼るのは危険、とは分かっていますが、意味なく完全 disable はマズイでしょう...。

/etc/rc.conf に
rpc_lockd_enable="YES"
rpc_statd_enable="YES"
と書いたところ、無事 commit 出来るようになりました。良かった、良かった。

ちなみに FreeBSD で、該当ファイルシステム上に exclusivelock 付きのファイルが作れるかどうかは、lockf(1) を使うのが簡単です。

lockf(1) では、open(2) にO_EXLOCK つけて lock の確認を行っています(rev 1.11.8.1)。apr-1.2.8 では、HAVE_FCNTL_H がenable されていれば、exclusive lock は fcntl(2) の F_WRLCKで行いますから、結果、同じになる、というわけです。

例えば上の状況だと、
% cd /foo/bar
% lockf foo test
lockf: cannot open foo: Operation not supported
という感じになりますから、あぁ、lockd 問題か、と簡単に気がつくことが出来ました。便利便利。

2008/05/08

Rietveldが来る!

Google内部で使われている、非常に有名なコードレビューツールMondrian。このツールは、Google社内の技術を積極的に有効活用している為、社外への公開は難しいとされてきました。

それが、作者じきじきの手によりGoogle AppEngine向けOpen Sourceとして書き起こされ、Rietveldという名前で公開されるそうです! やったー!

Mondiranは、数年前Googleの方に存在を教えて頂き「凄く便利。Google Videoに紹介動画があるから見てみな」と教えて頂いて、そのビデオを見てから、ずっと興味を持っていたので、本当に本当に嬉しいなぁ。

Mondrianには、例えば「Google社内では、各自のホームディレクトリがNFS共有なのを利用して、他人の手元に置かれているコードを自由にレビュー対象にする」など、いろいろなワザが実装されていると聞きました。その辺りも、どのように実現されているか楽しみです。わくわく。

というわけで(至る所に貼られている)Mondrianの紹介ビデオです。


2008/03/20

viewvcの漢字コード変換パッチ

viewvcは大変便利なソースコードブラウジングツールです。変更差分など、軽く見たいときに、大変重宝します。

残念ながらログやコードに、UTF-8以外の文字コードが含まれている場合(つまり、EUC-JPとかで書かれた日本語文字列が含まれている場合)、ContentTypeのCSがUTF-8と指定されている関係から、ブラウザ上では、所謂「文字化け」が発生したかのように見えてしまいます(文字コードを選択し直せば大丈夫)。また、コードと commit log の文字コードが異なっている場合などにも、いやな事が起こります。

但し、幸いにしてmuciusさんが日本語文字コードをUTF-8化するパッチを公開してくださっていまして、このお陰で、大変便利に過ごすことが出来ています。

先日試用していたら、元のコードがマルチバイト文字での文字コード変換を意識していない為(当たり前)、一部漢字の泣き別れが発生してしまう箇所がありましたので、小さなパッチをお送りしたら、早速採用してくださいました。

こういった献身的なボランティアの方々のお陰で、我々は快適に開発を勧めることが出来ているわけで、まさに、日々感謝なのです。どうも有り難うございます。

2008/02/01

cvs2svn

現在CVSで運用しているSCMをSubversionへ移行させる為にcvs2svnを試用。

リポジトリ規模が小さいこともあり、変換は30分弱、1500コミット足らずで問題なく終了。これならば、本番も良い感じで時間内に終わりそう。branchとtagの再現も期待通りで、本当に便利です。感謝。どちらかといえば、既存のリポジトリ内に特殊なファイルが多かったので--auto-props用設定を洗い出す方が大変でした。

しかし、こんなに良いツールなのに、もともとcvsログをまともに書いてないプロジェクトだったので、有り難み半減。くぅー。

2008/01/30

Bugzilla

久しぶりに、自前でBugzillaを立ち上げる。
バージョン3系をインストールするのは初めて。2系に比べてずいぶん簡単になっていてびっくり。開発者の皆様、ありがとうございます。
運用ルールを書いていて、今回もVERIFIEDとCLOSEDの定義に悩む。専任のSQAさんとかいる開発ならば、定義しやすいんだけど。
また、イテレーション毎の管理用に使おうかな。