A Way of Code

興味の赴くままに書き綴っていきます。

GitをupgradeしたらWarning: Non-libraries were installed to "lib".と表示された

結論:気にするな
(Conclusion: Ignore it.)

homebrewからgitをupgradeしたら、Warningが出たので調べてみました。

  1 ==> Caveats
  2 Bash completion has been installed to:
  3   /usr/local/etc/bash_completion.d
  4 
  5 The 'contrib' directory has been installed to:
  6   /usr/local/share/git-core/contrib
  7 Warning: Non-libraries were installed to "lib".
  8 Installing non-libraries to "lib" is bad practice.
  9 The offending files are:
 10 /usr/local/Cellar/git/1.7.9.3/lib/Git.pm
 11 ==> Summary
 12 /usr/local/Cellar/git/1.7.9.3: 1155 files, 23M, built in 98 seconds

気にするな、と言われても気になってしまう方は、警告の表示をみていきましょう

1-6行目のCaveats

#caveartsは「注意」という意味で、何かを利用するとき等に誤解させないための注意喚起のために使われたりしますね。warningほど重大じゃない感じ。
CaveatsはHomebrewの機能で、Formulaをインストールするときのプロセスとして一番最後に処理されます。Caveatsを表示したい場合は、Formulaにcaveatsメソッドを実装します。
んで、GitのFormulaでは、caveatsメソッド内で、2-6行目のメッセージしか作っていないので、7行目以降はCaveatsによるものではないですね。
GitのFormualをみると、2-6行目は必ず出力されるようになっていて、

  • Bash completionは/usr/local/etc/bash_completion.dにインストールしておいたからね!
    • Bashで自動補完をするためのスクリプト。zshな方は使っちゃダメ
  • contribディレクトリは/usr/local/share/git-core/contribにインストールしたよ!
    • contribは本体ではない付属品・寄贈品を入れておくディレクトリ。

という意味。#改めて書く程のことでもないけど、何故か自然と筆が進んでしまう

7-10行目のWarning

これが気になったところ。
adamv氏によると、推奨されていない場所に何かをインストールした場合に、それを検出する仕組みをHomebrewに設けたらしい。
https://github.com/mxcl/homebrew/issues/10562

今回は、/usr/local/Cellar/git/1.7.9.3/lib/Git.pmというライブラリファイルではないものが、本来ライブラリを入れるべきlibディレクトリにインストールされて、警告が出たようです。(これは本来、./lib/site_perl/に入れるべきものかなぁ。)
どちらかと言うと、Homebrewの利用者側に対する警告ではなく、Formulaの作成者側に向けた警告のようですね。

#ちなみに、この検知によるissueの投稿が多いので、検知の仕組みを外そうかと思っているらしい。

11-12行目

インストールが成功したときに表示されるいつものメッセージですね

ということでした

Gitの用語

Gitの用語集は既にあるのですが、Gitのエントリを書いていたら軽く用語集になっていたので分離しました。

リポジトリの中身等については言及していないので、以前まとめたGitの仕組みと併読するといいかもしれません。
公式の資料から定義を引っ張ってきたわけではなく、こういうことかな、と思ったことをまとめただけなので間違っているところがあるかもしれません。

リポジトリ (repository)

  • オブジェクトの貯蔵庫。Gitではファイルやディレクトリ等々をオブジェクトとして表現する
  • オブジェクトにはblobオブジェクトやtreeオブジェクト等がある

クローン (clone)

  • サーバにあるリモートリポジトリをローカルにコピーすること

origin

upstream

ステージングとステージングエリア(Index)

  • 修正作業によって更新したもののうち、コミット対象の更新を選り分けるための作業。またその領域
  • ステージングエリアの実体は、ステージに上がったオブジェクトを指し示すオブジェクトIDが詰まったバイナリファイル(Indexというファイル)

revert

  • ステージングエリアに追加した変更を戻すこと

コミット (commit)

  • 更新を確定すること
  • 仕組み的には、更新によって作られたGitオブジェクトに対してtreeオブジェクトとcommitオブジェクトを付与すること

ブランチ (branch)

  • 概念的には木の幹(master)から生えてる枝。CVSのモジュールやSVNのtrunk+branchesに近いけど、遥かに柔軟
  • 仕組み的に言うと、リポジトリ内のオブジェクト群に対するオブジェクトグラフをツリーに見立てた時、特定のノードから辿れるオブジェクト群のこと。また、その特定のノードを指し示すポインタ
  • コミットをするとポインタが動く
  • DQNEO氏曰く、「別宇宙」

