Original: http://pasky.or.cz/~pasky/dev/git/README
Latest: https://github.com/git/git/blob/master/README

原文: http://pasky.or.cz/~pasky/dev/git/git/README
翻訳: tez@kamihira.com


	GIT - バカなデータ追跡ソフト

"git" はあなたの気分に応じて、いろいろな意味を持ちます。

 - 適当な三文字の組み合わせでゴロが良く、UNIX コマンド名でまだ利用されて
   いないようなもの。"get" の間違った発音に関係しているかも知れないし、
   していないのかも知れません。
 - ばか。軽薄でしょーもないもの。たんじゅんなもの。スラング辞書からあなたの
   好きなものをどうぞ。
 - "global information tracker": 機嫌がよければ実際にあなたのために動作
   します。天使が唄い、光が部屋をつつむはず。
 - "goddamn idiotic truckload of sh*t": うまくいかないとき。

GIT は二つの層からなります。下位層は単に非常に速くじゅうんなんなファイルシステム
ベースのデータベースであり、履歴とともにディレクトリツリーを保存するように
設計されたものです。上位層は SCM のようなツール群であり、人間がこれらの
データベースに SCM ツールと似た形で操作することを可能にするものです(たとえば
CVS や BitKeeper あるいは Monotone の操作のように)。



	"GIT ツールキット"
	~~~~~~~~~~~~~~~~~

GIT の tar ボールを取得したときにしなくてはならないこと、最初の使い方、
それを駆使ししてハックする方法について簡単に説明します。ある程度の説明
にはなっているはずですが、ドキュメントはどうみても、もっと詳しく書き換えなくては
なりません。

この mini-HOWTO は取得した tarball に関して二つのことを仮定しています:
	(i)  あるブランチを "追跡" していること
	(ii) それは "pasky" という名前の "追跡" ブランチであること


make コマンドによってバイナリを作成し、スクリプトがすべて $PATH に含まれて
いることを確認し、最新のバージョンで更新するには以下のコマンドを実行します

	git pull pasky

(そしてそれ以降の更新を反映させるにはこれを繰り返し実行します - ただし以下
に注意してください)
それから最終的に以下のコマンドで再び最新バイナリを生成できます

	make

そして... これで全部です。ちょっと遊んでみてください。;-)

このツリーは追跡されています。つまり以下のコマンドによって私(pasky)の最後の
変更点を取得することができます:

	git pull pasky

(ブランチを追跡しているのであれば、単に "git pull" のように引数なしで実行した
場合には追跡されているブランチに対して処理されます。)
その間なにかローカルコミットをした場合、git は pasky ブランチにこれをマージ
しようとします。この場合、マージが正しくおこなわれ衝突していないことを確認
する必要があり、あるいはマージに関係した調整処理を行う必要があるかも知れませんが、
その後 git commit で最終的なマージ内容を記録します。

私(pasky)のツリーの追跡をやめるには(独立した開発ラインとしたり、linus のような
人のラインを再追跡するような場合には)、以下を実行してください:

	git track

(引数をつけなければツリーの追跡をやめる意味になります)。ブランチはまだそこに
あり、以下のコマンドで再び最新の更新をもってくる(pull)ことができます:

	git pull pasky

しかしもうブランチを追跡していないので変更点は自動的にローカルツリーに適用される
ことはもうありません。しかしもし何か変更があれば二つの ID が表示されます(
"Tree change" のような行のことを言っています)。これを git diff に引数として
わたせば最後に pull したときからの変更点を表示させることができます。また

	git diff -r pasky:this

とすれば私(pasky)とあなたのブランチの差分を表示できます。

'pasky' のかわりに 'linus' と指定すれば Linus の公式なブランチにアクセスすることも
できるのに注意してください。もちろんもっとたくさんのブランチを追加することができます。
以下のようにします:

	git addremote name rsyncurl

(rsyncurl は rsycn によってアクセス可能なリポジトリの内部にあるブランチを特定
するための部分です)。何かローカルな変更をした場合:

	git diff

