ラベル Git の投稿を表示しています。 すべての投稿を表示
ラベル Git の投稿を表示しています。 すべての投稿を表示

2013/05/20

既存gitリポジトリで、親の存在しないbranchを作成する

gitでbranchを作成するには、git branch、またはgit checkout -bを使いますが、稀に、他のcommitから派生していない、すなわち親の存在しないbranchを作りたいことがあります。

例えば、既存branchで各種実装検討を行い、方向性が見えたあとで、 新規にcommitを組み直したい、といった場合です。また、ソースコードの新規公開へむけて、過去の履歴を含まないbranchを新規に作成したい場合にも使えるかもしれません。

このためには、次のコマンドが使えます
git checkout --orphan <branch-name>
これで親のいない、まさにorphanなbranchを作ることができます。

なお、このコマンドを実行してもworking treeへ含まれているファイルは消えません。

2010/09/06

HTTP 経由の git push で lock エラーへ対処する

プロジェクトでHTTP 経由の gitを使っています

生憎サーバのディスクが壊れてしまったので、OSのアップデートを
含め入れ替えを行ったのですが、それ以後、git push で lock エ
ラーが発生するようになってしまいました。
% git push
error: cannot lock existing info/refs
fatal: git-http-push failed
パーミション問題かな、と該当 repos にある info/refs のパーミションを確認しましたが、問題ないようです。
# ls -la
total 64
drwxr-xr-x  2 www  admin  16384 Jul 15 16:52 ./
drwxr-xr-x  7 www  admin  16384 Jul 15 16:42 ../
-rw-r--r--  1 www  admin    240 Jul 15 16:42 exclude
-rw-r--r--  1 www  admin    175 Sep  3 07:43 refs
ヒントは httpd-error.log    にありました。エラー発生時のログを見てみると以下のメッセージが書かれていました。
[Fri Sep 03 07:39:53 2010] [error] [client 137.153.67.138] Could not LOCK /scm/git/p/foo.git/info/refs due to a failed precondition (e.g. other locks).  [500, #0]
[Fri Sep 03 07:39:53 2010] [error] [client 137.153.67.138] The locks could not be queried for verification against a possible "If:" header. [500, #0]
[Fri Sep 03 07:39:53 2010] [error] [client 137.153.67.138] Could not open the lock database.  [500, #400]
[Fri Sep 03 07:39:53 2010] [error] [client 137.153.67.138] (13)Permission denied: Could not open property database.  [500, #1]
「info/refs を lock したかったが、他の lock など、その前提条件で失敗した」と読めます。なるほど、WebDav 自体の lock が怪しそうです。私は WebServer に Apache を使っていますので、該当する設定ファイルを確認してみました。
# cd /usr/local/etc/apache22/extra
# grep -i lock httpd-dav.conf
# on the directory where the DavLockDB is placed and on any directory where
DavLockDB "/usr/local/var/DavLock"
# ls -ld /usr/local/var/
drwxr-xr-x  3 root  admin  512 Sep  3 07:43 /usr/local/var/
実際 httpd が書き込めないパーミションになっていることがわかりました。OS再インストール時に確認を怠ったようです。このパーミションを正しくする、または、DavLockDB ディレクティブのパスを適切に変更すれば問題解決です。

なお DavLockDB へ指定するのはロックデータベースへのフルパスであり、ディレクトリではありません。書き込み権限などを確認する場合には、ロックファイルの書き込まれるディレクトリへ注目しましょう。

私はディレクティブへディレクトリを指定するものだと勘違いし、自分で掘ったディレクトリのパーミションへばかり気を取られ、しばらくはまってしまいました。なお、設定後には、Apacheの再起動が必要になります。

HTTP 経由の git push で lock エラーになってしまった場合には、repos のパーミションだけではなく、WebDAV の設定も確認してみると良いと思います。

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/13

Git - SVN Crash Course 邦訳

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

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

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

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