タグ (tag)

  • リポジトリ内のオブジェクト群を引っこ抜いてくるための目印
  • 一見ブランチと似ているが、ブランチとは異なり、指し示す場所が変動しない

HEAD

  • 現在チェックアウトされているブランチを指し示すポインタ

追跡/トラック (track)

  • Git上で変更内容を追跡できるようにすること
  • ファイルやディレクトリに対して言う場合は、Gitオブジェクトに変換してリポジトリに格納することを指す。リポジトリに管理されていないファイルはUntracked Fileである
  • 特に、ローカルブランチとリモートブランチとを紐付けすることを指す。ローカルにリモートブランチ(ポインタ)を作成し、Gitの設定ファイルにローカルブランチとリモートブランチとのリンクを設定する。

作業ツリー (Working Tree)

  • ブランチ内から作業ディレクトリに展開されたファイル・ディレクトリ郡のこと

チェックアウト (checkout)

  • ブランチから作業ツリーにファイル・ディレクトリを展開すること
  • このとき、ステージエリアも切り替わる

マージ (merge)

  • 当該ブランチに対して別のブランチの差分を取り込むこと

リベース (rebase)

  • マージの一種。当該ブランチの更新差分を無かったことにして、別ブランチの最新を取り込んだ後、当該ブランチの更新差分を適用する処理

チェリーピック (cherry-pick)

  • マージの一種。全ての差分を取り込むのではなく、特定のコミットを指定して取り込む。
  • いまマージすると恐ろしいことになるけど、この変更だけは取り込んでおかないとこっちの作業ができない、なんてときに使う
  • 意味:いいとこ取り

競合 (conflict)

  • マージ(リベースを含む)の際に、同一のファイル・ディレクトリに対しての更新が発生していること。通常、競合を解消するために修正作業を行う

フェッチ (fetch)

プル (pull)

  • フェッチを行い、さらに現在チェックアウトしているブランチに対してマージを行うこと
  • 使用例:「それプルっちゃって」「プルってないじゃん」

圧縮コミット(squash)

  • 複数のコミットを1つのコミットにまとめること
  • バグが入り込んだコミットを無かったことにしようとしてコミットをまとめたとしても、リポジトリにはちゃんとオブジェクトの残骸が残っている(そのオブジェクトに対する参照が外れるだけ)

二等分 (bisect)

  • 二分探索の要領で、バグが入り込んだコミットを突き止める作業
  • bisectコマンドでコミットにマーキングしながら探索する
  • 探索している間、まわりがドキドキしているのは気のせいではない

GitHub

Fork(フォーク)

Pull Request

  • GitHubのサービスで、相手に対して自分のブランチをpullしてもらうように要求する機能

本家

  • GitHubにおいて、フォーク元のこと

GitHubからSSHキーを検査しろ、って言われた

GitHubから"Action Required - SSH Key Vulnerability"という件名のメールが送られてきました。

以下のページで、身に覚えのないSSHキーをRejectしてください。
自分が設定したSSHキーであれば承認してください。
https://github.com/settings/ssh/audit

確認方法

GitHubにログインして、SSHキーの確認ページを開きます。
https://github.com/settings/ssh/audit

表示されたfinger printが自分が作成したSSHキーのfinger printと同一かを確認します。
finger printを確認するには`ssh-keygen -l `を実行します。

ssh-keygen -l 
Enter file in which the key is (/Users/toggtc/.ssh/id_rsa): ※SSHキーファイルのパスを入力

すると、finger printが表示されますので、確認ページに表示された内容と同一のものか確認します。

GitHubから届いたメールの内容

#ざっくり意訳します

不定のGitHubアカウントに新しいSSHキーを追加できるセキュリティの脆弱性が発見されました!
この脆弱性はread/write権限付きでリポジトリへのclone/pullアクセスが出来ます。
日本標準時 3/4(日) 午前 8:53、この脆弱性は無くなりました。
既知の悪意のある活動は報告されていませんが、その一方で、全ての既存のSSHキーの検査を強制する追加の予防策を講じています。

っつーわけで、以下のことを行なってください。

要求されたアクション:

次のサイトに行って、あなたのGitHubアカウントに関係するSSHキーを確認してね。
https://github.com/settings/ssh/audit

※訳注:身に覚えのないSSHキーをRejectして、ってこと。

SSHキーを承認しないと、リポジトリに対してclone/pull/pushができないよ!