としてその内容を表示することができます。"ok" は同じものであることを意味しています
が hash 値が表示された場合にはそれらは何か違ったものであることを意味しています。
これは、いまのところちょっとした問題がありますが、それは ctime や inode 値が変化
したときにも表示されてしまうのです。ファイル内容に変化があった場合には実際に diff
表示されます。

もちろんコミットしたいのだと思います。新しいファイルを追加した場合にはまず

	git add newfile1 newfile2 ...

としてください。それから git diff で変更点を確認するか、変更されたファイル名
だけが知りたいのなら

	git status

としてから

	git commit

でコミットできます。このコマンドは標準入力からのメッセージを要求します。

コミット履歴を確認するのも良い習慣です。このためのツールもあります。

	git log pasky

は私(pasky) のブランチの履歴を表示します。git log で引数を指定しなければ
現在のブランチの履歴をデフォルト表示します。

新たらしいプロジェクトをはじめたい場合には (新規のディレクトリ中で)

	git init

を実行します。他の誰かのプロジェクトを見たい場合には

	git init URL

とします。(あなたの作業ディレクトリはデフォルトでは 'origin' ブランチ
を追う形になります)。

まだたくさんの機能が実現されていません。すでにある程度実現されている
ものにはブランチの分岐(git fork)、マージ(git merge)、あなたのツリーの
状態を古いコミット時点のものに移す(git seek) などがあります。

簡単なヘルプ表示には

	git help

を使ってください。リファレンスを見たければ私の URL 

	rsync://pasky.or.cz/git

を見てください。

これらすぺては非常に実験的なものであり、よく動作が途切れてしまいます。
LKML や git のメーリングリストに参加してください。


必要なソフトウェア:

	C コンパイラ
	bash
	基本的な shell 環境 (sed, grep, textutils, ...)
	mktemp 1.5+ (Mandrake のユーザは注意!)
	diff, patch
	libssl
	rsync



	"GIT の中核"
	~~~~~~~~~~~

これは本当にバカな(しかし非常に速い)ディレクトリデータマネージャです。
たいしたことはしませんが、ディレクトリの内容を効率的に追跡することは
できます。

二つの抽象化されたオブジェクト概念があります: "オブジェクトデータベース"
と "現在のディレクトリキャッシュ" あるいは "インデックス(index)" と
呼ばれるものです。


	オブジェクトデータベース (SHA1_FILE_DIRECTORY)

オブジェクトデータベースは文字どおり、単に区別して参照することができる
オブジェクトのあつまりにすぎません。すべてのオブジェクトはその内容に
よって名前がついています。大雑把にはオブジェクトの内容自身に対する
SHA1 ハッシュ値によるものです。オブジェクトは他のオブジェクトを
(その SHA1 ハッシュ値を参照することによって)参照することもできるので
オブジェクトの階層構造を作ることができます。

すべてのオブジェクトは静的に型づけされ、"tag(タグ)" と呼ばれます。
これはオブジェクト生成時に決定され、オブジェクトの形式を識別するものに
なります(たとえば、それはどのように利用され、どのようにして他のオブジェクト
を参照することができるか、など)。いまのところ三種類のオブジェクト型が
あります: "blob", "tree", "commit" です。

"blob" オブジェクトは他のオブジェクトを参照することはできません、つまり、
タグ名が暗示しているように、それは誰かのユーザのデータを含む純粋な
保存用データそのものです。これはファイルデータを実際に格納するために
利用されるので、blob オブジェクトは、あるファイルの特定のバージョン
に関連したものになります。

"tree" オブジェクトはひとつ以上の "blob" オブジェクトをディレクトリ構造の
形にまとめるためのオブジェクトです。さらに tree オブジェクトは他のツリー
オブジェクトを参照することもできるので、ディレクトリの階層構造を表現
することもできます。

最後に "commit" オブジェクトはそのようなディレクトリ階層構造を
リビジョンから構成される DAG にまとめあげるためのオブジェクトです -
それぞれの "commit" はただひとつのツリーと関係し(コミット時点での
ディレクトリ階層構造と関係し)ます。さらに "commit" はひとつあるいはそれ
以上の "親" のコミットオブジェクトを参照しますが、これは
そのディレクトリ階層構造が現在の姿になるまでの履歴を記述するものです。

