名前
gittutorial - Git チュートリアル (バージョン 1.5.1 以降用)
書式
git *
説明
このチュートリアルでは git に新しいプロジェクトソースをインポートする方法と、 そこに変更を加える方法、そして他の開発者と変更を共有する方法を説明します。
もしあなたの主な目的がプロジェクトの変更を取得すること(例えば最新バージョンのソースを取得してテストするなど)であるなら 、 Git ユーザーマニュアル の最初の2つの章から始める方が良いかもしれません。
まず最初に、`git log --graph`のようなコマンドに対するマニュアルは 以下の方法で取得できることを憶えてください:
$ man git-log
もしくは:
$ git help log
後者の方法では、マニュアルのビューアを指定できます;詳細は git-help(1) を参照して下さい。
Gitの操作を開始する前に氏名とメールアドレスを設定することを推奨します。 最も簡単な方法は以下の通りです:
$ git config --global user.name "氏名"
$ git config --global user.email you@yourdomain.example.com
新規プロジェクトのインポート
tarで圧縮されたファイル project.tar.gz を Git のリビジョン管理させる手順を説明します。最初に以下のコマンドを実行します。
$ tar xzf project.tar.gz
$ cd project
$ git init
この操作を終えると Git は以下のメッセージを表示します。
Initialized empty Git repository in .git/
そして、作業ディレクトリが初期化され、".git" という名前の ディレクトリが作成されます。
次に、カレントディレクトリ配下の全ファイルのスナップショットを取得する為、 git-add コマンドを実行します('.'があることに注意):
$ git add .
取得したスナップショットは "索引(index)" と呼ばれる一時エリアに格納されます。 索引の 中身を永続的にリポジトリに保管するには git-commit コマンドを使います:
$ git commit
コミットメッセージの入力が求められます。 その後、プロジェクトの最初のバージョンが Git に格納されます。
変更の記録
ファイルを変更した後、更新内容を索引に追加します:
$ git add file1 file2 file3
これでコミットする準備ができました。git-diff を --cached オプション付きで 実行するとコミット予定の内容を確認できます:
$ git diff --cached
(--cached を指定しない場合、git-diff は修正されているがまだ索引に 追加されていない変更を表示します。) 簡潔なサマリを表示するには git-status を使用します:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: file1
# modified: file2
# modified: file3
#
必要な場合はさらに変更し、新しい変更内容を索引に追加します。 最後に、変更をコミットします:
$ git commit
この操作を行なうとエディタが起動され、変更内容を説明するメッセージの入力を要求されます。 メッセージを入力しエディタを終了するとプロジェクトの新しいバージョンが記録されます。
別のやり方として、 git-add を実行せずに、以下のようにするやり方もあります。
$ git commit -a
この方法では変更ファイル(ただし新規ファイルは除く)が自動的に検出され、索引への追加とコミットが1ステップで実行されます。
コミットメッセージに関する注意: 必須ではありませんが、格納メッセージは1行の短文(50文字未満)で変更の概要を書き、 空行を1つ挟んだ後ろに詳細を書くことを推奨します。 コミットメッセージの最初の空行までのテキストは、コミットのタイトルとしてGitが扱うようにしている為です。 例えば、git-format-patch(1) コマンドではコミットを email に変換しますが、 このタイトルをメールのSubjectとし、残りを本文として扱います。
Git はファイルではなくファイルの中身を追跡する
多くのリビジョン管理システムでは add
コマンドは新規ファイルを追跡対象に加える役目をします。一方Gitの add
コマンドは、よりシンプルでパワフルです: git-add は新規ファイルと新しい変更ファイルの両方に対して使用され、
どちらの場合にも指定したファイルのスナップショットをとってファイル内容を索引に登録し、次のコミットに含める準備をします。
プロジェクトの履歴を参照する
どんな時でも、次のコマンドを実行して変更履歴をみることができます。
$ git log
各ステップの完全な差分を参照したい時は、次のようにします。
$ git log -p
変更の概要(ファイル名、修正行数など)を確認するには次のようにします。
$ git log --stat --summary
ブランチの管理
Git は1つのリポジトリ内に複数のブランチを作成できます。 "experimental" という名前の新しいブランチを作成するには次のようにします。
$ git branch experimental
次のコマンドを実行すると
$ git branch
存在する全てのブランチのリストが表示されます:
experimental
* master
"experimental" ブランチは今あなたが作成したものです、そして、 "master" ブランチは自動的に作成されたデフォルトブランチです。 "*" のマークは現在作業中のブランチを指しています。; 以下のコマンド
$ git checkout experimental
を打つと experimental ブランチにスイッチします。 さて、ファイルを編集し、コミットし、master ブランチに戻ってください:
(ファイルを編集)
$ git commit -a
$ git checkout master
そうすると変更内容がもはや見えなくなっているはずです。これは、experimental ブランチで変更した後、master ブランチに戻っている為です。
master ブランチ上で別の変更をしてみましょう:
(ファイルを編集)
$ git commit -a
この時点で2つのブランチは分岐しました。それぞれ異なる変更が行なわれています。 experimental の変更を master にマージするには、以下のようにします。
$ git merge experimental
変更がコンフリクト(競合)しない場合は、これでマージ完了です。 コンフリクトがある時は、マーカーが問題のあるファイル内に残り、 コンフリクトを示すでしょう。そして、
$ git diff
コマンドを実行するとマーカーの位置を示します。 ファイルを編集してコンフリクトを解消させてから、
$ git commit -a
コマンドを実行すると、マージ結果がコミットされます。 最後に、
$ gitk
を実行すると、実行結果の履歴がグラフ表示されます。
マージが完了したので、experimental ブランチは次のようにして削除できます。
$ git branch -d experimental
このコマンドは experimental ブランチの変更が現在のブランチにマージ済みであることを確認してからブランチを削除します。
ブランチ crazy-idea 上での開発が失敗し、それをマージせずに削除したい場合は、次のようにします。
$ git branch -D crazy-idea
ブランチは手軽で簡単です。何かを試す時にはとても便利です。
Gitを利用した共同開発
アリスが始めたプロジェクトのGitリポジトリが/home/alice/project にあり、同一マシン上にアカウントを持つボブがアリスの仕事を手伝おうとしていたとします。
ボブが最初にすることは:
bob$ git clone /home/alice/project myrepo
これによりアリスのリポジトリを複製した "myrepo" という 新規ディレクトリが作成されます。 この複製は元プロジェクトと対等であり、元プロジェクトの履歴がコピーされています。
ボブはこの複製した環境でいくつかの変更とコミットをします:
(ファイルを編集)
bob$ git commit -a
(必要なだけ繰り返す)
準備ができたら、ボブは /home/bob/myrepo にあるリポジトリから変更を取得(pull)するようアリスに伝えます。 アリスは次のコマンドで変更を取得します:
alice$ cd /home/alice/project
alice$ git pull /home/bob/myrepo master
この結果、ボブの "master" ブランチの変更をアリスの現在のブランチにマージされます。 もしアリスが自身の変更もしている場合は、彼女は手動でコンフリクト(競合)を解消する必要があるかもしれません。
"pull" コマンドは次の2つの操作をしています:リモートのブランチから変更を取得し、取得結果を現在のブランチにマージ。
注意:一般的に"pull"をする前には自身のローカルな変更はコミットしておくほうが 良いでしょう。ボブとアリスの変更が分岐し競合した場合、競合を解消するために作業ツリーとインデックスが使用されることになりますが、コミットしていないローカルな変更が 存在した場合には、それらが競合を解消させる妨げになってしまうからです。 (ローカルにコミットしていない変更がある状態で"pull"をした場合でも Gitは変更を取得しますが、マージは拒否します。 その場合、アリスはローカルの変更を何らかの方法で取り除いた後に、再度pullする 必要があります)
アリスはマージをしなくても"fetch"コマンドを使用してボブの作業を確認できます。 "fetch"をすると特別なシンボル"FETCH_HEAD"が使用可能になり、 ボブの作業がpullに値するかどうかが次のようにして検査できます:
alice$ git fetch /home/bob/myrepo master
alice$ git log -p HEAD..FETCH_HEAD
この操作はたとえアリスがコミットしていないローカルな変更を持っていても安全です。 範囲表記 "HEAD..FETCH_HEAD" は "FETCH_HEADから到達可能な全履歴のうちHEADから到達可能な履歴は除外して表示する"という意味です。 アリスはすでに現在の状態(HEAD)から到達可能な履歴は全て知っているので、 このコマンドを使うことでボブの状態(FETCH_HEAD)にある未知の履歴をレビューすることができます。
フォーク後のボブの変更履歴を可視化して表示したい場合、アリスは次のコマンドを実行します。
$ gitk HEAD..FETCH_HEAD
ここでも先ほどの git log で説明した2つのドットで表した範囲表記を使用しています。
アリスは分岐以降に彼ら二人が行った作業を見たいかもしれません。 その場合は2つドットのかわりに3つのドットを使用します:
$ gitk HEAD...FETCH_HEAD
これは "どちらか一方からは到達可能な履歴のみ表示し、両方から到達可能な履歴は表示しない" という意味です。
これら範囲表記はgitkと"git log" 両方で使用可能であることに注意してください。
ボブの作業を検査した後、急を要するものがなければ、 アリスはボブからpullをせ ずに自分の作業を続行することができます。 もしボブの履歴にすぐ必要となるもの があれば、アリスはまず最初に処理中の作業を退避(stash)してから "pull" をし、その後で履歴の先頭に作業中の変更を再適用することもできます。
小さいお互いによく連絡をとりあうグループで作業をするときには、 同じリポジトリと繰り返し通信するのはよくあることです。 'リモート'のリポジトリの略称を定義するとその作業がしやすくなります:
alice$ git remote add bob /home/bob/myrepo
こうすることで、アリスはボブのリポジトリのパスを書かなくても'git fetch'をするときに "bob" という名前を使えるようになります:
alice$ git fetch bob
パスを指定した時と違い、git remote
で設定したリモートリポジトリの略称を使って変更を取得した場合には、取得した情報はリモート追跡ブランチに保存されます。 この例の場合は
bob/master
です。従ってこの後には:
alice$ git log -p master..bob/master
を実行すると、アリスの master ブランチから分岐した以降のボブの変更全てが表示されます。
それら変更を確認した後に、アリスは彼女の master ブランチに変更をマージすることができます:
alice$ git merge bob/master
この merge
は 彼女自身のリモート追跡ブランチから取得(pull)する ことによって行うこともできます。次のように:
alice$ git pull . remotes/bob/master
git pull は常に現在のブランチにマージすることに注意してください。 これはコマンドラインで他の引数を与えても変わりません。
その後、ボブは次のようにしてアリスの最新の変更を彼のリポジトリに反映できます。
bob$ git pull
ボブはgit pullの引数にアリスのリポジトリパスを指定する必要がない点に注意してください。ボブがアリスのリポジトリを複製した時に、Gitがアリスのリポジトリ位置を設定ファイル内に自動的に保存されています。git pull した時にその値が使われています:
bob$ git config --get remote.origin.url
/home/alice/project
(git-clone が追加した設定の完全なリストは git config -l
コマンドで確認できます。また、git-config(1) の man ページに各オプションの説明があります)
Gitは "origin/master" という名前でアリスの master ブランチのコピーを保持しています:
bob$ git branch -r
origin/master
ボブが後に異なるホストで作業することを決めたなら、彼は ssh プロトコルで clone と pull ができます:
bob$ git clone alice.org:/home/alice/project myrepo
別の方法としては、Gitが持っているネイティブなプロトコルや、rsync, http も使用できます; 詳細は git-pull(1) を参照してください。
git はまた、CVS ライクなモードで使用することもできます。 つまり、中央リポジトリを持ち、様々なユーザが変更を push するような使用法です。詳細は git-push(1) と gitcvs-migration(7) を参照してください。
履歴の探索
git の履歴は一連の相関的なコミットにより表されています。 我々は既に git-log コマンドがそれらのコミットをリスト表示するのを見ました。各 git log エントリの最初の行が、そのコミットに対する名前を示していることに注意してください:
$ git log
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
Author: Junio C Hamano <junkio@cox.net>
Date: Tue May 16 17:18:22 2006 -0700
merge-base: Clarify the comments on post processing.
この名前を'git-show'コマンドで使用すると、そのコミットに関する詳細を見ることができます。
$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
しかし、それ以外にもコミットを参照する方法があります。そのコミットを一意に特定できるだけの十分な長さをもった先頭の数文字を用いる方法です:
$ git show c82a22c39c # コミット名の最初の数文字で
# 大抵は十分です
$ git show HEAD # 現在のブランチの先端(tip)
$ git show experimental # ブランチ "experimental" の先端(tip)
全てのコミットは常に1つの "parent"(親) のコミットを持ち、プロジェクトの1つ前の状態を指し示しています:
$ git show HEAD^ # HEAD の親を表示
$ git show HEAD^^ # HEAD の祖父を表示
$ git show HEAD~4 # HEAD の4つ前を表示
マージコミットは1つ以上の親を持つ場合があることに注意してください:
$ git show HEAD^1 # HEAD の1つ目の親を表示(HEADと同じ)
$ git show HEAD^2 # HEAD の2つ目の親を表示
コミットに名前をつけることもできます;次のコマンド
$ git tag v2.5 1b2e1d63ff
を実行すると、"v2.5" という名前で 1b2e1d63ff を参照できるようになります。 この名前を(例えば、リリースバージョンを特定する為に)他の人々と共有するには、 "tag" オブジェクトを作成し、それに署名をつけるべきです。; 詳細は git-tag(1) を参照してください。
コミットを引数にとるどんな git コマンドも、この名前を利用できます。例えば以下のように:
$ git diff v2.5 HEAD # 現在の HEAD を v2.5 と比較
$ git branch stable v2.5 # v2.5の位置に "stable" という名前の新しい
# ブランチを作成
$ git reset --hard HEAD^ # 現在のブランチと作業ディレクトリをリセットし、
# HEAD^ の状態にします
上記の最後のコマンドに注意してください:このコマンドは作業ディレクトリ内の変更を失うことに加えて、このブランチにあった全ての保留中のコミットを削除してしまうでしょう。 もしこのブランチがそれらコミットを含む唯一のブランチであった場合、それらコミットは削除されてしまいます。また、他の開発者が pull するような公開ブランチでは git-reset は使用しないでください。もしそうすると、他の開発者に 履歴をきれいにするための不要なマージ作業をさせることになってしまいます。あなたが push した変更を元に戻す必要があるる場合は、git-revert を代わりに使用してください。
git-grep コマンドは当該プロジェクトの任意のバージョン内の文字列を検索します。 例えば、
$ git grep "hello" v2.5
は v2.5 内の "hello" を全文検索します。
コミット名を省いた場合、git-grep は現在のディレクトリ内でGit管理下にある全ファイルを検索します。 従って、次のコマンド
$ git grep "hello"
は、Gitにより管理されているファイルだけを検索するのに便利です。
多くのGit コマンドはまた、コミットの集合を扱うこともできます。その方法は何通りもあります。以下は、git-log における使用例です。
$ git log v2.5..v2.6 # v2.5 から 2.6 までのコミット
$ git log v2.5.. # v2.5 以降のコミット
$ git log --since="2 weeks ago" # 最近2週間のコミット
$ git log v2.5.. Makefile # v2.5 以降に Makefile を
# 変更しているコミット
git log
にはコミットの "範囲" も指定できます。その際、範囲指定の1つ目は必ずしも2つ目の祖先である必要はありません;例えば、ブランチ
"stable-release" と "master" の先端(tip)が、ある時点の共通のコミットから枝分かれしている場合、次のコマンド
$ git log stable..master
は、ブランチ master にあって、ブランチ stable に存在しないコミットを一覧表示します。一方、次のコマンド
$ git log master..stable
は、ブランチ stable にあって、ブランチ master に存在しないコミットを一覧表示します。
git-log コマンドには弱点があります: それはコミットのリスト表示に関するものです。履歴が枝分かれし両者がマージされた開発ラインを持つ場合、git-log の コミットの表示順序には意味がありません。(訳注:とはいえ、--graph のオプションを付ければ、マージの関係が確認できるので大きな問題ではありません)
複数の貢献者を持つ多くのプロジェクト(例えば Linux カーネルや git自身)では、頻繁にマージが行われます。gitk はそれら履歴をビジュアルに表示するので 大変重宝します。 例えば、次のコマンド
$ gitk --since="2 weeks ago" drivers/
は最近2週間に "drivers" ディレクトリを修正したコミットを表示します。 (注意: gitk のフォントはコントロールキーを押さえながら "-" か "+" を押すことで調整できます。)
最後に、オプションとしてファイル名を引数に取る大抵のコマンドが コミットにファイル名を付けられる点を説明します。 あるファイルの特定のバージョンを指し示すには次のようにします:
$ git diff v2.5:Makefile HEAD:Makefile.in
git-show コマンドでも、次のようにファイルを指定できます:
$ git show v2.5:Makefile
次のステップ
このチュートリアルは、あなたがプロジェクトで分散リビジョン管理を行う基礎としては十分な内容です。しかし、Gitの奥深さと能力を十分理解するには、Gitの基礎となる2つのシンプルな概念を理解する必要があります。:
-
オブジェクトデータベース:プロジェクト(ファイル、ディレクトリ、コミット)の履歴を格納するために使われる簡潔なシステムです
-
indexファイル:これはディレクトリツリーの状態を管理するキャッシュです。コミットを作成する時、作業ディレクトリをチェックアウトする時、 マージ時に必要となる様々なツリーを保持するのに使用されます。
チュートリアルのパート2では、 オブジェクトデータベース、indexファイル、そして Git を最大限利用するため必要となる残りの部分について説明します。 gittutorial-2(7)を参照して下さい.
今すぐ続きを学習したくない人は、下記のなかから興味のあるものを読んでみても良いかもしれません:
-
git-format-patch(1), git-am(1): これらコマンドは 一連の git コミットの E-mail パッチへの変換と、その逆をします。Linux カーネルのように E-mail のパッチに強く依存している プロジェクトで役に立ちます。
-
git-bisect(1): プロジェクトで不具合を見つけた時に、履歴からその元になったコミットを探し出して原因を調査することがあると思います。git bisect は二分探索によりコミットを探す手助けをします。 多くのマージブランチを持つ複雑で非線形な場合にも、 最適な探索ができます。
-
gitworkflows(7): 推奨するワークフローの概要紹介
-
gitcvs-migration(7): CVSユーザのためのGit移行ガイド
関連項目
GIT
git(1) スイートの一部