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

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

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

背景および概要

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

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

作業の流れ

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

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

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

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

以前はrsyncも使用できたが、2.8.0で廃止された[9]

設計

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

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

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

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

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

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

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

歴史

名前の由来

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

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

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

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

開発初期の歴史

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

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

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

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

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

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

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

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

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

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

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

ブランチモデル

ソフトウェア開発におけるGitブランチの作成・更新モデルをブランチモデルと呼ぶ。

GitHub flow

GitHub flowはブランチモデルの一種である[43]。GitHub flowの方針は「masterブランチは常にデプロイ可能」である[44]。コードの変更を行う際にはトピックを名称とするブランチをmasterからforkする。マージ時を含め他者からの意見募集・レビューを行う際にはpull request(merge request)を用いる。pull request時に自動化テスト(c.f. 継続的インテグレーション)をおこなうことでmergeの安全性を確保し、masterが常に正常 = デプロイ可能に保たれる。GitHub flowが有効な分野は継続的デリバリー継続的デプロイメントが有効な分野、例えばWebサービスが挙げられる。

2011年の提唱時と比較して、GitHub社ではモデルの一部を変更している。オリジナルのGitHub flowでは更新がmasterへマージされ、そこからデプロイされる。GitHub社ではレビュー後(CI後)のtopic branchが最終テストとしてプロダクション環境へデプロイされる。そこで問題がないと確認されたのちにmasterへmergeされている[45]。このモデル変更により、CIで判明しなかったバグが発生した場合にmasterのrevert commitではなくmasterの再デプロイで対応できる。

マージ

Gitはブランチのマージ(merge)に対応している。

マージが行われるとマージコミット(英: merge commit)が生成される。コンフリクトが発生しない場合、git mergeがマージコミットを自動生成する[46]。コンフリクトが発生した場合、まず安全な範囲がマージされインデックスとワーキングツリーが更新される[47]。自動マージできないコンフリクト部は、ワーキングツリーに特定の記法で両方の変更が併記された状態になる[48]。ユーザーによるコンフリクト修正後git addをおこない、git commitあるいはgit merge --continueをおこなってはじめてマージコミットが生成される[49]

マージコミットの実体は2つ以上のparent属性を持つただのコミットオブジェクトである(特別なGitオブジェクトではない)[50]。通常のコミットオブジェクトと同様に変更後ファイルセットがtreeに記録され、更新の元となっている(複数の)コミットがparentに設定されているだけである。

注釈

  1. ^ LKML.ORG - the Linux Kernel Mailing List Archive
  2. ^ a b ここでは -mm ツリーメンテナのアンドリュー・モートンを指す。