特別な場合として commit オブジェクトのうち親を持たないものを "root" 
オブジェクトといい、これがプロジェクトの最初のコミットに対応することに
なります。プロジェクトのそれぞれは少なくともひとつのルートを持たねば
なりません。さらに、複数の異なるルートオブジェクトをまとめてひとつのプロジェクト
とすることもできます。これには二つ以上の異なるルートを究極の親とするような
新しいコミットオブジェクトを作ることで行います。これは混乱を引き起こす
でしょう。それで、git 自身がそれを強制することはないにしても、"ひとつのプロ
ジェクトにはひとつのルートオブジェクト" の原則を守りましょう。

オブジェクトの型によらず、すべてのオブジェクトは以下の性質を持ちます:
すべて zlib によって圧縮され、タグを指定するだけではなくオブジェクト中の
データサイズについての情報も含むようなヘッダをもちます。オブジェクトの
名前として利用される SHA1 ハッシュ値は、常に、もとのデータではなく、
この圧縮後のハッシュ値であることに注意してください。

結果として、オブジェクトの一般的な整合性は常にオブジェクトの方や内容
とは独立にチェックすることができます: すべてのオブジェクトは以下のように
して検証することができます。(a) ハッシュ値がファイルの内容に一致している
こと (b) オブジェクトは +  +  +  +  の並びになるようなバイトストリーム
に正しく解凍可能であること。

構造化されたオブジェクトはそれ自身が内部構造を持ち、別のオブジェクトとの
関連性も検証することができます。これは一般的には "fsck-cache" プログラム
によって行われますが、これはすべてのオブジェクトの完全な依存グラフを生成
し、それらの内部無矛盾性が検証されます(それに加えてハッシュ値を通じての
チェックもされます)。

オブジェクト型ごとのもう少し詳しい説明としては:

  BLOB: "blob" オブジェクトはバイナリデータそのものであって何か自分以外
        のものを参照したりはしません。データに対する署名やその他の検証
        の仕組みはないのでオブジェクトは常に一貫している一方で(sha1 ハッシュ
        で index されているのでデータ自身は確かに正しいといえます)、
        それ以外の属性はまったく持ちません。どのような名前も、パーミッション
        とも関係していません。純粋に、単なるバイナリーデータです(たとえば
        通常のファイル内容そのものです)。

        特に、blob はデータ自身だけによって完全に定義されるので、ディレクトリ
        ツリー中の二つのファイル(あるいはリポジトリ中の複数の異なるバージョン)
        が同じ内容を持てば同じ blob オブジェクトを共有することになります。
        オブジェクトはディレクトリツリー中の場所から完全に独立で、ファイルの
        名称変更はどんな形であれそのファイルが結びついているオブジェクトを
        変更することはありません。

  TREE: 次の階層オブジェクト型は "tree" オブジェクトです。ツリーオブジェクト
        は mode/name/blob データのリストで、名前によってソートされている
        ものです。言い換えると、mode データはディレクトリ mode を指定する
        かも知れず、この場合 blob を名づけるかわりにその名前は別の tree
        オブジェクトに関係したものになります。

        "blob" オブジェクトと似て、ツリーオブジェクトは内容の組によって
        一意に決まるので二つの異なっているが内容が等しいツリーは常に
        まったく同一のオブジェクトを共有します。これはすべての階層で
        成立します。つまり "葉" のツリー(blob 以外のどのような他のツリー
        を参照することもないツリー)についても、サブディレクトリ全体に
        ついても成り立ちます。

        この理由で、"tree" オブジェクトは単なるデータ抽象化にすぎません:
        それは履歴を持たず、署名も持たず、妥当性の検証情報も含みません。
        ただし内容はハッシュ値自身によって保護されているので、ツリーは
        書き換えられることがなく、その内容は不変であることを信用することは
        できます。

        それでツリーの内容が妥当であることを信用でき、同様に blob の内容
        も信用することができますがその内容が、いったいどこから来たものかを
        知ることはできません。

        ツリーについての補足: "tree"オブジェクトは "ファイル名+内容" の
        ソートしたリストなので二つのツリー間の diff を実際に二つのツリー
        を展開しなくても生成することができます。すべての共通部分を無視
        するだけで、diff は正しい形になります。言い換えると、O(n) の
        オーダーで二つの任意のツリー間の差分を効率的に知ることができます。
        ここで n は差分のサイズであり、ツリーのサイズではありません。

        ツリーについての補足2: "blob" の名前はその内容によって完全に
        そして排他的に決まる(つまり、名前やパーミッションは含んでいない)
        ので、ちょっとした名称変更やパーミッションの変化は blob 自体を
        変化させずに知ることができます。しかしデータ内容の修正と同時に
        加えた名称変更には賢い "diff" の実装が必要になります。