状況:
私どもはセキュリティを真摯に受け止めて、問題が起こらなかったと認識しています。
十分なコード検査に加えて、あなたのアカウントのセキュリティを増強する次の手段を取りました:

  • 全ての既存のSSHキーの検査を強要しています
  • いま新しいSSHキーを加えるとパスワードを要求します
  • 新しいSSHキーがあなたのアカウントに加えられればemailを送ります
  • Account Settingsページからアカウント変更のログを確認することができます

iPad3の解像度と本のサイズと重さ

iPad3が発表されましたね。自炊族としては解像度が気になるところです。
※数式の画像が前後逆になっていたので修正しました。

iPad3は本の代替になるのでしょうか。
iPad3は2048x1536で9.7インチの大きさなので、およそ264dpi (正しくはppi)となります。技術仕様にもそう書いてありますね。
http://www.apple.com/jp/ipad/specs/

#MacBook Pro Mid 2010 13.3inchの解像度が1280×800で113dpiですから、iPad3に搭載されたディスプレイの解像度がいかに高いかが伺えます。

iPad3の表示サイズ

まず、iPad3のディスプレイ部分の高さ(長辺)/幅(短辺)のサイズを求めてみましょう。

f:id:toggtc:20120309184442p:plain
このとき、iPad3の対角は9.7inですから、
f:id:toggtc:20120309184456p:plain
となります。

264dpiで長辺197.10mm×短辺147.83mm!
A5サイズが長辺210mm×短辺148mmなので、264dpiのクオリティのA5資料が等倍表示で読めるってことですよ!若干はみ出してしまうのが惜しいですが。

ところで、ドキュメント印刷時の標準的なクオリティは300dpiですよね。(偏見?)
300dpiクオリティを求めると、どのぐらいのサイズになってしまうのでしょうか。
f:id:toggtc:20120309184508p:plain
300dpiクオリティで長辺173.48mm×短辺130.05mmのものを等倍表示すると、画面いっぱいになるということですね。

本のサイズと比較してみる

一般的な書籍のサイズと比較してみましょう。

iPad3の等倍表示サイズ:

  • 264dpiクオリティ:長辺197.10mm×短辺147.83mm
  • 300dpiクオリティ:長辺173.48mm×短辺130.05mm

一般的な書籍のサイズ:

  • B5: 257mm×182mm
    • 専門書、よくあるキャンパスノート、WEB+DB PRESSあたりの雑誌、『詳解 Linux カーネル』あたりがこの大きさ。ちょっと厳しいですね。
  • A5: 210mm×148mm
    • 専門書等、『Binary Hacks』、『Linuxカーネル Hacks』あたりがこの大きさ。
  • ドラッカー本: 192mm×138mm
    • 参考までに、『7つの習慣』とかカーネギー本、ドラッカー本あたりは、四六判よりやや大きい。
  • 四六判: 188mm×127mm
    • ビジネス書でよく見かけるサイズ。よくあるポケットリファレンスもこのサイズが多い。
  • B6: 182mm×128mm
    • 単行本等、ビジネス書の中にたまにこのサイズが混じっている。
  • 新書判: 182mm×103mm
    • よくある新書本、『脳が冴える15の習慣』とか。十分読めるサイズです。
  • A6: 148mm×105mm
    • 文庫本、余裕のサイズですね。

本棚の場所をとるB5サイズの本をスラスラと読むのは、まだ少し厳しいようです。
ビジネス書をよく読まれる方は、是非買いなのではないでしょうか。

ちなみに、300dpiクオリティでA4サイズの資料を等倍表示で閲覧しようと思ったら、3507×2481ぐらい欲しい。

本の重量と比較してみる

#体重計で計ったので、正確じゃないかも。。

重たい専門書を常に持ち歩く方にも、iPad3は良さそうですね!

本を複数冊常に持ち歩いていて、A5サイズ以下の専門書やビジネス書を中心に読まれる方にお勧め、ということになりました。
逆に、普段は文庫本や新書を1-2冊程度持ち歩く人には、重たいだけになるかもしれませんね。
なお、本に書き込みをする方は、iAnnotate PDFを使うと幸せになれるかもしれません。

Gitの仕組み - homebrewをフォークするためのGit&GitHub入門 中編

前回:Gitのセットアップ

前回、GitHubを使うためのセットアップをしていきました。
今回はGitとGitHubを学んでいきます。
(さらに次回はhomebrewをforkしていきます)

注意:

  • Gitを知らない人がいきなりGitHubを触ったときのメモなので、間違っているところがあるかもしれません。
  • CVSSubversion等のバージョン管理ツールの知識がある前提で書いています。
  • あくまでメモなので説明が至らないところが多々あります。ざっと読み流して、Gitを実際に触ってから読み返したほうが分かりやすいと思います。

