: |
Git バージョンコントロールシステムへようこそ! ここでは、現在あなたが有している Subversion の知識を元に、Gitの使いかたを簡単に紹介していくよ。 最新の Git をインストールしておこう。 Git ドキュメントの中にも、とっても有益なチュートリアルが用意されている。
もし、誰かのプロジェクトを追い掛けたいだけなら、これだけで簡単に開始できるよ。
|
こんな感じの小さなテーブルの中では、特定のタスクを行うGitのコマンドを常に左側に、一方右側には、Subversionで同じ作業を行う時に使うと思われるコマンドが並べられている。 もし急いでいるのなら、このテーブル群へザッと目を通すだけでも、Git の基本的な使い方を知ることができると思うよ。
どんなコマンドも、初めて実行する前には、該当するマニュアルページへ、少なくとも簡単には、目を通すことをお勧めする。
多くのコマンドには、(僕らがここで取り上げていない)便利且つ、興味深い機能が実装されているし、知っておいた方が良い注意事項の書かれていることも時々ある。
使いかたの簡単なヘルプは、Git のコマンドへ-h
スイッチを指定することで参照可能だ。
Gitを使い始めるにあたって、知っておいたほうが良い、大事なコンセプトが幾つか存在する。 とはいえ、もし凄く急いでいるなら、このセクションをひとまず読み飛ばし、ひどく混乱してしまった場合にだけここへ戻ってくる、という方法も良いよね。 面白そうなものだけ読む、というのもありかもね。
.git
サブディレクトリ内にある)。
そのため、ローカルとリモートの複数ブランチを持つことが可能だ。
また、一般的にベアリポジトリと呼ばれる、ワーキングコピーにくっついていないリポジトリを作ることもできる。
これは、あなたがリポジトリを公開したい場合に、特に有益だ。
これに関しては、後で試してみよう。
trunk/
、branches/
、tags/
ディレクトリが作られるだろう。
Gitでは、URLはリポジトリの位置を示すためだけに使われ、リポジトリには常にブランチとタグが含まれる。
ブランチの1つがデフォルトだ(通常、master と名前が付けられている)。
HEAD
で参照できるし、その親にはHEAD^
が、そのまた親にはHEAD^^ = HEAD~2
が使える(キャレットを繋げてゆくことも可能だよ)。
カットアンドペーストも凄く手助けになるし、リビジョンの先頭数文字書くだけでも大丈夫。
その値がユニークである限り、残りは Git が補ってくれるよ(リビジョン指定子を用いることで、より進んだ使いかたも可能だ。
詳しくは、git-rev-parse のマニュアルページを参照のこと)。
git confilg -l
コマンドを使おう。
また、設定するには次のコマンドが使用できる。
git config --global user.name "あなたのお名前をここへ" git config --global user.email you@yourdomain.example.com
git command
という形式をしている。
git-command
という形式も同様に利用可能だ。
git config --global color.diff auto git config --global color.status auto git config --global color.branch auto
gitk
を使うと便利かも。
まず最初の一歩として、あなたのプロジェクトを Git に追跡させ、日々の開発がどんな感じになるのか見てみることにしよう。
あなたのプロジェクトがあるディレクトリへ cd
して、真新しい Git リポジトリを初期化してみよう。
git init git add . git commit |
svnadmin create repo svn import file://repo |
git init
はリポジトリを初期化し、git add .
は 現在のディレクトリ配下にある全てのファイルを追加する。
またgit commit
は最初のインポートを作成する。
これでこのリポジトリは、作業コピーへと結びつけられた。
さて、これであなたのツリーは、正式に Git で追跡されるようになった。
もし興味があるなら、.git
サブディレクトリの中を少し探索してもいいし、特に気にならないなら、別に覗かなくても構わない。
適当にあなたのツリーへ変更を加えてみよう。
例えば、幾つかのファイルを弄くりまわす、とかね。
僕らの行なった変更をチェックしてみよう。
git diff | svn diff | less |
まさに、これだ。 これは最もパワフルなコマンドの一つなんだ。 特定リビジョンとpathとのdiffを得るには、こんな感じ。
git diff rev path | svn diff -rrev path |
Git は diff に対し、追加や削除、モード変更に関する特別な情報を埋め込む。
git apply | patch -p0 |
このコマンドは、これらの「メタ変更」を Git へ伝え、実行させながら、パッチを適用する。
変更をもっと簡単に確認する方法がある。
git status | svn status |
これは、変更のサマリーを、ファイルのリスト(但し、ignore に設定していたり Git へその旨伝えてあるものは除く)と共に、分りやすい形式で表示してくれる。 また、冒頭には、現在あなたの居るブランチ名も表示されているだろう。
status コマンドを使うと、そのうち、大量の「Untraceked files」が登場してくるかもしれない。
これらは、Git に追跡されていないファイルだ。
だけど、これらのファイルを add するのは、ちょっと待って。
もしこれらのファイルを一掃したいなら、git clean
を実行しよう。
もしくは、ファイルを追跡しないまま放置しておきたいのであれば、これらを.gitignore
ファイルへ追加しよう(これはSVNのsvn:ignore
プロパティと同じように機能する)。
ファイルを最新版へ復元するにはこのコマンド。
git checkout path | svn revert path |
全てのファイルを復元することも出来るし、指定したファイルだけを復元することも可能だ。
SVN と同じく、ファイルを add や move、remove した場合には、その旨、Git へ教えてあげなければならない。
git add file
git rm file git mv file |
svn add file svn rm file svn mv file |
また、add/remove、はディレクトリ全体等に対して、再帰的に行うことも可能だ。 GitはCoolだね!
さて、そろそろ、変更をコミットする時がきたようだ。 驚くべきことに、次のコマンドは全ての変更点をコミットする。
git commit -a | svn commit |
または、Subversionのように、指定されたファイル等だけをコミットするように制限することも可能だ。
コミットメッセージに関して一言。
メッセージの1行目には、コミットに関する短めのサマリを書くことが慣例となっている。
これは、様々なツールが、コミットをリスト表示する際、メッセージの最初の行だけを表示することが多いためだ。
従来のように、-m
パラメタを使って、コミットメッセージを指定することは可能だけど、複数の-m
引数を使うこともできる。
この場合、各要素が段落として、コミットメッセージが構築されることになる。
もし、-m
パラメタを指定しなかったり、または、-e
パラメタを指定した場合には、あなたの愛用の$EDITOR
が起動されるので、それを使ってコミットメッセージを書くことができる。
丁度Subversion と一緒だ。加えて、コミットされるファイルのリストも示される。
またオマケとして、-v
パラメタを指定すれば、コミット予定のパッチ全体がエディタ内に表示される。
これにより、手早く最後のレビューを行うことが可能だ。
ところで、コミットでヘマをやらかした時、Subversionだと、今一わけのわからないsvnadmin
サブコマンド群を使う以外、あなたの出来ることは多くないよね。
Gitならばもっと上手くできる。
最後のコミットを修正(メタデータを再編集したり、ツリーを更新したり)する為に、git commit --ammend
が利用できる。
または、最後のコミットを、git reset HEAD^
で完全に葬りさってしまうこともできる。
これは、作業ツリーは変更しないよ。
幾つかコミットしたので、履歴を確認してみよう。
git log git blame file |
svn log | less svn blame file |
log コマンドの挙動は、SVN と Git で大変よく似ている。まぁ、ここでも、git log
の方が少しばかりパワフルなんだけどね。どんなことが出来るのか、オプションを調べてみて欲しい。
blame コマンドは更に強力で、行の変遷を追いかけることができる。
たとえそのファイルがコピーされたり改名された場合でも、追跡可能だ。
でも、あなたが何か違ったことをしたいと思っている大きな可能性があるよ!
大抵 annotate を使うときは、あるコード片の起源を探している時で、所謂 Git のpickaxeは、この作業へより一層適したツールなんだ(git log -Sstring
は、stringに合致するファイルを追加したり、削除したコミットを表示してくれる)。
ファイルの中身や、ディレクトリのリスト、コミットを確認したいときには、次のコマンドが利用できる。
git show rev:path/to/file
git show rev:path/to/directory git show rev |
svn cat url
svn list url svn log -rrev url svn diff -crev url |
Subverison では、履歴上にチェックポイントを残しておくために、コピーを使っていて、このコピーは、通例、tags と名付けられたディレクトリ内へ置かれる。 Git のタグはより強力だ。 Git のタグへは、任意の説明を付けることができ(1行目が、特別な意味を持つのはコミットの場合と同様)、実際、リリースアナウンス全体をタグの説明文へ納める人もいる。 タグづけした人のIDが格納される(こちらも、コミッタのIDルールと同様だ)。 コミットではない、他のオブジェクトへタグを打つことも出来る(が、これは、概念的に、幾分 low-level な操作となる)。 IDを検証する為に、タグはPGPで署名することも出来る(Git の本質的な挙動として、署名は関連するリビジョンや履歴、ツリーに対しても検証される)。 というわけで、次のコマンドを実行してみよう。
git tag -a name | svn copy http://examplecom/svn/trunk http://example.com/svn/tags/name |
タグのリスト、ならびに、タグのメッセージを見るには以下のコマンド使う。
git tag -l git show tag |
svn list http://example.com/svn/tags/
svn log --limit 1 http://example.com/svn/tags/tag |
Subversion同様、Gitではブランチを作ることができる(こりゃ、驚いた!)。Subversion では、基本的に、プロジェクトをサブディレクトリへとコピーする。Gitでは、その旨を、つまり、まぁ、ブランチを作れ、って指示すればよい。
git branch branch
git checkout branch |
svn copy http://example.com/svn/trunk
http://example.com/svn/branches/branch
svn switch http://example.com/svn/branches/branch |
最初のコマンドではブランチを作成し、次のコマンドでは、あなたのツリーを特定ブランチへとスイッチしている。新しいブランチの作成時、最新以外のリビジョンをベースにしたい場合には、git branch
へ引数を指定しよう。
ブランチのリストは、先に説明した git-branch
コマンドを使うことで簡単に見ることができる。引数にブランチリストを指定せず実行しよう。
現在のブランチは「*」で示される。
git branch | svn list http://example.com/svn/branches/ |
あなたのツリーを、古いリビジョンへ戻したい場合には、次のコマンドを使おう。
git checkout rev
git checkout prevbranch |
svn update -r rev svn update |
または、一時的なブランチを作ってもよい。 Gitでは、古いリビジョンの上にコミットを作成し、それを別のブランチとして使うことが可能だ。
Git ではブランチ間のマージを、Subversion よりもずっと良い具合にサポートしている。 両ブランチの履歴はマージ後も保持されるし、同じブランチ間同士でのマージの繰り返しも、意識せず利用可能だ。 マージされる側のブランチ上にいることを確認して、もう片方のブランチをマージしてみよう。
git merge branch | (ブランチはリビジョン20で作成され、あなたは trunkの作業コピー内にいると仮定)
svn merge -r 20:HEAD http://example.com/svn/branches/branch |
もし、最後のマージ以後、片方のブランチでしか変更が行われていなければ、単純に、他方のブランチでもその変更が繰り返される(所謂、高速前進マージ(fast-forward merge))。
もし両方のブランチが変更されていた場合、変更点は、賢くマージされる(これは、3方向マージ(three-way merge)と呼ばれる)。
もし、変更点が衝突した場合、git merge
は、木の残りを結果状態へと更新し、その旨を報告してあなたへと解決を依頼する。
衝突を解決したらgit commit
を実行しよう。
変更が衝突しなかった場合、手頃なログメッセージと共に commit が自動的に実行される(またはgit merge --no-commit branch
を実行することで、マージの結果を確認し、自分自身でコミットを行うこともできる)。
マージとは別に、時には、別のブランチから、コミットを1つだけ適用したい、と思うこともあるだろう。 リビジョンrevの変更点を適用し、現在のブランチへコミットするには、次のコマンドを使おう。
git cherry-pick rev | svn merge -c rev url |
今迄のところ、僕らは Git が分散バージョン管理システムである、ということを無視してきたけど、そろそろ、真実に目を向けても良いんじゃないかな。 というわけで、リモートサイトからの取得を行ってみよう。
もしもあなたが、別の誰かのプロジェクトで作業をしよう、と思っているのなら、大抵は、自身のリポジトリで作業を開始するかわりに、その人のリポジトリをcloneしたいと思うだろう。 これに関しては、既にこのドキュメントの先頭で説明した。
git clone url | svn checkout url |
さて、あなたはデフォルトブランチ(通常はmaster
)を手にしているわけだが、加えて、全てのリモートブランチとタグも手にしている。
clone のデフォルト設定では、デフォルトのローカルブランチはoriginリモートを追跡しているんだけど、これはリモートリポジトリ内のデフォルトブランチを指し示している。
え? リモートブランチって何かって? そうだね、ここまで、僕らは、ローカルブランチだけで作業してきたからね。 リモートブランチは、リモートリポジトリ内にあるブランチのミラーイメージで、これに対しては、決して直接 switch したり、書き込んだりすることはできない。 もう一度言わせて欲しい、あなたは決してリモートブランチに干渉することはできない。 もし、リモートブランチにスイッチしたいと思ったら、リモートブランチを「追跡(track)」する為のローカルブランチを作成する必要がある。
git checkout --track -b branch origin/branch | svn switch url |
もし、常にリモートブランチを追跡したい場合(そして--track
の事を忘れたい場合)、次の設定を行おう。
git config --global branch.autosetupmerge auto
複数のリモートブランチを clone したリポジトリへ追加したい場合、または、単に初期化したい場合には、git remote add remote url
コマンドを使えばよい。
git remote
コマンドは、全てのリモートリポジトリを表示してくれるし、git remote show remote
はリモートリポジトリ内のブランチを表示してくれる。
さて、リモートリポジトリから新しい変更点を入手するにはどうしたら良い? 掴みとって(fetch)くれば良いのさ: git fetch
。
この時点で、変更点はあなたのリポジトリへ格納されていて、git log origin
でそれを確認することができるし(git log HEAD..origin
で、あなたのブランチに存在していない変更点だけを確認することが可能だ)、diff することも、そして勿論、マージすることも出来る。単にgit merge origin
を実行するだけだ。
もし fetch するブランチを指定しなかった場合には、便利なことに、リモートのトラッキングをデフォルトで行ってくれる、ということを伝えておこう。
リモートブランチを追跡する場合には頻繁に fetch + merge を行うことになるから、これを自動化する為のコマンドが存在する。
git pull | svn update |
あなたのローカルリポジトリは、変更をpullする為に他人が使うことも出来るけど、通常は、プライベートなリポジトリとパブリックなリポジトリとを持つんじゃないかな、と思う。
パプリックリポジトリは、誰もが pull できるところで、そしてあなたは、えーと、その反対? 変更点をpushするってこと?
その通り!
git push remote
で手元の全てのブランチを、対応するリモートブランチへpushできるんだ。
この操作は、一般的には、SSH(か、特別な設定が行われたWebServerであればHTTP)上でのみ動作することに注意。
SSHキーとSSHエージェントメカニズムの設定を、強く強く推奨する。
そうでないと、パスワードをひっきりなしに打ち込むことになっちゃ
うよ。
1つ重要な点は、現在、あちら側で check out の行われていないリモートブランチへだけ push するようにすべきだ、ということ(同じ理由から、ローカルでは、決してリモートブランチへスイッチしてはならない)! そうでないと、リモートブランチにある作業コピーが古いものになってしまい、混乱は免れない。 これを避ける最良の方法は、作業コピーを全く持っていないリポジトリ - このためベア(bare)リポジトリと呼ばれている - に対してだけ push すること。 このリポジトリは、パブリックアクセスの為や、開発者の落ち合う場所、例えば履歴を交換したりするだけのような、どのみち、チェックアウトコピーが空間の無駄になるような場所で、一般的に使われている。 あなたもこのようなリポジトリを作れるよ。 詳細は「公開リポジトリの設定」を参照のこと。
GitはSubversionと同じワークフローで動作することが可能で、作業結果の交換の場として単一リポジトリを利用している開発者グループとともに用いることが出来る。
唯一の違いは、変更内容が自動的には投稿されず、代わりに、push しなければならない、という事だ(但し、post-commit フックを設定することで、コミットが行われる度にpush が行われるようにすることも可能ではある。
とはいえ、これは、グチャグチャになったコミットを修正する、といった柔軟性が失われることになるけれど)。
開発者は、(HTTP DAVを使う場合には)htaccess のエントリ、もしくは、(SSHを使う場合には)UNIXのアカウントを有している必要がある。
彼らのシェルアカウントを、Gitのpush/fetch に限定したい場合には、git-shell
をログインシェルに指定すればよい。
パッチをメイルで交換することも出来る。
Gitはメイルで送られてきたパッチ群に対して、非常に便利な機能を提供している。
これらパッチ群の適用は、パッチメイルが格納されているメイルボックスをgit am
へ指定することで可能だ。
パッチを送りたい場合には、git format-patch
と、恐らくgit send-email
が利用できる。
パッチ群の管理には、StGITツールを使うのがベストだ(StGIT Crash Courseを参照のこと)。
質問や問題など、このドキュメントでは分からないことがある場合には、お気軽にGit mailgin list(git@vger.kernel.org)まで英語でご連絡を。 ぜひGitで快適な時間を!