CHANGESET: "changeset" オブジェクトは履歴概念を構成するために導入される
        オブジェクトです。他のオブジェクトとは違い、ツリーの物理的な状態
        を記述するのではなく、どのようにしてその状態に到達したか、あるいは
        なぜその状態に到達したか、を記述するものです。

        "changeset" は結果としてのツリーオブジェクト、そこにいたるための
        親チェンジセット群(ゼロ個、一個、それ以上のこともあります)、そして
        起きたことについてのコメントからなります。changeset 自身が
        信頼できる情報ではないことに注意してください: その内容は矛盾なく
        定義され、すべてのレベルでの暗号学的な署名によって安全なものではあ
        りますがそのツリーが良いものであるか、あるいはマージ情報に意味が
        あるかどうかを信じてよい理由はありません。たとえば、その親たちは
        実際にその結果とどのような関係を持つ必要もありません。

        changeset についての注意: 実際の SCM とは違い changeset は名称変更
        情報あるいはファイルモードの変更情報を含んでいません。これらすべて
        は関係したツリーに暗黙に含まれている情報です(結果のツリーとその親の
        ツリーの内部に含まれています)、そしてそれを記述することはこのバカな
        ファイルマネージャでは意味を持ちません。

TRUST: "trust" の概念は "git" の範囲の外にありますが、いくつかの点について
        触れておくことには意味があります。まず、すべては SHA1 でハッシュ
        されるのであるオブジェクトは不変であり、外部資源の影響を受けていない
        ことを信じることができます。それでオブジェクトの名前はユニークな
        ある状態を示すことができます - trust したいと思っている状態ではなく(XXX)。

        さらに、changeset の SHA1 署名はツリーが関係している SHA1 署名
        と、その親の署名を参照しているので、ひとつの名前がついた changeset は
        その内容全体と共に、履歴の完全な組を一意に指定することができます。
        いったん changeset の名前を決めれば、そのステップをあとでごまかすことは
        できません。

        それで、システム中になにかある本当の trust を持ち込む場合、しなくては
        ならないことはある特定の注釈に対してデジタル的に署名することだけです。
        それは最上位 changeset の名前を含んだものです。あなたのデジタル署名は
        他のひとたちに対してあなたがその changeset を信じていることを示します。
        そして changeset の履歴が不変であることは他の人たちにその履歴全体を信用して
        よいのだということを伝えます。

        言い換えると、アーカイブ全体の妥当性を確認するには、単に email を
        送って人々に最上位 changeset の名前(SHA1 ハッシュ値) を伝え、GPG/PGP
        のような何かの仕組みを使ってその email に署名すればよいのです。 

        特に、タグの "信頼できる地点" の個別のアーカイブを持つこともでき、
        そこにはあなたの(そして他の人たちの) trust の内容が書かれている
        ような形にできます。もちろんこれらの "trust の証明書" は "git" 自身
        を使ってアーカイブすることもできますが、"git" があなたにたいして何か
        する、というようなものではありません。

最後の点を別の形で言い表すと: "git" 自身はデータ内容の整合性だけをあつかい
trust は外部から持ち込まなくてはなりません。


	"インデックス(index)" あるいは "現在のディレクトリキャッシュ" (".git/index")