1. Gitの構成

Gitは大きく分けて、リポジトリ、ステージングエリア、作業ツリーから構成されます。
f:id:toggtc:20120305020212p:plain

作業ツリー上で編集したファイル・ディレクトリの中からコミット対象のものをステージングエリアに持って行き、その後、コミットをすることでリポジトリに更新内容が格納されます。

1.1 リポジトリ

リポジトリはObject Store(オブジェクト格納領域)とも呼ばれます。
リポジトリというと、Object Storeよりやや広い響きがありますが、ここではリポジトリ=Object Storeとして表現します)

Gitのリポジトリは、概念的には単数または複数のブランチで構成されています。
f:id:toggtc:20120305020235p:plain

ブランチと聞くとSubversionを知っている方は、"trunk"と"branches"を思い浮かべるかもしれませんが、Gitの場合は"trunk"に相当するものが"master"ブランチなのです。masterブランチは、Gitリポジトリを作成する際にデフォルトで作成されるブランチで、名前はmasterである必要はありません。ですが慣習のため、他の人がみて分かりやすいようにmasterという名前にしておくことをお勧めします。

Gitのリポジトリは以下に示すblob, tree, commit, tagsというGitオブジェクトが保持されています。
個々のGitオブジェクトにはSHA-1によるオブジェクト名(オブジェクトID)が付与されます。

1.1.1 blobオブジェクト

blobオブジェクトは、ざっくり言ってしまうとファイルコンテンツに対応するオブジェクトです。
例えば、新たに"hello.txt"というファイルをリポジトリに追加したとすると、Gitでは"hello.txt"ファイルの中身をblobオブジェクトとして保管します。
f:id:toggtc:20120305020253p:plain

1.1.2 treeオブジェクト

treeオブジェクトはディレクトリに対応するオブジェクトで、当該ディレクトリに格納されたファイルに関するオブジェクトのIDやパス等の情報を持っています。
ディレクトリの中にサブディレクトリがある場合、そのサブディレクトリはまた別のtreeオブジェクトとして扱われます。
例えば、新たに"foo_dir"というディレクトリを追加すると、Gitではtreeオブジェクトとして保管します。
f:id:toggtc:20120305020303p:plain

1.1.3 commitオブジェクト

当該コミットに対応するリビジョンの情報を保持するオブジェクトです。
コミット時点のトップレベルのtreeオブジェクトのID、commuterやauthor、日付、コミットメッセージ等の情報が格納されています。また、親commitオブジェクトを保持しており、親を辿っていくことでHistoryが分かります。
以下に、コミットを行った時のGitオブジェクトの例を示します。

1度目のコミット:

  • hello.txtを新規作成し、ファイルの中身を"hello, git"としている

f:id:toggtc:20120305020314p:plain


2度目のコミット:

  • hello.txtはそのまま
  • 新たにfoo_dirディレクトリを追加
  • foo_dirディレクトリ直下にfoo.txtを新規作成し、ファイルの中身を"foo"としている

f:id:toggtc:20120305020328p:plain

1.1.4 tagオブジェクト

tagオブジェクトはコミットオブジェクトを指し示すオブジェクトです。
タガー(タグ付した人), 日付、メッセージ、コミットオブジェクトへの参照等が保持されています。
f:id:toggtc:20120305020342p:plain

1.2 ステージングエリア

ステージングエリアはIndexとも呼ばれます(さらに以前はcacheとも呼ばれていたようです)。
ステージングエリアは、ステージングと呼ばれる作業を行うための領域で、位置的にはリポジトリと後述する作業ツリーとの間にあります。
ステージングと聞くと、インフラな人は本番環境に移行する前のステージングの段階を連想するかもしれません。Gitのステージングもそれと似ていて、リポジトリにコミット(本番環境への移行)をする前に、ステージングエリア(ステージング環境)で確認を行います。
主な確認作業は、作業ツリー上での変更のうち、どの変更をリポジトリにコミットするかを選定する作業です。このステージング作業によって不用意なコミットを避けることが出来ます。
これらの操作は、git addによって行います。追加あるいは修正したファイルをgit addすることで、ステージングエリアに変更が追加されます。

ステージングエリアの中身は.gitディレクトリの中にある「index」というバイナリファイルです。このファイルには、ファイル名やファイルに対応するblobオブジェクト名、データの一覧等が保持されています。
リポジトリに保持される各種GitオブジェクトがImmutableなのに対し、ステージングエリアはMutableなバイナリファイルになっています。