出典

  1. ^ 濱野 純; "[ANNOUNCE Git v2.45.2 and friends to unbreak "git lfs" and others"]; 出版日: 2024年5月31日; 閲覧日: 2024年5月31日.
  2. ^ Tech Talk: Linus Torvalds on git. 該当時間: 1分30秒. 2014年7月21日閲覧
  3. ^ Git - IT用語辞典e-words”. 2014年7月29日閲覧。
  4. ^ Scott Chacon「1.2 使い始める-Git略史」『Pro Git』https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E7%95%A5%E5%8F%B22021年3月7日閲覧 
  5. ^ a b c d e Scott Chacon. “4.1 Git サーバー - プロトコル”. 2013年1月19日閲覧。
  6. ^ Scott Chacon; Ben Straub. “Pro Git 2nd Edition 4.6 Gitサーバー - Smart HTTP”. 2021年8月26日閲覧。
  7. ^ Git - user-manual Documentation” (英語). 2021年8月26日閲覧。 “(See also setup-git-server-over-http for a slightly more sophisticated setup using WebDAV which also allows pushing over HTTP.)”
  8. ^ git-clone(1) Manual Page” (英語). 2017年6月14日閲覧。 “in addition, ftp, and ftps can be used for fetching, but this is inefficient and deprecated; do not use it”
  9. ^ Documentation/RelNotes/2.8.0.txt” (英語). 2017年6月14日閲覧。 “The rsync:// transport has been removed.”
  10. ^ Linus Torvalds (5 May 2006). "Re: [ANNOUNCE] Git wiki". linux-kernel (Mailing list). 2009年3月3日閲覧 Gitの元となったプログラムに関する歴史的経緯
  11. ^ Linus Torvalds (7 April 2005). "Re: Kernel SCM saga". linux-kernel (Mailing list). 2009年3月3日閲覧
  12. ^ Linus Torvalds (8 April 2005). "Re: Kernel SCM saga". linux-kernel (Mailing list). 2008年2月20日閲覧
  13. ^ Linus Torvalds (23 March 2006). "Re: Errors GITtifying GCC and Binutils". Git (Mailing list). 2009年3月3日閲覧
  14. ^ Linus Torvalds (19 October 2006). "Re: VCS comparison table". Git (Mailing list). 2009年3月3日閲覧
  15. ^ 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倍以上になる。
  16. ^ Roland Dreier (2006年11月13日). “Oh what a relief it is”. 2009年3月3日閲覧。, "git log"は"svn log"と比較して100倍以上高速だが、これは後者はリモートのサーバにアクセスする必要があるためである。
  17. ^ Linus Torvalds (18 October 2006). "Re: VCS comparison table". Git (Mailing list). 2009年3月3日閲覧, Gitのスクリプト指向デザインについて
  18. ^ iabervon (2005年12月22日). “Git rocks!”. 2009年3月3日閲覧。, Gitを使ったスクリプトの書きやすさに関する賞賛
  19. ^ Git User's Manual” (2007年8月5日). 2009年3月3日閲覧。
  20. ^ Linus Torvalds (10 April 2005). "Re: more git updates." linux-kernel (Mailing list). 2009年3月3日閲覧
  21. ^ Bruno Haible (11 February 2007). "how to speed up "git log"?". Git (Mailing list). 2009年3月3日閲覧
  22. ^ Linus Torvalds (1 March 2006). "Re: impure renames / history tracking". Git (Mailing list). 2009年3月3日閲覧
  23. ^ Junio C Hamano (24 March 2006). "Re: Errors GITtifying GCC and Binutils". Git (Mailing list). 2009年3月3日閲覧
  24. ^ Junio C Hamano (23 March 2006). "Re: Errors GITtifying GCC and Binutils". Git (Mailing list). 2009年3月3日閲覧
  25. ^ Linus Torvalds (28 November 2006). "Re: git and bzr". Git (Mailing list). 2009年3月3日閲覧, git-blameコマンドを使用したソースファイル間のコードの移動の調査について
  26. ^ Linus Torvalds (2007年7月18日). “git-merge(1)”. 2009年3月4日閲覧。
  27. ^ Linus Torvalds (2007年7月18日). “CrissCrossMerge”. 2009年3月4日閲覧。
  28. ^ “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日閲覧。. 
  29. ^ GitFaq: Why the 'git' name?”. 2007年3月21日閲覧。
  30. ^ Jonathan Corbet (2005-04-20), “How Tridge reverse engineered BitKeeper”, Linux Weekly News, http://lwn.net/Articles/132938/ 2009年3月26日閲覧。 
  31. ^ Linus Torvalds (7 April 2005). "Re: Kernel SCM saga." linux-kernel (Mailing list). 2009年3月26日閲覧
  32. ^ Linus Torvalds (31 October 2005). "Re: git versus CVS (versus bk)". Git (Mailing list). 2009年3月26日閲覧
  33. ^ a b c d e f Linus Torvalds (3 May 2007). Google tech talk: Linus Torvalds on git. 該当時間: 02:30. 2007年5月16日閲覧
  34. ^ Linus Torvalds (10 June 2007). "Re: fatal: serious inflate inconsistency". Git (Mailing list). 2009年3月26日閲覧 Gitにおけるデータの完全性に関する設計目標に関する概要説明。
  35. ^ a b Linus Torvalds (27 February 2007). "Re: Trivia: When did git self-host?". Git (Mailing list). 2009年3月26日閲覧
  36. ^ Linus Torvalds (6 April 2005). "Kernel SCM saga." linux-kernel (Mailing list). 2009年3月26日閲覧
  37. ^ Linus Torvalds (17 April 2005). "First ever real kernel git merge!". Git (Mailing list). 2009年3月26日閲覧
  38. ^ Matt Mackall (29 April 2005). "Mercurial 0.4b vs git patchbomb benchmark". Git (Mailing list). 2009年3月26日閲覧
  39. ^ Linus Torvalds (17 June 2005). "Linux 2.6.12". git-commits-head (Mailing list). 2009年3月26日閲覧
  40. ^ Linus Torvalds (20 October 2006). "Re: VCS comparison table". Git (Mailing list). 2009年3月26日閲覧 Git vs. BitKeeperの議論
  41. ^ Linus Torvalds (27 July 2005). "Meet the new maintainer..." Git (Mailing list). 2009年3月26日閲覧
  42. ^ 濱野純 (Junio C Hamano) (21 December 2005). "ANNOUNCE: GIT 1.0.0". Git (Mailing list). 2009年3月26日閲覧
  43. ^ a b Scott Chacon (2011年8月31日). “GitHub Flow”. 2020年5月31日閲覧。
  44. ^ "#1 - anything in the master branch is deployable.
    This is basically the only hard rule of the system."[43]
  45. ^ GitHub Guides”. 2020年5月31日閲覧。 “With GitHub, you can deploy from a branch for final testing in production before merging to master.”
  46. ^ "A merged version ... is committed, and your HEAD, index, and working tree are updated to it."[git 1]
  47. ^ "Paths that merged cleanly are updated both in the index file and in your working tree."[git 1]
  48. ^ "When both sides made changes to the same area, however, Git cannot randomly pick one side over the other, and asks you to resolve it by leaving what both sides did to that area."[git 1]
  49. ^ "Edit the files into shape and git add them to the index. Use git commit or git merge --continue to seal the deal."[git 1]
  50. ^ "the branches to be merged must be tied together by a merge commit that has both of them as its parents."[git 1]
  1. ^ a b c d e git-merge - git 2020-11-01閲覧

関連項目

外部リンク