index は単純なバイナリファイルで、ある時点での仮想的なディレクトリの
内容の効率的な表現を含んでいます。これは、名前、日付、パーミッション、
"blob" の内容をひとつにしたものの単純な配列です。キャッシュは常に名前
によって並んでいて、名前はどの時点でもユニークです(ただしいくつかの非常
に特殊な規約があります)が、キャッシュは長期間にわたって利用するものでは
なく、常に部分的に更新することが可能なものです。

特に index は現在のディレクトリの内容と無矛盾である必要はありません
(事実、ほとんどの操作はディレクトリ階層と index が一貫していない状態
にするようないろいろな方法に依存していますXXX)が、三つの重要な性質が
あります:

 (a) キャッシュしている完全な状態を再生成することができます(ディレクトリ
     構造だけではありません: これは "blob" オブジェクトへの参照も含んで
     いるのでそのデータもまた再生成できます)

     特殊な場合として、現在のディレクトリキャッシュから "tree オブジェクト"
     に対する、あいまいではないはっきりした一方向のマッピングが存在
     します。これは現在のディレクトリキャッシュの情報だけを使って効率的に生成する
     ことができます。こうして特定の時点でのディレクトリキャッシュは
     ユニークにただひとつの "tree" オブジェクトを指定することが
     できます(しかしディレクトリにおきた変化と tree オブジェクトを簡単に
     比較することができるための追加データも持っています)

 (b) キャッシュされた状態("tree オブジェクトがインスタンス化されるのを
     待っている状態") と現在の状態との間の矛盾を見つけるための効率的
     な方法をもっている。

 (c) 異なる tree オブジェクト間でのマージ衝突についての情報を効率的に
     追加で表現することができる。このさい、それぞれのパス名はツリーに関する
     十分な情報と関係していて、二つのツリー間での3方法マージを作ることが
     できる。


これら三つだけがディレクトリキャッシュの仕事です。それはキャッシュであり、
通常の操作はすでにわかっているツリーオブジェクトから完全に再生成するか、
開発中の生きたツリーを更新したり比較したりする中で再生成することです。
もしディレクトリキャッシュが完全になくなってしまったとしても、それを記述する
気の名前をおさえておきさえすれば、一般にはどのような情報も失われることは
ありません。

同時に、ディレクトリ index は新しいツリーを作成するための場所にもなり、
新しいツリーは常に index ファイルの制御された修正を含んでいます。特に
index ファイルはまだインスタンス化されていない中間的なツリーの表現を
持つこともできます。それで index はライトバック・キャッシュと考えること
ができ、バックストーレージにまだ書き戻していない汚れた情報を含むことが
できると考えることができます。


	作業の流れ

一般的に、すべての "git" 操作は index ファイルに対するものです。
いくつかの操作は純粋に index ファイルだけに関係しています(index
の現在の状態を表示するようなものがそうです)。しかしほとんどの操作
はデータを index ファイルから、また index ファイルに転送します。
転送はデータベースから、あるいは作業ディレクトリのどちらかからになります。
それで四つの主な組合せがあります。

 1) 作業ディレクトリ -> インデックス

        index を作業ディレクトリからの情報で更新するには "update-cache"
        コマンドを使います。一般的に index 情報を更新するには更新したい
        ファイル名を指定するだけです。たとえば:

		update-cache filename

	しかしファイル名のグロブなどについてのよくある間違いを避ける
        ため、普通このコマンドは新しい項目を追加したり古い項目を削除
        したりすることはしません。つまり既存のキャッシュ項目にについ
        てだけ更新を実行します。

        git にある種のファイルがすでに存在しない、あるいは新しいファイル
        を追加したい場合にはそれぞれ "--remove" と "--add" フラグを
        指定します。

	注意! "--remove" フラグは引き続くファイル名が必ず削除されなくては
        ならないということを意味しません: もしファイルがディレクトリ構造中
        に依然として存在しているなら index はその新しい状態で更新され
        削除されることはありません。"--remove" の意味はたんに update-cache
        はファイルが削除されることを正常な処理とみなすというだけであり
        ファイルがほんとうにもう存在しないのなら index をそのように更新する
        だけです。

        特殊な場合として "update-cache --refresh" を実行することができます
        がこれは現在の状態情報に一致するようなそれぞれの index の"状態"情報
        を最新の状態にします。それはオブジェクトの状態そのものを更新する
        のではなく、単にそのオブジェクトが依然としてその古いバックストーレージ
        中のオブジェクトと一致しているかどうかをすばやくチェックするために
        利用されるフィールドだけを更新します。

 2) インデックス -> オブジェクトDB

        以下のプログラムによって現在の index ファイルの内容を "tree"
        オブジェクトに書き出します:

		write-tree

        これはどんなオプションもとりません - 単に現在の index ファイルの
        内容をその状態を示す tree オブジェクトの組に書き出し、結果の最上位の
        tree の名前を返します。この tree は他の命令によって常に index を
        再生成するために利用することができます:

 3) オブジェクトDB -> インデックス

        オブジェクトデータベースから "tree" ファイルを読み、それを現在の
        index にすることができます(あとで復元しようとおもっている保存
        していない状態をあなたの index が含んでいる場合にはこれをしないで
        ください!)。通常の操作では単に

		read-tree 

        と実行し、これであなたの index ファイルはすでに保存してある tree と
        等しくなります。しかしそれは index ファイルだけです: 作業ディレクトリ
        の内容は変更されません。

 4) インデックス -> 作業ディレクトリ

        ファイルを"チェックアウト" することによって index から作業
        ディレクトリを更新します。これはそれほど頻繁に実行する操作
        ではありませんが、それは通常、自分のファイルは更新された状態
        とするのが普通で、作業ディレクトリに書き出すよりも、index 
        ファイルに対して作業ディレクトリ中での変更点を伝えるのが普通
        だからです(つまり "update-cache"コマンドです)。

        しかしながら、新しいバージョンに切替えることにした場合や
        誰か別の人のバージョンをチェックアウトしたり以前のツリーを
        単に復元したりする場合には read-tree を使って index ファイル
        を展開し、それからその結果を以下のコマンドでチェックアウト
        したいと考えるかも知れません

		checkout-cache filename

        あるいはもし index のすべてをチェックアウトしたいのなら
        "-a" オプションを使います。

	注意! checkout-cache は普通古いファイルを上書きするのを拒否
        するので、すでにチェックアウトされているツリーの古いバージョン
        を持っているなら、"-f" フラグを指定する必要があります("-a" フラグ
        あるいはファイル名の前に指定します)。これでチェックアウトを
        強制的に行ないます。