以下の例では、hello.txtの内容を"hello, 1.1"から"hello, 1.2"へ変更しています。
f:id:toggtc:20120305020405p:plain

上記の図ではcommitをした段階で、"hello, 1.2"に対応するblobオブジェクト"6ccfdb"がObject Storeに追加されているように見えますが、厳密にはaddした段階で追加されています。そして、コミットした段階でツリーに"6ccfdb"が追加され、さらにcommitオブジェクトが付与されるのです。言い換えると、コミットを行うということは、追加あるいは修正したファイルへの参照を持つツリーを作成するということになります。
このことを、オブジェクトグラフで見てみましょう。

まず、最初の状態です。hello.txtの中身として"hello, 1.1" (65c2bb) が参照されています。
f:id:toggtc:20120305020422p:plain


次に、hello.txtの内容を"hello, 1.2"に変更し、ステージングエリアに追加( git add )します。
すると、"hello, 1.2"という内容に対して6ccfdbというオブジェクト名のblobオブジェクトがリポジトリ(Object Store)に追加されました。まだコミットはしていません。
f:id:toggtc:20120305020437p:plain

そしてステージングエリアでは、hello.txtの参照先として、6ccfdbが設定されています。
f:id:toggtc:20120305020444p:plain

この段階では、"hello, 1.2" (6ccfdb) はツリーから孤立しています。
ここでコミットを行います。すると、ステージングエリアの内容どおり、hello.txtの内容は6ccfdbに置き換えられます。これは65c2bbから6ccfdbへオブジェクトの参照先が変わるということになるため、6ccfdbを参照するツリーが新たに作成されます
さらに、新たに作成されたtreeオブジェクトに対してcommitオブジェクトが付与されています。
f:id:toggtc:20120305020456p:plain


なお、ステージングエリアを表示するには、git ls-files --stageコマンドを実行します。

1.3 作業ツリー

作業ツリーとは、ブランチ内から作業ディレクトリに展開されたファイル・ディレクトリ郡のことです。展開されたファイル/ディレクトリ群は直接編集することが出来ます。

ローカルにGitリポジトリを作成すると、以下のようなディレクトリ構成をみることが出来ます。(一部省略)

sample_project
├── .git
├── bar_dir
│   └── bar.txt
├── foo_dir
│   └── foo.txt
└── hello.txt

上記のsample_projectには「.git」というディレクトリと、hello.txtやfoo_dir、bar_dirといったディレクトリが格納されています。
「.git」ディレクトリは、リポジトリやステージングエリアが格納されています。それ以外のファイル/ディレクトリ群が作業ツリーです。(もしかすると、.gitディレクトリの一部のファイルも含めてsample_project全体を作業ツリーと呼ぶのかもしれない)

git checkoutをすることで、ブランチの内容を作業ツリーに反映できます。
以下の例ではfooブランチをチェックアウトしています。
f:id:toggtc:20120305020522p:plain

2. リモートリポジトリとローカルリポジトリ

リモートリポジトリは、既にCVSSubversion等を使っている方は馴染み深いですね。
サーバ側にあるリポジトリがリモートリポジトリ、ローカルで作業するためにコピーしたリポジトリがローカルリポジトリです。GitHubを使った場合、GitHub上にリモートリポジトリを配置することが出来ます。

2.1 クローン

git cloneコマンドを使うことで、リモートリポジトリをローカルリポジトリとして、ローカル環境にコピーすることが出来ます。
クローン元となったリモートリポジトリのことを一般に"origin"と呼びます。

2.2 複数のリモートリポジトリ

Gitは分散リポジトリです。CVSSubversionとは異なり、複数のリモートリポジトリを設定できます。これにより、いろいろなリモートリポジトリから変更を取得することが出来ます。
f:id:toggtc:20120305020541p:plain

例えば、homebrewの場合は、自分のGitHubにコピーしたhomebrewリモートリポジトリと、本家(Max氏)のリモートリポジトリから変更を取得できます。もっとも、追加したリモートリポジトリに対してコミット権限がなければ変更は反映できないので、その場合はread onlyということになります。
なお、Gitでは上流に位置するリモートリポジトリをupstreamと呼びます。原本情報が上流で、それを受取る側は下流です。GitHubの場合、フォーク元となったリモートリポジトリはupstreamです。Max氏のhomebrewをフォークした場合、upstreamはhttps://github.com/mxcl/homebrew.gitになります。

リモートリポジトリの追加は、git remote addコマンドによって行います。

2.3 リモートブランチ

