git

ソースコードなどの分散型バージョン管理システム

これはこのページの過去の版です。Iwai.masaharu (会話 | 投稿記録) による 2017年1月31日 (火) 13:35個人設定で未設定ならUTC)時点の版 (提案:#関連文献(書籍や雑誌記事のリスト)の編集除去)であり、現在の版とは大きく異なる場合があります。

git(ギット[1][2][3])は、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。Linuxカーネルのソースコード管理に用いるためにリーナス・トーバルズによって開発され、それ以降ほかの多くのプロジェクトで採用されている。Linuxカーネルのような巨大プロジェクトにも対応できるように、動作速度に重点が置かれている。現在のメンテナンスは濱野純 (Junio C Hamano) が担当している。

git
git logo
gitのWebインターフェース、gitweb
開発元 濱野純, リーナス・トーバルズ, ほか多数
初版 2005年12月21日 (18年前) (2005-12-21)
リポジトリ ウィキデータを編集
プログラミング
言語
C, Bourne Shell, Tcl, Perl
対応OS Unix系, Linux, Windows, macOS
種別 バージョン管理ソフトウェア
ライセンス GNU General Public License バージョン2,GNU Lesser General Public License 2.1
公式サイト git-scm.com
テンプレートを表示

gitでは、各ユーザのワーキングディレクトリに、全履歴を含んだリポジトリの完全な複製が作られる。したがって、ネットワークにアクセスできないなどの理由で中心リポジトリにアクセスできない環境でも、履歴の調査や変更の記録といったほとんどの作業を行うことができる。これが「分散型」と呼ばれる理由である。

背景および概要

Linuxカーネルの開発では、Linux Kernel Mailing Listに投稿される多数のパッチをメンテナーたちがソースコードに適用するという形式が採用されている。これらの作業を効率的に行うため、当初はBitKeeperというバージョン管理システムを用いていたが、このソフトウェアは商用ソフトウェアであった(クライアントはバイナリ版のみ無料で、サーバは商用だがBitMover社の好意で無料で使えていた)。この状況を快く思わない人々がBitKeeperのクローンを実装したことから、この環境が使えなくなってしまい(BitKeeper#ライセンス問題BitKeeper#価格変更を参照)、その代替として2005年にgitが開発された。[4]

Linuxカーネルの開発では、巨大なソースコードの集合を扱うため、変更点の抽出やリポジトリ操作ができるかぎり高速にできる必要がある。他の様々なバージョン管理システムをあたったが、満足のいくものがなかったため、gitではこのような問題も出来る限り解決できるよう、いくつかのアイデアが導入されている(この部分は、他のバージョン管理システムにも同様の機能が導入されるようになった)。

作業の流れ

gitは分散型のソースコード管理システムであるため、リモートサーバ等にある中心リポジトリの完全なコピーを手元(ローカル環境)に作成して、そのローカルリポジトリを使って作業を行う。

一般的な開発スタイルでは、大雑把に言えば、以下のようなステップの繰り返しで作業が行なわれる:

  1. リモートサーバ等にある中心リポジトリをローカルに複製する (git clone)。
  2. ローカルでコンテンツの修正・追加・削除を行い、ローカルリポジトリに変更履歴を記録する (git commit)。必要に応じて過去の状態の閲覧や復元などを行う。場合によってはこのステップを何度か繰り返す。
  3. 中心リポジトリに加えられた他人による変更をローカルに反映させる (git pull)。他人の変更内容が自分の変更内容と衝突することもある。衝突は、gitが自動で解決できることもあれば、手動で解決しなければならないこともある (git merge)。
  4. ローカルの変更内容を中心リポジトリに反映させる (git push)。ステップ2.へ戻る。

リポジトリ間の通信 (clone, pull, push) では以下のプロトコルが使用できる[5]

rsyncFTP/FTPSは、もはや使うべきではないとされている[6]

設計

gitの設計はBitKeeperMonotoneが元になっている[7][8]。元々のgitはローレベルなエンジンとして設計されていたが、これは、他の開発者がCogitoStGITのようなフロントエンドを容易に開発できるようにすることを目的としていた[9]。現在では、gitのコア自体もユーザから直接利用できるようになっている[10]

gitの設計には、リーナスが大規模プロジェクトのメンテナンスを行った経験や、ファイルシステムのパフォーマンスに関する深い知識、また実用性のあるシステムを短期間に作成しなければならないという差し迫った必要性(BitKeeperを参照)が反映されている。これらの影響は、以下のような形で実装に現れている。

  • ノンリニアな開発スタイルに対する強力なサポート。gitではブランチやマージが高速に行える。また、ノンリニアな開発の履歴を可視化・ナビゲートするための専用のツールを同梱している。また、ツリーに対する1回の変更に対して、複数回のマージが発生するという前提を置いているが、これは変更点が複数のレビュアーによってレビューされることを想定しているためである。
  • 分散開発。他の分散型バージョン管理システム(DarcsBitKeeperMercurialSVKBazaarMonotone)と同様に、gitでも各々の開発者がリポジトリの完全なコピーをローカルに保持しており、各開発者の行った変更は他のリポジトリにコピーされる。これらの変更は新しい開発用ブランチとしてインポートされる。また、ローカルな開発用ブランチへのマージも可能である。
  • HTTPFTPrsync、gitプロトコル(sshを利用したトンネリングも可能)を使用したリポジトリの配布が可能。また、CVSサーバのエミュレーション機能を使用すれば、既存のCVSクライアントやIDEのプラグインからgitリポジトリにアクセスできる。
  • git-svnを使用すれば、Subversionおよびsvkのリポジトリを直接操作できる。
  • 大きなプロジェクトにおける処理の効率化。gitは非常に高速かつスケーラブルになるよう記述されている[11]Mozillaによって行われたパフォーマンステストでは、他のリビジョンコントロールシステムと比較して10倍、処理によっては100倍高速に動作することが示された[12][13]
  • ツールキット化された設計。gitはC言語で書かれたプログラム一式と、それらのラッパーとなる何本かのシェルスクリプトで構成されている[14]。gitをWindowsに移植する過程で、シェルスクリプトのほとんどはC言語で書き直された。しかし、現在でも複数のコンポーネントを繋げることで複雑な処理を容易に行えるような設計になっている[15]
  • プラガブルなマージアルゴリズム。gitでは不完全なマージに対する優れたモデル化が行われている。また、不完全なマージを補完するアルゴリズムも複数存在する。最終的に自動的なマージが行えなかった場合には、ユーザによる編集が必要である旨がユーザに通知される。
  • ガベージコレクションは行われない。操作を中断したり変更の取り消しを行った場合、データベース中には不要なデータが残ったままになる。これらのデータは操作対象のオブジェクトの履歴に比例して大きくなる。git-gc --pruneコマンドを使用して明示的にガベージコレクションを行うこともできるが、この処理には時間がかかる[16]

gitの特徴の一つとして、ディレクトリツリーに対するスナップショットを作成する点が挙げられる。初期のバージョン管理システム(SCCSRCS)では、個々のファイルを処理の対象としており、直近のバージョンに対して差分符号化を行うことでリポジトリのサイズを縮小することに機能の重点が置かれていた。以降のバージョン管理システムでも、この「プロジェクト内の複数バージョンにまたがって一つのファイルを追跡できる」という概念が継承されていた。

一方、gitではこのコンセプトを使用していない[17]。その結果として、gitはソースコードツリー中のファイルのリビジョン間の関係性を記録しなくなっている。これにより、gitは以下のような特徴をもつようになっている。

  • プロジェクト全体の変更履歴を調べるよりも、一つのファイルの変更履歴を調べる方が時間がかかる[18]。特定のファイルの変更履歴を取得する場合、gitはツリーの履歴全体を走査し、各リビジョンでそのファイルに変更があったかどうか調査する必要がある。ただしこの処理手順では、一つのファイルに対しても、任意のファイルの集合に対しても、ほぼ同じ時間で履歴の調査が行える。よく行われる処理としては、例えば「ソースツリー中のあるサブディレクトリと、それに関係するヘッダファイルの調査を行う」といったものがある。
  • ファイル名の変更を明示的に扱わない。CVSに対してよく挙げられる不満として、ファイルのリネームや移動を行うと変更履歴が途切れてしまう問題がある。これは、変更履歴の識別にファイル名を使用しているためである。CVS以降に開発されたバージョン管理システムの多くでは、管理対象のファイルに対してファイル名より寿命の長い、内部的な名前(inode番号のようなもの)を付与することでこの問題を解決している。一方、gitではそのような内部名を使用しておらず、その点が長所であるとしている[19][20]。プログラムのソースコードに対しては、リネームの他にも分割やマージといった処理が行われる[21]。これらの処理を単純にファイルのリネームとして十把一絡げに扱うと、実際にソースコードツリーに対して行われた処理が何であるか不明瞭なまま履歴に記録されてしまう。gitでは、リネームの検出をスナップショット作成時ではなく履歴のブラウズの際に行うことでこの問題を解決している[22]。(単純に考えれば、リビジョンN中のあるファイルに対して、リビジョンN-1中に同じ名前のファイルがあれば、それが元ファイルと考えられる。しかし、リビジョンN-1中に似たような名前のファイルがない場合もある。この場合gitは、リビジョンN-1のみに存在し、かつ似たような内容のファイルを検索する。)しかし、この処理は履歴の表示を行う度にCPUに負荷のかかる処理が必要となる。そのため、使用するヒューリスティックを選択するオプションが提供されている。

リポジトリの保存方法については批判もある。

  • gitは新しく作成されたオブジェクトを個別のファイルの形で保存する。各ファイルは圧縮されて保存されるが、そうであったとしてもこの方法は記録領域を大量に必要とするため非効率的である。gitはこの問題を“pack”を使用することで解決している。複数のオブジェクトは一つのファイル(またはネットワークバイトストリーム)の形にパックされ、各pack間で差分圧縮が行われる。packの差分圧縮にはヒューリスティックが用いられる。例えば、同じ名前のファイルは似た内容である可能性が高いものとして処理される。ただし、リポジトリの正確性を保つため、ヒューリスティックに完全に依存することはない。現在のgitでも新しく作成されたオブジェクト(新しく加えられた履歴)はまず単一のファイルとして保存されるため、空間効率を高く保つためには定期的な再パックが要求される。gitはこの定期的な再パックを自動的に行うが、git gcコマンドを使用することで手動で再パックを行うこともできる。

gitは以下のマージアルゴリズムを実装している。アルゴリズムはマージ時に選択することができる[23]

resolve
従来通りの3-wayマージアルゴリズムを使用する。
recursive
3-wayマージの変種を使用する。ブランチのmergeやpullを行う場合のデフォルトである。3-wayマージにおいて共通の祖先が複数ある場合、共通の祖先からのmerge treeを作成し、それをreference treeとして3-wayマージを行う。Linuxカーネル2.6の開発で行われたマージコミットの履歴から、このアルゴリズムを使用するとマージの衝突が少なく、マージ漏れもなかったことが報告されている。さらに、リネームを伴うマージに対しても検出および処理が可能である[24]
octopus
3つ以上のheadからのマージを行う場合のデフォルトである。

歴史

名前の由来

リーナス・トーバルズによれば[25]

僕は自己中心的な奴だから、自分のプロジェクトには自分にちなんだ名前を付けるようにしているんだ。最初はLinuxで、今度はgitだ。

英語のスラングとして、gitには「バカ」「間抜け」といった類の意味がある。この自虐ネタはもちろん皮肉で、これはリーナスがLinuxの名前を決める際に自身の名前にちなんだ名前を付けるよう強要されたことから来ている。(Linux#名前の由来を参照)

gitのオフィシャルサイトのWikiでは、“git”という名前に対して他にもいくつかの解釈がなされている。例としてはGlobal Information Trackerなどが挙げられる[26]

開発初期の歴史

gitの開発は、Linuxカーネルの開発者の多くがBitKeeperのシステムに対するアクセスを禁止されたことに端を発している(BitKeeper#価格変更を参照)。これは、アンドリュー・トリジェル(Andrew Tridgell)がプロプラエタリなソフトウェアであるBitKeeperのプロトコルをリバースエンジニアリングしたことに対し、BitKeeperの著作者であるLarry McVoy(en)がこれをライセンス違反であるとして、BitKeeperの無料提供を止めたためである。Linux.conf.au 2005のキーノートにおいて、Tridgellはこのリバースエンジニアリングの手順について説明を行ったが、内容はBitKeeperのサーバの適切なポートにtelnetでアクセスし“help”とタイプするだけという単純なものだった[27]

リーナスはBitKeeperと同じように使える分散型バージョン管理システムを探していたが、無料のシステムで彼の要求(特に速度面での要求)に適合するものは見つからなかった。リーナスが書いたメールによると、2005年4月7日頃に最初のプロトタイプを作成していたようである[28]

だけど、僕が見たSCMたちはそれ(bk pull相当のこと)をするのが大変だったんだ。僕がやろうとしていることの1つは(実はこれが一番なんだけど)その過程を十分効率的にすること。もし1つのパッチを適用してその変更の境界を記録するなどするのに30秒かかったとすると(正直、Linux規模のプロジェクトで30秒っていうのは大抵のSCMでは速いほうの見積りだけど)、250通(例えばAndrew[29] と同期するときには決して珍しい量じゃない)のメールパッチを適用するのに2時間かかることになる。

BKはスピード狂ではなくて、(他のSCMと比較するとBKは1桁か2桁くらいは高速だけど)Andrew[29]とマージをする時に1メールにつき約10-15秒かかっていた。だけど、BKではそれは大きな問題にならなかったんだ。BK<->BK間のマージは簡単だから、僕は他の主要な開発者とは時間がかかるメールでのマージをしたことはなかったから。パッチアプリケーションに基づいたSCMにするなら、“マージ機能”をBKよりも速くしなければならなくなる。それは本当に本当に大変なこと。

だから、僕はいまスクリプトを書いていて、変更をずっと速く追跡できるようにしているんだ。最初の目標はパッチを適用するのと同じくらい高速にそれを行うこと。だけどはっきりいって、今のところできたのは多く見積もってもまだ半分くらいで、思わぬ障害にぶつかったら全然嘘になるかもしれないけど。いずれにせよ、僕がそれをすぐにできる理由は、僕のスクリプトがSCMではないからで、とても特別で“Linuxの状態を記録する”ようなものだからなんだ。それはリニアなパッチを十分効率的な時間でマージできるようになるだろう。

(パッチの適用が3秒でできるなら、大きな1つながりのパッチでも問題にはならない: 途中で失敗しても1分か2分で気がつくなら、それで十分で、手作業で修正することができる。待ち時間が重要な理由はそこにある。--“オフライン”で効果的にそれができるなら、問題が起きた時に僕は定義どおりそれを修理できずにいるだろう)

リーナスは以下のような原則に基づいて設計を行っている。

  1. CVSを「悪い見本」とする。設計上のことで確信が持てない場合は、CVSと逆の決断をする。リーナスは冗談めかして以下のように語っている。
    “カーネルメンテナンスの最初の10年間、僕らは文字通りtarボールとパッチを使っていた。CVSよりもずっと優れたソース管理システムさ。僕は営利企業 (トランスメタ[30]) でCVSを7年間使わされたことで、CVSを強烈に憎むようになった。CVSを強烈に憎んでいると言う時には、このことも言っておかなくちゃいけないね。観衆の中にSVN(Subversion)のユーザがいるなら、この場から去ったほうがいいかもしれない。僕がCVSを強烈に嫌悪しているということは、僕がSubversionが史上最大の無意味なプロジェクトであると思っていることも意味しているんだ。Subversionのしばらくのスローガンは‘ちゃんとCVSをやる’とかそんなものだったよね。そんなスローガンから始めたら、どこにも辿りつけないよ。CVSをちゃんとやるなんて不可能なのさ。”[31]
  2. 分散型の、BitKeeperのようなワークフローをサポートする。
    “BitKeeperだけが、「まあ使ってもいいかな」と最初に思わせてくれたSCMだというわけではないけれど、BitkeeperはSCMというものの存在意義と、実際にどう使うことができるのかを教えてくれた。だから、gitは技術的な観点とかいろんなところでBitkeeperとは随分違うものになっているけど(それはもう一つの設計目標でもある。Bitkeeperのクローンではないことをはっきりさせたかったから。)、gitのワークフローの多くは、Bitkeeperが教えてくれたフローから直接きたものになっているんだ。”[31]
  3. データ破壊に対する強力な抑止機能。データ破壊は、偶然によるものと意図的なものの両方を想定している[32][31]
  4. 非常に高い処理速度。

最初の3つの条件によって、既存のバージョン管理システムはMonotoneを除き全て選に漏れてしまい、4つ目の条件で該当するものがなくなってしまった[31]。そのため、Linuxカーネル2.6.12-rc2のリリース直後に[31]、リーナスは自分で開発を始めた[31]

gitの開発は2005年4月3日に開始された[33]。プロジェクトとしてのアナウンスは4月6日に行われ[34]、4月7日にはセルフホスティングされるようになった[33]。4月18日には複数のブランチからのマージが最初に行われた[35]。4月29日にはリーナスの目標としていた処理速度が実現された。Linuxのカーネルツリーにパッチを当てるベンチマークで、初期のgitでは毎秒6.7個のパッチを処理している[36]。6月6日には、gitによるLinuxカーネル2.6.12のリリースが行われた[37]

BitKeeperからの影響で、リーナスは従来と同じようなアプローチを意図的に避けており、結果としてgitは非常にユニークな設計になっている[38]。技術に長けたユーザがgitを利用できるようになるレベルまではリーナスが開発を行っており、その後、2005年6月26日にはプロジェクトへの主要な貢献者であったJunio C Hamanoにメンテナンスが引き継がれた[39]。Hamanoは2005年12月21日にバージョン1.0のリリースを行い[40]、2009年3月現在も彼がメンテナンスを行っている。

脚注

  1. ^ Tech Talk: Linus Torvalds on git (1分30秒の発音)
  2. ^ git - IT用語辞典e-words
  3. ^ git - IT用語辞典 - 日立ソリューションズ
  4. ^ 使い始める-Git略史」『Git Pro』 Git --distributed-is-the-new-centralized
  5. ^ a b c d e Scott Chacon. “4.1 Git サーバー - プロトコル”. 2013年1月19日閲覧。
  6. ^ git-clone(1) Manual Page”. 2013年1月19日閲覧。
  7. ^ Linus Torvalds (5 May 2006). "Re: [ANNOUNCE] Git wiki". linux-kernel (Mailing list). 2009年3月3日閲覧 gitの元となったプログラムに関する歴史的経緯
  8. ^ Linus Torvalds (7 April 2005). "Re: Kernel SCM saga". linux-kernel (Mailing list). 2009年3月3日閲覧
  9. ^ Linus Torvalds (8 April 2005). "Re: Kernel SCM saga". linux-kernel (Mailing list). 2008年2月20日閲覧
  10. ^ Linus Torvalds (23 March 2006). "Re: Errors GITtifying GCC and Binutils". git (Mailing list). 2009年3月3日閲覧
  11. ^ Linus Torvalds (19 October 2006). "Re: VCS comparison table". git (Mailing list). 2009年3月3日閲覧
  12. ^ Stenback, Johnny (2006-11-30), “bzr/hg/git performance”, Jst's Blog, http://weblogs.mozillazine.org/jst/archives/2006/11/vcs_performance.html 2008年2月20日閲覧。 , "git diff"と"bzr diff"のベンチマーク結果の比較。ケースによっては、gitの処理速度はBazzarの100倍以上になる。
  13. ^ Roland Dreier (2006年11月13日). “Oh what a relief it is”. 2009年3月3日閲覧。, "git log"は"svn log"と比較して100倍以上高速だが、これは後者はリモートのサーバにアクセスする必要があるためである。
  14. ^ Linus Torvalds (18 October 2006). "Re: VCS comparison table". git (Mailing list). 2009年3月3日閲覧, gitのスクリプト指向デザインについて
  15. ^ iabervon (2005年12月22日). “Git rocks!”. 2009年3月3日閲覧。, gitを使ったスクリプトの書きやすさに関する賞賛
  16. ^ Git User's Manual” (2007年8月5日). 2009年3月3日閲覧。
  17. ^ Linus Torvalds (10 April 2005). "Re: more git updates." linux-kernel (Mailing list). 2009年3月3日閲覧
  18. ^ Bruno Haible (11 February 2007). "how to speed up "git log"?". git (Mailing list). 2009年3月3日閲覧
  19. ^ Linus Torvalds (1 March 2006). "Re: impure renames / history tracking". git (Mailing list). 2009年3月3日閲覧
  20. ^ Junio C Hamano (24 March 2006). "Re: Errors GITtifying GCC and Binutils". git (Mailing list). 2009年3月3日閲覧
  21. ^ Junio C Hamano (23 March 2006). "Re: Errors GITtifying GCC and Binutils". git (Mailing list). 2009年3月3日閲覧
  22. ^ Linus Torvalds (28 November 2006). "Re: git and bzr". git (Mailing list). 2009年3月3日閲覧, git-blameコマンドを使用したソースファイル間のコードの移動の調査について
  23. ^ Linus Torvalds (2007年7月18日). “git-merge(1)”. 2009年3月4日閲覧。
  24. ^ Linus Torvalds (2007年7月18日). “CrissCrossMerge”. 2009年3月4日閲覧。
  25. ^ “After controversy, Torvalds begins work on git”. InfoWorld. (2005-04-19). ISSN 0199-6649. http://www.infoworld.com/article/05/04/19/HNtorvaldswork_1.html 2008年2月20日閲覧。. 
  26. ^ GitFaq: Why the 'git' name?
  27. ^ Jonathan Corbet (2005-04-20), “How Tridge reverse engineered BitKeeper”, Linux Weekly News, http://lwn.net/Articles/132938/ 2009年3月26日閲覧。 
  28. ^ Linus Torvalds (7 April 2005). "Re: Kernel SCM saga." linux-kernel (Mailing list). 2009年3月26日閲覧
  29. ^ a b ここでは -mm ツリーメンテナのアンドリュー・モートンを指す。
  30. ^ Linus Torvalds (31 October 2005). "Re: git versus CVS (versus bk)". git (Mailing list). 2009年3月26日閲覧
  31. ^ a b c d e f Linus Torvalds (05-03). Google tech talk: Linus Torvalds on git. 該当時間: 02:30. 2007-05-16閲覧 {{cite AV media}}: |date=|year=|date=の日付が不正です。 (説明)
  32. ^ Linus Torvalds (10 June 2007). "Re: fatal: serious inflate inconsistency". git (Mailing list). 2009年3月26日閲覧 gitにおけるデータの完全性に関する設計目標に関する概要説明。
  33. ^ a b Linus Torvalds (27 February 2007). "Re: Trivia: When did git self-host?". git (Mailing list). 2009年3月26日閲覧
  34. ^ Linus Torvalds (6 April 2005). "Kernel SCM saga." linux-kernel (Mailing list). 2009年3月26日閲覧
  35. ^ Linus Torvalds (17 April 2005). "First ever real kernel git merge!". git (Mailing list). 2009年3月26日閲覧
  36. ^ Matt Mackall (29 April 2005). "Mercurial 0.4b vs git patchbomb benchmark". git (Mailing list). 2009年3月26日閲覧
  37. ^ Linus Torvalds (17 June 2005). "Linux 2.6.12". git-commits-head (Mailing list). 2009年3月26日閲覧
  38. ^ Linus Torvalds (20 October 2006). "Re: VCS comparison table". git (Mailing list). 2009年3月26日閲覧 Git vs. BitKeeperの議論
  39. ^ Linus Torvalds (27 July 2005). "Meet the new maintainer..." git (Mailing list). 2009年3月26日閲覧
  40. ^ Junio C Hamano (21 December 2005). "ANNOUNCE: GIT 1.0.0". git (Mailing list). 2009年3月26日閲覧

関連文献

単行本

雑誌記事

関連項目

外部リンク