最後に、例外的な操作がいくつかあり、これはある表現を別の場所に単に移す
という形では表すことができないものです:

 5) すべてをひとまとめに

        "write-tree" でインスタンス化したツリーをコミットするには
        ツリーとそれに関する履歴を参照するような "commit" オブジェクト
        を作る必要があります - ほとんどの場合それは、履歴中で今回の
        コミットに先立っておきた "親" のコミットになります。

        通常 "commit" はひとつの親をもちます: これはある変更を加える前
        のツリーの状態です。しかし場合によっては二つ以上の親のコミット
        が存在する場合もあり、この場合は "merge(マージ)" と呼ばれます。
        理由はそのようなコミットは異なるコミットで表される二つ以上の
        過去の状態をまとめて生成されるからです。

        言い換えると "tree" は作業ディレクトリの特定のディレクトリの
        状態を表現するのにたいして、"commit" はその状態を時間の中で考えた
        ものになっていて、どのようにしてその状態に到達したかを説明する
        ものになっているということです。

        commit オブジェクトを作るには、この commit オブジェクトに対して
        その時点での状態を示すツリーと、親のリストを指定します:

		commit-tree  -p  [-p  ..]

        そしてコミットの理由をしめすメッセージを標準入力から与えます(
        パイプやファイルからのリダイレクトでも良いですし、端末から直接
        入力してもかまいません)。

        commit-tree はそのコミットを示すオブジェクトの名前を返すので、
        後の利用のためにはこれを保存する必要があります。
        通常コミットによって "HEAD" と呼ばれる状態が更新され、git は
        一般にはあなたがコミットオブジェクトの名前をどのように保存したか
        は考慮しませんが、最後のコミットについてだけは".git/HEAD" に保存
        されるので、最後のコミットされた状態がどうであるかだけは常に知る
        ことができます。

 6) データの確認

        さまざまな補助的なツールを使ってオブジェクトデータベースや index 中に
        表現されたデータを調べることができます。すべてのオブジェクトについて
        "cat-file" を使ってオブジェクトの詳細を調べることができます:

		cat-file -t 

        これはオブジェクトの型を表示し、型がわかってしまえば(これは通常
        オブジェクトがどこにあったかで暗黙にわかることですが)、以下の
        コマンド

		cat-file blob|tree|commit 

        を使ってその内容を知ることができます。注意! ツリーはバイナリデータ
        なので結果的にその内容を表示するには特殊な補助ツールが必要になります。
        これは "ls-tree" と呼ばれ、バイナリデータの内容をもっと見やすい形式に
        変換します。

        "commit" オブジェクトの内容を見るとは特に理解の助けになりますが、
        それはこのオブジェクトは小さくて、内容を見ればそれだけで理解できる
        ような形式をしているからです。特に ".git/HEAD" にある最上位コミット
        が必要であれば、

		cat-file commit $(cat .git/HEAD)

        とすることで簡単に最上位コミットが何であったかを知ることができます。

 7) 複数のツリーのマージ

        git は 3 方向マージ処理を支援しますが、最終的にその状態を
        "commit" するまで任意の回数だけ 3 方向マージを繰り返すことで
        n 方向マージ処理にまで拡張することができます。
        通常は唯一の 3 方向マージ(二つの親を持つ場合です)を実行して
        からコミットするのが普通ですが、一度にもっと多くの親について
        処理したいこともあるかも知れません。

        3 方向マージを実行するにはマージしたい "commit" オブジェクトを
        二組つくり、それを使って一番近い共通祖先(第三の "commit" オブジェクト)
        を見つけ、それからこれらのコミットオブジェクトをそれらの時点での
        ディレクトリの状態("tree"オブジェクト)を見つけるために利用します。

        マージのための "base" を見つけるには、二つのコミットの共通の親を
        以下のコマンドで見つけます

		merge-base  

        これは両方の元になった commit を返します。ついでこれらのコミット
        の "tree" オブジェクトを調べる必要がありますが、これはたとえば以下の
        ようなコマンドによって簡単に見つけることができます:

		cat-file commit  | head -1

        理由は tree オブジェクト情報は常にコミットオブジェクトの先頭行に
        あるためです。

        マージしようとする三つの tree がわかってしまえば(ひとつの "もとの"
        ツリー、つまり共通の親と、二つの "結果の" ツリー、つまりマージ
        しようとしているブランチがわかってしまえば)、index 中にたいして
        "merge" を実行します。これは古い index 内容を捨ててしまうので
        それらをコミットしたことを保障しなくてはなりません - 実際には
        通常は常に最後のコミットに対してマージを実行します(これでとにかく
        現在の index 中にあるものにマッチしているはずです)XXX。
        マージするには

		read-tree -m   

        と実行し、これですべての明らかなマージ処理については直接 index
        ファイルに反映されるので "write-tree" を使って結果を書き出すだけ
        だけです。

	注意! マージは index ファイル中で起こり作業ディレクトリに対して
        ではないので、作業ディレクトリはもうあなたの index とは一致しなく
        なります。作業ディレクトリ中でマージ結果を反映させるためには
        "checkout-cache -f -a" コマンドを使うことができます。

	注意2! 残念なことに多くのマージはそんなに単純なものではありません。
        もし追加、名称変更、削除などのファイルがある場合、あるいは両方の
        ブランチが同じファイルを修正していた場合には、"マージ項目" を
        含むような index ツリーが残ってしまうので、結果を書き出す前に
        外部ツールを使ってこのようなマージの失敗した部分を解決してやる
        必要があります。

	[ fixme: マージの解決についての説明をここに ]