前述のとおり、リポジトリは複数のブランチで構成されます。
それではリモートリポジトリ上にあるブランチとローカルリポジトリにあるブランチの関係はどうなるのでしょうか。
f:id:toggtc:20120305020600p:plain
上記の例では、リモートリポジトリとしてorigin, upstreamを登録しています。
ローカルリポジトリには、origin, upstreamそれぞれのmasterブランチと同期するリモートブランチ"origin/master", "upstream/master"を保持しています。
また、ローカルリポジトリにはローカルブランチmasterを持っています。ローカルで作業する際は、このローカルブランチを使います。そして、ローカルで更新した内容をリモートリポジトリにあるブランチに反映します。

2.4 リモートリポジトリの最新を取得する

もしかしたらGitの操作をしている間に、あるいはあなたが用事を思い出して出かけている間に、リモートリポジトリに対して誰かが更新をしたかもしれません。その更新は、これからあなたが変更しようとしている内容と重複するかもしれません。

そんなときは、修正作業に入る前に、まずリモートリポジトリ上にあるブランチから最新の変更を取り込みましょう。
リモートリポジトリの最新の内容を取り込む方法はいくつかあります。

2.4.1 fetchとmerge

fetchは、ローカルにあるリモートブランチを最新の状態に更新します。この段階ではステージングエリアや作業ツリー、ローカルのブランチには影響がありません。
f:id:toggtc:20120305020649p:plain


fetchで取得した更新を、ローカルブランチや作業ツリー等に反映するにはmergeコマンドを使用します。
mergeコマンドではいろいろなマージが出来るのですが、以下の例ではローカルにある指定したリモートブランチと、現在チェックアウトされているローカルブランチとをマージしています。このとき、マージされた結果がステージングエリアと作業ツリーに反映されます。
f:id:toggtc:20120305020716p:plain

なおmergeでは、作業ツリーやステージに何らかの修正があった場合、その修正差分とfetchで取り込んだ更新差分とを突合させ、

  • 競合する場合→競合エラーになる
  • 競合しない場合→更新差分をコミットして取り込む、修正差分はそのまま作業ツリーやステージングエリアに保持される

となります。
mergeには、他にも、コミットをせず作業ツリーを更新する方法もあります。
また、マージの方法は他にもリベースやチェリーピックがありますが、ここでは割愛します。

2.4.2 pull

pullは、fetchとmergeを同時に行うコマンドです。mergeを自動で行うため、pullを使用する際は、事前にmergeしたいローカルブランチがチェックアウトされているか確認しておくといいでしょう。
なお、普段はこちらのコマンドでいいのですが、単にリモートブランチの内容をウォッチするだけで、ローカルブランチや作業ツリーには変更を反映させたくない場合はfetchを使ったほうがいいでしょう。

2.5 リモートリポジトリに変更を反映する

ローカルで変更した差分をリモートリポジトリに反映するには、pushコマンドを使用します。
pushでは、ローカルのどのブランチを、どのリモートリポジトリの、どのブランチに反映させるかを指定することができます。
なお、pushはコミットされたもののみを送信するため、作業ツリーやステージングエリアにある変更は送信されません。

3. GitHubの概要

GitHubはGitを使ったプロジェクトホスティングサービスです。
特徴的なところは、ForkとPull Requestの機能です。

3.1 GitとGitHubのおいしい関係

GitHubを使うと、誰かのリポジトリを自分のリポジトリとしてコピーできます。
さらに、Gitは分散リポジトリですから複数のリモートリポジトリを設定することができます。
そうすると、GitHubとGitの組み合わせによって、誰かが作ったリポジトリを自分の作業用に持つことができる上に、その誰かのリポジトリから常に最新の更新を取り出すことが出来るわけです。
f:id:toggtc:20120308013545p:plain

3.1 Fork

フォークをすることで、誰かのリポジトリを自分のGitHubのリポジトリとしてコピーできます。
フォークはGitの機能ではなく、GitHubが提供するサービスです。Forkという名のとおり、フォーク元のリポジトリが親リポジトリとしてGitHubに管理されます。GitHubさんは目の付け所が違いますね。

  • フォークをしただけでは、相手のGitリポジトリと自分のGitリポジトリはそれぞれ(Git側から見ると)独立している。GitHubが繋がりを管理している。
    • 自分のGitリポジトリで何をしようが、相手には影響がない。(ただし後述のPull Requestをするときは影響がある)
    • フォークをすると、相手にフォークをしたことが通知される。

3.2 Pull Request

Pull Requestは、自分のGitHub内で修正した内容を、フォーク元にpullしてくれ、と依頼できる機能です。
Pull Requestをするとき、どのブランチをpullしてもらうかを指定することが出来ます。Pull Requestしたあとで対象のブランチに余計な変更を入れてしまうと、相手側がpullしたタイミングでその余計な変更が取り込まれてしまうため注意が必要です。

次回

Gitの仕組みをざっと見てきました。
さらにGitを理解するには、以下のサイトを参考にし、実際にGitを動かしてステージングエリアの状態やオブジェクトの中身を解析することをお勧めします。
http://progit.org/
http://progit.org/book/ja/  #日本語化していただいた方に感謝!

次回は、実際にhomebrewをForkしてPull Requestを行うまでの一連の作業を行います。

関連記事

homebrewをフォークするためのGit&GitHub入門
前編:Gitのセットアップ
中編 : Gitの仕組み
後編1:実践Git&GitHub (1/2)
後編2:実践Git&GitHub (2/2)


Homebrewを再構築する、インストールしたパッケージはそのままで

homebrewをいじっていたら、Formulaディレクトリがごちゃごちゃになってきたのでhomebrewを再構築してみました。(何をいじっているんだ、というツッコミは無しで)
git reset --hardで戻らなかった時の手段としてメモを残しておきます。

パッケージを全てインストールし直していたら何日掛かるか分からないので、インストールしたパッケージはそのままで。

バックアップ

まずhomebrewからインストールしたパッケージのリストを保存しておきます。万が一、homebrweを完全アンインストールすることになっても、環境を再構築できるようにするために(そうはなってほしくないですが)。

$ mkdir ~/homebrew_backup
$ brew list -v > ~/homebrew_backup/brew_list.log

さらに、念のためLinkedKegsをバックアップしておきます。
# 空き領域がある方は、さらにさらにCellarまでバックアップしておけば安心です

cd /usr/local
cp -R Library/LinkedKegs

アンインストール

本家が提示しているアンインストール方法だと、インストールしたパッケージやシムリンクも削除されてしまうので、手動で最低限のものだけアンインストールしていきます。

rm -rf ~/Library/Caches/Homebrew
rm -rf ~/Library/Logs/Homebrew

cd /usr/local
rm -rf .git
rm -rf .gitignore
rm -rf Library/Aliases
rm -rf Library/Contributions
rm -rf Library/Formula
rm -rf Library/Homebrew
rm -rf README.md
rm -rf bin/brew
rm -rf share/man/man1/brew.1


ちなみに、homebrewのインストーラーからインストールされるものは以下です。(サブサブディレクトリとその中にあるファイルは省略)

.git  # brew updateしたときにインストールされる
.gitignore  # brew updateしたときにインストールされる
Library/Aliases
Library/Contributions
Library/Formula
Library/Homebrew
README.md
bin/brew
share/man/man1/brew.1

インストール

本家の通りにインストール。

/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"

既存のパッケージに影響はないか確認

さて、どうなっていることやら。

brew updateしてみる

$ brew update
Initialized empty Git repository in /usr/local/.git/
remote: Counting objects: 58600, done.
remote: Compressing objects: 100% (24770/24770), done.
remote: Total 58600 (delta 38261), reused 50488 (delta 33106)
Receiving objects: 100% (58600/58600), 8.93 MiB | 1.89 MiB/s, done.
Resolving deltas: 100% (38261/38261), done.
From https://github.com/mxcl/homebrew
 * [new branch]      gh-pages   -> origin/gh-pages
 * [new branch]      master     -> origin/master
 * [new branch]      tap        -> origin/tap
HEAD is now at 71a53dc libzzip 0.13.60
Already up-to-date.

おお、正常に動いていますね!

brew listはどうだろう?

$ brew list -v
binutils 2.21.1a
cmake 2.8.7
colordiff 1.0.9
d-bus 1.4.16 1.4.18
fftw 3.3
flac 1.2.1
gdbm 1.10
gfortran 4.2.4-5666.3
ghostscript 9.05
git 1.7.9
… 以下省略

ちゃんと残っていましたね。

brew upgradeしてみる

$ brew upgrade
==> Upgrading 5 outdated packages, with result:
binutils 2.22, git 1.7.9.2, imagemagick 6.7.5-7, mercurial 2.1.1, sdl 1.2.15
==> Upgrading binutils
==> Downloading http://ftpmirror.gnu.org/binutils/binutils-2.22.tar.gz
######################################################################## 100.0%
… 以下省略


無事にhomebrewを再構築できました。

はてなブログにZenbackを埋めて関連記事を生成する方法

ブログの関連記事を生成するには、Zenbackサービスを使うと便利です。小飼弾さんの404 Not Foundで使用されていることで有名です。
http://zenback.jp/

はてなブログの記事本体にzenbackのコードを埋め込んでみました。
挙動が不安定ですが、興味のある方は試してみてください。

  • 頻繁に2エントリ目以降のzenbackが読み込まれない
  • たまに脚注記法が適用されて表示がおかしくなる
  • <head>部にrssのリンクが無いので、関連記事が出ないんじゃないか疑惑
    • →生成されました。/feedへのリンクが貼ってありましたね (2012/2/27追記)

とりあえず記事ごと表示すればにzenbackが読み込まれるのでまいっか。

#ご利用は自己責任で

前提

1. はてなブログには、2012年2月現在、HTMLテンプレート機能が無いため、記事ごとにzenbackのコードを埋め込む必要があります。
#サイドバーに埋めた場合、各ガジェットのリンク先は、記事ではなく常にトップページになってしまいます。

2. 編集モードを「はてな記法モード」にしておきます。

zenbackに登録する

以下のページで、利用規約等々に同意したらあなたのブログページを登録します。
#ブログURLの末尾に/を付けて登録しないと挙動がおかしくなります。

http://zenback.jp/

登録すると以下のようにコードが生成されます。
f:id:toggtc:20120226065243p:plain
そのコードをコピーして、変更を加えます。

方法A コピペ用

さっとコピペしたい人のためにコードを貼っておきます。

[]<script type="text/javascript" src='http://widget.zenback.jp/?base_uri=http%3A//YOUR_URL&nsid=YOUR_NSID&rand='+Math.ceil((new Date()*1)*Math.random())></script>[]

YOUR_URLはあなたのブログURLを指定してください。(http://より後ろの部分です)
YOUR_NSIDはあなたのnsidパラメータ値に置き換えてください。

方法B 自分で修正する

はてなブログにzenbackのコードを貼り付けるには、以下の修正が必要です。

  • 前後のコメント部分を削除
  • document.writeを使わず、<script></script>を直接記述する
  • 前後にはてな記法[]を挿入する

赤字…削除部分、青字...追加部分、緑字...変更部分)
変更前:
<!-- X:S ZenBackWidget --><script type="text/javascript">document.write(unescape("%3Cscript")+" src='http://widget.zenback.jp/?base_uri=http%3A//hoge.hatenablog.com&nsid=99999999999999999999999999999&rand="+Math.ceil((new Date()*1)*Math.random())+"'type='text/javascript'"+unescape("%3E%3C/script%3E"));</script><!-- X:E ZenBackWidget -->

変更後:
[]<script type="text/javascript" src='http://widget.zenback.jp/?base_uri=http%3A//hoge.hatenablog.com&nsid=99999999999999999999999999999&rand='+Math.ceil((new Date()*1)*Math.random())> </script>[]

あとは出来上がったスクリプトコードを、記事の最後に貼りつけてください。コードは改行せず、一行にしておく必要があります。
#改行を<p>タグに変換されてしまうので

なぜコードの修正が必要なのか

  • コメントの除去
  • document.writeの除去
    • はてなブログはクライアントサイドで脚注の展開をしているっぽい(´・ω・`)
    • はてなダイアリーでどうだったかは知らないです)
    • document.writeのところに、[]を付与すれば脚注評価がキャンセルできるかもしれない、試していないけど
  • []の付与
    • →注釈記法の回避

実際に、はてなブログにzenbackのスクリプトをそのまま埋め込むと、おかしな表示になります↓

*1:new Date()*1)*Math.random(

ソースを確認してみたところ、はてなブログ内で以下のように変換されていました。

Math.ceil((new Date()*1)*Math.random())
↓
Math.ceil<a href="#f1" name="fn1" title="new Date()*1)*Math.random(">*1</a>")

#上記コードで、fn1というname属性はfotternote(脚注)のことですね。

((new Date()*1)*Math.random())が、注釈記法に引っかかるようです。

zenbackをフルで入れると、コメント欄とはてなスターが遠くなるので、ガジェットを絞ったほうがいいかもしれませんね。
あと、ページが重いとタイムアウトが走るのか、読み込み中で止まってしまうようです。
はてなのJavaScriptを把握していないので、全ての状況でこの方法でうまくいくかは分かりませんが、興味のある方は試してみてください。

それからそれから、Firefox便利ですね。表示されたページの見たい部分を範囲選択or全選択して、右クリックして"選択した部分のソースを表示"ってするとJavaScript展開後のHTMLが表示できる!