[{"data":1,"prerenderedAt":815},["ShallowReactive",2],{"/ja-jp/blog/a-beginners-guide-to-the-git-reftable-format":3,"navigation-ja-jp":41,"banner-ja-jp":452,"footer-ja-jp":462,"blog-post-authors-ja-jp-Patrick Steinhardt":698,"blog-related-posts-ja-jp-a-beginners-guide-to-the-git-reftable-format":712,"next-steps-ja-jp":753,"blog-promotions-ja-jp":762},{"id":4,"title":5,"authorSlugs":6,"authors":8,"body":10,"category":11,"categorySlug":11,"config":12,"content":16,"date":20,"description":17,"extension":27,"externalUrl":28,"featured":14,"heroImage":19,"isFeatured":14,"meta":29,"navigation":14,"path":30,"publishedDate":20,"rawbody":31,"seo":32,"slug":13,"stem":37,"tagSlugs":38,"tags":39,"template":15,"updatedDate":26,"__hash__":40},"blogPosts/ja-jp/blog/a-beginners-guide-to-the-git-reftable-format.yml","初心者向けGit reftableフォーマットガイド",[7],"patrick-steinhardt",[9],"Patrick Steinhardt","最近まで、Gitでの参照の保存方法は、「files」フォーマットだけに限られていましたが、[Git 2.45.0の新機能](https://about.gitlab.com/ja-jp/blog/whats-new-in-git-2-45-0/)により、Gitでは参照を「reftable」フォーマットで保存できるようになりました。この新しいフォーマットは、バイナリフォーマットで非常に複雑ですが、その複雑さが「files」フォーマットのいくつかの欠点を解決します。「reftable」フォーマットは、次のような目的で設計されました。\n\n- 単一の参照の検索と参照範囲のイテレーションを、可能な限り効率的かつ迅速に行えるようにする。\n- 複数の参照が部分的にしか更新されていない中途半端な状態をGitが読み取らないように、一貫した参照の読み取りをサポートする。\n- 複数の参照の更新がオールオアナッシング型のオペレーションとして実行される、アトミック書き込みをサポートする。\n- 参照および参照ログの効率的な保存。\n\nこの記事では、「reftable」フォーマットの仕組みを詳しく見ていきます。\n\n## Gitでの参照の保存方法\n\n「reftable」フォーマットについて詳しく掘り下げる前に、まずはGitがこれまで参照をどのように保存してきたのかを簡単に振り返ってみましょう。すでにご存知の方は、このセクションを読み飛ばして構いません。\n\nGitリポジトリは、次の重要な2つのデータ構造を追跡します。\n\n- [オブジェクト](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects)：リポジトリの実際のデータ（コミット、ディレクトリツリー構造、ソースコードを含むblobなど）を格納しています。オブジェクトは互いに参照し合い、オブジェクトグラフを形成します。さらに、各オブジェクトにはオブジェクトIDがあり、そのオブジェクトを一意に識別します。\n\n- 参照：ブランチやタグなどがあります。これらはオブジェクトグラフへのポインタであり、オブジェクトに覚えやすい名前を付けたり、開発履歴の異なるトラックを追跡するのに使われます。たとえば、リポジトリには`main`ブランチが含まれている場合があり、これは特定のコミットを指し示す`refs/heads/main`という名前の参照です。\n\n参照は、参照データベースに保存されます。Git 2.45.0までは、「files」データベースフォーマットのみが存在していました。このフォーマットでは、各参照が通常のファイルとして保存され、そのファイルには次のいずれかが含まれます。\n\n- 通常の参照：指し示すコミットのオブジェクトIDが保存されています。\n- シンボリック参照：別の参照の名前が保存されています。これは、シンボリックリンクが別のファイルを指し示すのと似ています。\n\n定期的に、これらの参照は検索を効率化するために1つのpacked-refsファイルにまとめられます。\n\n次の例は、「files」フォーマットがどのように動作するかを示しています。\n\n```shell\n$ git init .\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) 6917c17] Initial commit\n\n# HEADはrefs/heads/mainを指すシンボリック参照です。\n$ cat .git/HEAD\nref: refs/heads/main\n\n# refs/heads/mainはコミットを指す通常の参照です。\n$ cat .git/refs/heads/main\n6917c178cfc3c50215a82cf959204e9934af24c8\n\n# git-pack-refs(1)はこれらの参照をpacked-refsファイルにパック化します。\n$ git pack-refs --all\n$ cat .git/packed-refs\n# pack-refs with: peeled fully-peeled sorted\n```\n\n## reftableフォーマットの構造概要\n\nGit 2.45.0以降がインストールされている場合、`--ref-format=reftable`スイッチを使用して「reftable」フォーマットでリポジトリを作成できます。\n\n```shell\n$ git init --ref-format=reftable .\nInitialized empty Git repository in /tmp/repo/.git/\n$ git rev-parse --show-ref-format\nreftable\n\n# わかりやすくするために不要なファイルを削除しています。\n$ tree .git\n.git\n├── config\n├── HEAD\n├── index\n├── objects\n├── refs\n│   └── heads\n└── reftable\n\t├── 0x000000000001-0x000000000002-40a482a9.ref\n\t└── tables.list\n\n4 directories, 6 files\n```\n\nまず、リポジトリの設定を見ると、それには`extension.refstorage`キーがあります。\n\n```shell\n$ cat .git/config\n[core]\n    repositoryformatversion = 1\n    filemode = true\n    bare = false\n    logallrefupdates = true\n[extensions]\n    refstorage = reftable\n```\n\nこの設定は、リポジトリが「reftable」フォーマットで初期化されており、「reftable」バックエンドを使用してアクセスするようGitに指示するものです。\n\n不思議なことに、このリポジトリにはまだ「files」バックエンドが使われているかのように見えるいくつかのファイルがあります。\n\n- `HEAD`は通常、現在チェックアウト済みのブランチを指すシンボリック参照です。「reftable」バックエンドでは使用されませんが、GitクライアントがディレクトリをGitリポジトリとして検出するために必要です。したがって、「reftable」フォーマットを使用する場合、`HEAD`は`ref: refs/heads/.invalid`という内容のスタブになります。\n\n- `refs/heads`は、`this repository uses the reftable format`という内容が書かれているファイルです。「reftable」フォーマットを認識できないGitクライアントは、このパスがディレクトリであると想定します。したがって、このパスをファイルとして作成することで、古いGitクライアントが「files」バックエンドでリポジトリにアクセスしようとすると、意図的に失敗するようになります。\n\n実際の参照は、次のように`reftable/`ディレクトリに保存されます。\n\n```shell\n$ tree .git/reftable\n.git/reftable/\n├── 0x000000000001-0x000000000001-794bd722.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000001-794bd722.ref\n```\n\nここには、次の2つのファイルがあります。\n\n- `0x000000000001-0x000000000001-794bd722.ref`は、参照と参照ログデータをバイナリフォーマットで含むテーブルです。\n\n- `tables.list`は、テーブルのリストです。リポジトリの現在の状態では、このファイルにはテーブルの名前の1行だけが含まれています。このファイルは「reftable」データベースにある現在有効なテーブルをまとめて追跡し、新しいテーブルがリポジトリに追加されるたびに更新されます。\n\n次のように、参照を更新すると、新しいテーブルが作成されます。\n\n```shell\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) 1472a58] Initial commit\n\n$ tree .git/reftable\n.git/reftable/\n├── 0x000000000001-0x000000000002-eb87d12b.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000002-eb87d12b.ref\n```\n\nご覧のとおり、以前のテーブルは新しいテーブルに置き換えられました。さらに、`tables.list`ファイルが更新され、新しいテーブルが取り込まれました。\n\n## テーブルの構造\n\n前述のとおり、参照データベースの実際のデータはテーブルに含まれています。テーブルは大まかに次のような複数のセクションに分かれています。\n\n- header：テーブルに関するメタデータが含まれています。これには、フォーマットのバージョン、ブロックサイズ、およびリポジトリで使用されるハッシュ関数（SHA1、SHA256など）が、他の情報と一緒に含まれています。\n- ref：参照が含まれています。これらのレコードは参照名と等しいキーを有し、通常の参照の場合はオブジェクトIDを、シンボリック参照の場合は他の参照を指します。\n- obj：オブジェクトIDからそれらのオブジェクトIDを指す参照への逆マッピングが含まれています。これにより、Gitは特定のオブジェクトIDを指す参照を効率的に検索できます。\n- log：参照ログエントリが含まれています。これらのレコードは、参照名にログエントリの番号を表すインデックスを付け足したものと等しいキーを有し、 さらに、古いオブジェクトIDと新しいオブジェクトID、およびその参照ログエントリのメッセージを含みます。\n- footer：各セクションへのオフセットが含まれます。\n\n![すべてのreftableセクションを含んだ縦長の表](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_1_-_Reftable_overview.svg)\n\n各セクションのタイプは、似たような構造を持っています。セクションには一連のレコードが含まれており、各レコードのキーでソートされています。たとえば、 `refs/heads/aaaaa`と `refs/heads/bbb`という2つの参照レコードがある場合、これらの参照名がそれぞれのキーとなり、`refs/heads/aaaaa`が`refs/heads/bbb`よりも前に来ます。\n\nさらに、各セクションは固定長のブロックに分割されています。このブロックの長さはヘッダー（header）にエンコードされており、次の2つの目的を果たします。\n\n- セクションの開始位置とブロックサイズに基づき、リーダー（reader）は各ブロックの開始位置を暗に認識します。これにより、Gitは先行するブロックを読み込むことなくセクションの途中に簡単に移動できるため、ブロック上でのバイナリ検索が可能になり、レコードの検索を高速化します。\n- 一度に読み込むディスクデータの量をリーダーが認識できるようにします。このために、ブロックサイズはデフォルトで4KiBに設定されており、これはハードディスクのセクターサイズとしては最も一般的です。最大ブロックサイズは16MBです。\n\nたとえば、「ref」セクションを覗いてみると、おおよそ次の図のようになります。ここで留意すべき点は、レコードがブロック内で、そしてブロック間の両方で辞書順に並んでいることです。\n\n![未圧縮参照ブロック](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_2_-_Ref_block_uncompressed.svg)\n\n現在の情報を基に、次の手順でレコードを検索できます。\n\n1. 各ブロックの最初のレコードのキーを確認してバイナリ検索を行い、目的のレコードが含まれているブロックを特定します。\n\n2. 特定したブロック内で線形検索を行い、目的のレコードを特定します。\n\nこの手順はまだ少し非効率です。多くのブロックがある場合、目的のブロックを特定するためにバイナリ検索で対数的に多くのブロックを読み込むことが必要になる場合があります。また、ブロックに多数のレコードが含まれている場合、線形検索中にすべてのレコードの読み込みが必要になる可能性もあります。\n\n「reftable」フォーマットには、これらのパフォーマンス問題に対処する追加のメカニズムが組み込まれています。後のセクションでこれらについて詳しく説明します。\n\n### プレフィックス圧縮\n\nお気づきかもしれませんが、すべてのレコードキーには`refs/`という共通のプレフィックスがあります。これはGitでは一般的です。\n\n- すべてのブランチは`refs/heads/`で始まります。\n- すべてのタグは`refs/tags /`で始まります。\n\nしたがって、後続のレコードもキーの大部分で共通のプレフィックスを持つことが予想されます。これを利用して、貴重なディスク容量を節約できます。ほとんどのキーが共通のプレフィックスを持つことがわかっているため、これを最適化するのは理にかなっています。\n\nこの最適化にはプレフィックス圧縮を使用します。各レコードは、前のレコードのキーから何バイトを再利用するかを示すプレフィックスの長さがエンコードされています。たとえば、`refs/heads/a`と`refs/heads/b`という2つのレコードがある場合、後者はプレフィックスの長さを11バイトとしてエンコードし、サフィックスとして`b`だけを保存します。その後、リーダーは`refs/heads/a`の最初の11バイト（`refs/heads/`）を取得し、サフィックス`b`を追加します。\n\n![プレフィックス圧縮](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_3_-_Ref_block_prefix_compression.svg)\n\n### 再起点\n\n前述のように、現在の「reftable」フォーマットの理解に基づいてブロック内の参照を検索する最適な方法は、線形検索です。これは、レコードが固定長ではないため、ブロックの先頭からスキャンしないとレコードの開始位置を特定できないためです。また、レコードが固定長であったとしても、レフィックス圧縮があるため、先行するレコードを読み込む必要があり、ブロックの途中に直接移動はできません。\nしかし、ブロックには数百から数千のレコードが含まれる可能性があり、線形検索は非常に非効率です。この問題に対処するために、「reftable」フォーマットは各ブロックに「再起点」と呼ばれるポイントをエンコードします。再起点は圧縮されていないレコードであり、ここではプレフィックス圧縮がリセットされます。したがって、再起点のレコードは常に完全なキーを含んでおり、先行するレコードをスキップしながら直接移動してレコードを読み込むことが可能になります。これらの再起点は各ブロックのフッターにリストされています。\n\nこの情報を用いることで、ブロック全体を線形検索する必要がなくなります。代わりに、再起点のバイナリ検索を行い、目的のキーより大きい最初の再起点を探します。そこから、目的のレコードが_前の_再起点から特定された再起点までのセクションに存在することがわかります。\n\nしたがって、レコードを検索する最初の手順（ブロックのバイナリ検索、レコードの線形検索）は次のようになります。\n\n1. ブロックのバイナリ検索を行い、目的のレコードが含まれるブロックを特定します。\n\n2. 再起点のバイナリ検索を行い、目的のレコードが含まれるブロックのサブセクションを特定します。\n\n3. 特定したサブセクション内でレコードの線形検索を行います。\n\n![レコードの線形検索](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_4_-_Restart_points.svg)\n\n### インデックス\n\nブロック内のレコードの検索はかなり効率化されましたが、ブロック自体の位置を特定するのはまだ効率的とはいえません。数個のブロックであればバイナリ検索でも十分に効率的です。しかし、数百万もの参照を含むリポジトリには数百から数千のブロックが存在します。この場合、追加のデータ構造がなければ、平均して対数的に多くのディスクアクセスが必要になります。\n\nこの問題を避けるために、各セクションの後にブロックを効率的に検索するためのインデックスセクションを追加できます。各インデックスレコードには次の情報が含まれます。\n\n- インデックス化されているブロックの位置。\n- インデックス化されているブロックの最後のレコードのキー。\n\n3つ以下のブロックであれば、バイナリ検索は最大2回のディスク読み取りで目的のブロックを特定できます。この読み取り回数は、インデックスを使用する場合も同じです。具体的には、インデックス自体を読み取るための1回と、目的のブロックを読む取るための1回です。したがって、インデックスは実際に読み取り回数を減らす場合、つまりインデックス化されたブロックが4つ以上ある場合にのみ作成されます。\n\n次の疑問は、インデックス自体が複数のブロックにまたがるほど大きくなった場合はどうすべきかという点です。その答えは、そのインデックスをインデックス化するために別のインデックスを作成するというものです。この複数階層のインデックスは、数十万もの参照があるリポジトリでのみ必要となります。\n\n次のインデックスを使用することで、レコードの検索手順をさらに効率化できます。\n1. テーブルのフッターを見てインデックスがあるかどうかを確認します。\n\t- インデックスがあれば、バイナリ検索を行い、目的のブロックを特定します。このブロックがインデックスブロック自体を指している場合は、目的のレコードタイプに到達するまでこの手順を繰り返します。\n\t- インデックスがなければ、先ほどのようにブロックのバイナリ検索を行います。\n2. 再起点のバイナリ検索を行い、目的のレコードが含まれているブロックのサブセクションを特定します。\n3. 特定したサブセクション内でレコードの線形検索を行います。\n\n## 複数のテーブル\n\nここまでは、単一のテーブルを読み取る方法について説明してきましたが、`tables.list`という名前が示すように、「reftable」データベースには複数のテーブルを格納できます。\n\nリポジトリ内の参照を更新するたびに、新しいテーブルが作成され、`tables.list`に追加されます。したがって、最終的には次のように複数のテーブルが存在することになります。\n\n```shell\n$ tree .git/reftable/\n.git/reftable/\n├── 0x000000000001-0x000000000007-8dcd8a77.ref\n├── 0x000000000008-0x000000000008-30e0f6f6.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000007-8dcd8a77.ref\n0x000000000008-0x000000000008-30e0f6f6.ref\n```\n\nリポジトリの実際の状態を読み取るためには、これらの複数のテーブルを単一の仮想テーブルにマージする必要があります。\n\nここで疑問が生じます。それは、参照が更新されるたびにテーブルが作成され、同じ参照が複数回更新される場合、「reftable」フォーマットは特定の参照の最新の値をどのように把握するのか、ということです。直感的には、最新のテーブルに含まれる参照の値が最新であると仮定できます。\n\n実際には、各レコードには「更新インデックス」と呼ばれるものがあり、これがレコードの「優先度」をエンコードしています。たとえば、同じ名前の2つの参照レコードが存在する場合、更新インデックスが高い方が低い方を上書きします。\n\nこれらの更新インデックスは、上のファイル構造で確認できます。長い16進文字列（例：`0x000000000001`）が更新インデックスであり、テーブル名の左側がテーブルに含まれる最小の更新インデックス、そして右側が最大の更新インデックスを示しています。\n\nテーブルのマージは、参照レコードのキーと更新インデックスによって順序付けられた[優先キュー](https://en.wikipedia.org/wiki/Priority_queue)を介して行われます。すべての参照レコードをスキャンする場合、次の手順で行います。\n\n1. 各テーブルの最初のレコードを優先キューに追加します。\n\n![優先キューに最初のレコードを追加する](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_5_-_Priority_queue_1.svg)\n\n2. 優先キューの先頭を取り出します。このキューは更新インデックス順に並んでいるため、先頭にあるレコードは最新のバージョンでなければなりません。そのテーブルの次の項目を優先キューに追加します。\n\n![優先キューの先頭を取り出す](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_6_-_Priority_queue_2.svg)\n\n3. 同じ名前を持つすべてのレコードをキューから削除します。これらのレコードは上書きされているため表示されません。レコードを削除した各テーブルについては、その次のレコードを優先キューに追加します。\n\n![同じ名前を持つすべてのレコードをキューから削除する](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_7_-_Priority_queue_3.svg)\n\nこれを繰り返して、他のキーのレコードを読み取ります。\n\nテーブルには、レコードが削除されたことを示す特殊な「トゥームストーン」レコードが含まれている場合があります。このように、すべてのテーブルを書き換えることなく、レコードを削除できます。\n\n### 自動圧縮\n\n優先キューの考え方はシンプルですが、このアプローチでは、マージするテーブルの数が数百個、あるいは数十個であっても、非常に非効率になります。参照を更新するたびに新しいテーブルが`tables.list`ファイルに付加されるのは事実ですが、他にも重要な特徴があります。\n\nそれが、自動圧縮です。新しいテーブルがテーブルリストに付加された後、「reftable」バックエンドは一部のテーブルをマージする必要があるかどうかを確認します。これは、シンプルなルールを使って行われます。具体的には、テーブルのリストがファイルサイズの[幾何数列](https://en.wikipedia.org/wiki/Geometric_progression)を形成しているかどうかをチェックします。すべてのテーブル`n`は、その次に新しいテーブル`n+1`の2倍以上のサイズでなければなりません。この幾何数列が維持されなかった場合、バックエンドはテーブルを圧縮して幾何数列を復元します。\n\n時間が経つにつれて、次のような構造になります。\n\n```shell\n$ du --apparent-size .git/reftable/*\n429    .git/reftable/0x000000000001-0x00000000bd7c-d9819000.ref\n101    .git/reftable/0x00000000bd7d-0x00000000c5ac-c34b88a4.ref\n32    .git/reftable/0x00000000c5ad-0x00000000cc6c-60391f53.ref\n8    .git/reftable/0x00000000cc6d-0x00000000cdc1-61c30db1.ref\n3    .git/reftable/0x00000000cdc2-0x00000000ce67-d9b55a96.ref\n1    .git/reftable/0x00000000ce68-0x00000000ce6b-44721696.ref\n1    .git/reftable/tables.list\n```\n\nすべてのテーブルにおいて、`size(n) > size(n+1) * 2`という性質が維持されていることに注目してください。\n\n自動圧縮がもたらすメリットのひとつは、「reftable」バックエンドのメンテナンスが自動化されることです。これにより、リポジトリで`git pack-refs`を実行する必要がなくなります。\n\n## さらに詳しく知りたい方へ\n\nこの記事では、新しい「reftable」フォーマットの仕組みについて解説しました。さらに詳しく知りたい場合は、Gitプロジェクトで提供される[テクニカルドキュメント](https://git-scm.com/docs/reftable)をご参照ください。\n\n> [Git 2.45.0の新機能](https://about.gitlab.com/ja-jp/blog/whats-new-in-git-2-45-0/)では、このバージョンにおけるその他の変更点をご確認いただけます。\n\n*監修：川瀬 洋平 [@ykawase](https://gitlab.com/ykawase)\u003Cbr>\n（GitLab合同会社 カスタマーサクセス本部 シニアカスタマーサクセスマネージャー）*\n","open-source",{"slug":13,"featured":14,"template":15},"a-beginners-guide-to-the-git-reftable-format",true,"BlogPost",{"title":5,"description":17,"authors":18,"heroImage":19,"date":20,"body":10,"category":11,"tags":21,"updatedDate":26},"Git 2.45.0では、GitLabがreftableバックエンドをGitに取り込んだことで、参照の保存方法が完全に変更されました。この新しいフォーマットの内部の仕組みを詳しく見てみましょう。",[9],"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664595/Blog/Hero%20Images/blog-image-template-1800x945__9_.png","2024-05-30",[22,23,24,25],"git","tutorial","open source","performance","2025-02-04","yml",null,{},"/ja-jp/blog/a-beginners-guide-to-the-git-reftable-format","seo:\n  title: 初心者向けGit reftableフォーマットガイド\n  description: >-\n    Git\n    2.45.0では、GitLabがreftableバックエンドをGitに取り込んだことで、参照の保存方法が完全に変更されました。この新しいフォーマットの内部の仕組みを詳しく見てみましょう。\n  ogTitle: 初心者向けGit reftableフォーマットガイド\n  ogDescription: >-\n    Git\n    2.45.0では、GitLabがreftableバックエンドをGitに取り込んだことで、参照の保存方法が完全に変更されました。この新しいフォーマットの内部の仕組みを詳しく見てみましょう。\n  noIndex: false\n  ogImage: >-\n    https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664595/Blog/Hero%20Images/blog-image-template-1800x945__9_.png\n  ogUrl: https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format\n  ogSiteName: https://about.gitlab.com\n  ogType: article\n  canonicalUrls: https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format\ncontent:\n  title: 初心者向けGit reftableフォーマットガイド\n  description: >-\n    Git\n    2.45.0では、GitLabがreftableバックエンドをGitに取り込んだことで、参照の保存方法が完全に変更されました。この新しいフォーマットの内部の仕組みを詳しく見てみましょう。\n  authors:\n    - Patrick Steinhardt\n  heroImage: >-\n    https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664595/Blog/Hero%20Images/blog-image-template-1800x945__9_.png\n  date: '2024-05-30'\n  body: \"最近まで、Gitでの参照の保存方法は、「files」フォーマットだけに限られていましたが、[Git\n    2.45.0の新機能](https://about.gitlab.com/ja-jp/blog/whats-new-in-git-2-45-0/)によ\\\n    り、Gitでは参照を「reftable」フォーマットで保存できるようになりました。この新しいフォーマットは、バイナリフォーマットで非常に複雑ですが、そ\\\n    の複雑さが「files」フォーマットのいくつかの欠点を解決します。「reftable」フォーマットは、次のような目的で設計されました。\n\n\n    - 単一の参照の検索と参照範囲のイテレーションを、可能な限り効率的かつ迅速に行えるようにする。\n\n    - 複数の参照が部分的にしか更新されていない中途半端な状態をGitが読み取らないように、一貫した参照の読み取りをサポートする。\n\n    - 複数の参照の更新がオールオアナッシング型のオペレーションとして実行される、アトミック書き込みをサポートする。\n\n    - 参照および参照ログの効率的な保存。\n\n\n    この記事では、「reftable」フォーマットの仕組みを詳しく見ていきます。\n\n\n    ## Gitでの参照の保存方法\n\n\n    「reftable」フォーマットについて詳しく掘り下げる前に、まずはGitがこれまで参照をどのように保存してきたのかを簡単に振り返ってみましょう。すで\\\n    にご存知の方は、このセクションを読み飛ばして構いません。\n\n\n    Gitリポジトリは、次の重要な2つのデータ構造を追跡します。\n\n\n    -\n    [オブジェクト](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects)：リポジトリの実際\\\n    のデータ（コミット、ディレクトリツリー構造、ソースコードを含むblobなど）を格納しています。オブジェクトは互いに参照し合い、オブジェクトグラフを形成\\\n    します。さらに、各オブジェクトにはオブジェクトIDがあり、そのオブジェクトを一意に識別します。\n\n\n    -\n    参照：ブランチやタグなどがあります。これらはオブジェクトグラフへのポインタであり、オブジェクトに覚えやすい名前を付けたり、開発履歴の異なるトラックを追\\\n    跡するのに使われます。たとえば、リポジトリには`main`ブランチが含まれている場合があり、これは特定のコミットを指し示す`refs/heads/ma\\\n    in`という名前の参照です。\n\n\n    参照は、参照データベースに保存されます。Git\n    2.45.0までは、「files」データベースフォーマットのみが存在していました。このフォーマットでは、各参照が通常のファイルとして保存され、そのファ\\\n    イルには次のいずれかが含まれます。\n\n\n    - 通常の参照：指し示すコミットのオブジェクトIDが保存されています。\n\n    - シンボリック参照：別の参照の名前が保存されています。これは、シンボリックリンクが別のファイルを指し示すのと似ています。\n\n\n    定期的に、これらの参照は検索を効率化するために1つのpacked-refsファイルにまとめられます。\n\n\n    次の例は、「files」フォーマットがどのように動作するかを示しています。\n\n\n    ```shell\n\n    $ git init .\n\n    $ git commit --allow-empty --message \\\"Initial commit\\\"\n\n    [main (root-commit) 6917c17] Initial commit\n\n\n    # HEADはrefs/heads/mainを指すシンボリック参照です。\n\n    $ cat .git/HEAD\n\n    ref: refs/heads/main\n\n\n    # refs/heads/mainはコミットを指す通常の参照です。\n\n    $ cat .git/refs/heads/main\n\n    6917c178cfc3c50215a82cf959204e9934af24c8\n\n\n    # git-pack-refs(1)はこれらの参照をpacked-refsファイルにパック化します。\n\n    $ git pack-refs --all\n\n    $ cat .git/packed-refs\n\n    # pack-refs with: peeled fully-peeled sorted\n\n    ```\n\n\n    ## reftableフォーマットの構造概要\n\n\n    Git\n    2.45.0以降がインストールされている場合、`--ref-format=reftable`スイッチを使用して「reftable」フォーマットでリポジ\\\n    トリを作成できます。\n\n\n    ```shell\n\n    $ git init --ref-format=reftable .\n\n    Initialized empty Git repository in /tmp/repo/.git/\n\n    $ git rev-parse --show-ref-format\n\n    reftable\n\n\n    # わかりやすくするために不要なファイルを削除しています。\n\n    $ tree .git\n\n    .git\n\n    ├── config\n\n    ├── HEAD\n\n    ├── index\n\n    ├── objects\n\n    ├── refs\n\n    │   └── heads\n\n    └── reftable\n\n    \\t├── 0x000000000001-0x000000000002-40a482a9.ref\n\n    \\t└── tables.list\n\n\n    4 directories, 6 files\n\n    ```\n\n\n    まず、リポジトリの設定を見ると、それには`extension.refstorage`キーがあります。\n\n\n    ```shell\n\n    $ cat .git/config\n\n    [core]\n\n    \\    repositoryformatversion = 1\n\n    \\    filemode = true\n\n    \\    bare = false\n\n    \\    logallrefupdates = true\n\n    [extensions]\n\n    \\    refstorage = reftable\n\n    ```\n\n\n    この設定は、リポジトリが「reftable」フォーマットで初期化されており、「reftable」バックエンドを使用してアクセスするようGitに指示する\\\n    ものです。\n\n\n    不思議なことに、このリポジトリにはまだ「files」バックエンドが使われているかのように見えるいくつかのファイルがあります。\n\n\n    -\n    `HEAD`は通常、現在チェックアウト済みのブランチを指すシンボリック参照です。「reftable」バックエンドでは使用されませんが、Gitクライアン\\\n    トがディレクトリをGitリポジトリとして検出するために必要です。したがって、「reftable」フォーマットを使用する場合、`HEAD`は`ref:\n    refs/heads/.invalid`という内容のスタブになります。\n\n\n    - `refs/heads`は、`this repository uses the reftable\n    format`という内容が書かれているファイルです。「reftable」フォーマットを認識できないGitクライアントは、このパスがディレクトリであると\\\n    想定します。したがって、このパスをファイルとして作成することで、古いGitクライアントが「files」バックエンドでリポジトリにアクセスしようとすると\\\n    、意図的に失敗するようになります。\n\n\n    実際の参照は、次のように`reftable/`ディレクトリに保存されます。\n\n\n    ```shell\n\n    $ tree .git/reftable\n\n    .git/reftable/\n\n    ├── 0x000000000001-0x000000000001-794bd722.ref\n\n    └── tables.list\n\n\n    $ cat .git/reftable/tables.list\n\n    0x000000000001-0x000000000001-794bd722.ref\n\n    ```\n\n\n    ここには、次の2つのファイルがあります。\n\n\n    -\n    `0x000000000001-0x000000000001-794bd722.ref`は、参照と参照ログデータをバイナリフォーマットで含むテーブルで\\\n    す。\n\n\n    -\n    `tables.list`は、テーブルのリストです。リポジトリの現在の状態では、このファイルにはテーブルの名前の1行だけが含まれています。このファイル\\\n    は「reftable」データベースにある現在有効なテーブルをまとめて追跡し、新しいテーブルがリポジトリに追加されるたびに更新されます。\n\n\n    次のように、参照を更新すると、新しいテーブルが作成されます。\n\n\n    ```shell\n\n    $ git commit --allow-empty --message \\\"Initial commit\\\"\n\n    [main (root-commit) 1472a58] Initial commit\n\n\n    $ tree .git/reftable\n\n    .git/reftable/\n\n    ├── 0x000000000001-0x000000000002-eb87d12b.ref\n\n    └── tables.list\n\n\n    $ cat .git/reftable/tables.list\n\n    0x000000000001-0x000000000002-eb87d12b.ref\n\n    ```\n\n\n    ご覧のとおり、以前のテーブルは新しいテーブルに置き換えられました。さらに、`tables.list`ファイルが更新され、新しいテーブルが取り込まれまし\\\n    た。\n\n\n    ## テーブルの構造\n\n\n    前述のとおり、参照データベースの実際のデータはテーブルに含まれています。テーブルは大まかに次のような複数のセクションに分かれています。\n\n\n    -\n    header：テーブルに関するメタデータが含まれています。これには、フォーマットのバージョン、ブロックサイズ、およびリポジトリで使用されるハッシュ関数\\\n    （SHA1、SHA256など）が、他の情報と一緒に含まれています。\n\n    -\n    ref：参照が含まれています。これらのレコードは参照名と等しいキーを有し、通常の参照の場合はオブジェクトIDを、シンボリック参照の場合は他の参照を指し\\\n    ます。\n\n    -\n    obj：オブジェクトIDからそれらのオブジェクトIDを指す参照への逆マッピングが含まれています。これにより、Gitは特定のオブジェクトIDを指す参照を\\\n    効率的に検索できます。\n\n    - log：参照ログエントリが含まれています。これらのレコードは、参照名にログエントリの番号を表すインデックスを付け足したものと等しいキーを有し、\n    さらに、古いオブジェクトIDと新しいオブジェクトID、およびその参照ログエントリのメッセージを含みます。\n\n    - footer：各セクションへのオフセットが含まれます。\n\n\n    ![すべてのreftableセクションを含んだ縦長の表](https://res.cloudinary.com/about-gitlab-com/im\\\n    age/upload/v1749675179/Blog/Content%20Images/Frame_1_-_Reftable_overview.sv\\\n    g)\n\n\n    各セクションのタイプは、似たような構造を持っています。セクションには一連のレコードが含まれており、各レコードのキーでソートされています。たとえば、\n    `refs/heads/aaaaa`と\n    `refs/heads/bbb`という2つの参照レコードがある場合、これらの参照名がそれぞれのキーとなり、`refs/heads/aaaaa`が`re\\\n    fs/heads/bbb`よりも前に来ます。\n\n\n    さらに、各セクションは固定長のブロックに分割されています。このブロックの長さはヘッダー（header）にエンコードされており、次の2つの目的を果たしま\\\n    す。\n\n\n    -\n    セクションの開始位置とブロックサイズに基づき、リーダー（reader）は各ブロックの開始位置を暗に認識します。これにより、Gitは先行するブロックを読\\\n    み込むことなくセクションの途中に簡単に移動できるため、ブロック上でのバイナリ検索が可能になり、レコードの検索を高速化します。\n\n    -\n    一度に読み込むディスクデータの量をリーダーが認識できるようにします。このために、ブロックサイズはデフォルトで4KiBに設定されており、これはハードディ\\\n    スクのセクターサイズとしては最も一般的です。最大ブロックサイズは16MBです。\n\n\n    たとえば、「ref」セクションを覗いてみると、おおよそ次の図のようになります。ここで留意すべき点は、レコードがブロック内で、そしてブロック間の両方で辞\\\n    書順に並んでいることです。\n\n\n    ![未圧縮参照ブロック](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749\\\n    675179/Blog/Content%20Images/Frame_2_-_Ref_block_uncompressed.svg)\n\n\n    現在の情報を基に、次の手順でレコードを検索できます。\n\n\n    1. 各ブロックの最初のレコードのキーを確認してバイナリ検索を行い、目的のレコードが含まれているブロックを特定します。\n\n\n    2. 特定したブロック内で線形検索を行い、目的のレコードを特定します。\n\n\n    この手順はまだ少し非効率です。多くのブロックがある場合、目的のブロックを特定するためにバイナリ検索で対数的に多くのブロックを読み込むことが必要になる場\\\n    合があります。また、ブロックに多数のレコードが含まれている場合、線形検索中にすべてのレコードの読み込みが必要になる可能性もあります。\n\n\n    「reftable」フォーマットには、これらのパフォーマンス問題に対処する追加のメカニズムが組み込まれています。後のセクションでこれらについて詳しく説\\\n    明します。\n\n\n    ### プレフィックス圧縮\n\n\n    お気づきかもしれませんが、すべてのレコードキーには`refs/`という共通のプレフィックスがあります。これはGitでは一般的です。\n\n\n    - すべてのブランチは`refs/heads/`で始まります。\n\n    - すべてのタグは`refs/tags /`で始まります。\n\n\n    したがって、後続のレコードもキーの大部分で共通のプレフィックスを持つことが予想されます。これを利用して、貴重なディスク容量を節約できます。ほとんどのキ\\\n    ーが共通のプレフィックスを持つことがわかっているため、これを最適化するのは理にかなっています。\n\n\n    この最適化にはプレフィックス圧縮を使用します。各レコードは、前のレコードのキーから何バイトを再利用するかを示すプレフィックスの長さがエンコードされてい\\\n    ます。たとえば、`refs/heads/a`と`refs/heads/b`という2つのレコードがある場合、後者はプレフィックスの長さを11バイトとして\\\n    エンコードし、サフィックスとして`b`だけを保存します。その後、リーダーは`refs/heads/a`の最初の11バイト（`refs/heads/`）\\\n    を取得し、サフィックス`b`を追加します。\n\n\n    ![プレフィックス圧縮](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749\\\n    675179/Blog/Content%20Images/Frame_3_-_Ref_block_prefix_compression.svg)\n\n\n    ### 再起点\n\n\n    前述のように、現在の「reftable」フォーマットの理解に基づいてブロック内の参照を検索する最適な方法は、線形検索です。これは、レコードが固定長では\\\n    ないため、ブロックの先頭からスキャンしないとレコードの開始位置を特定できないためです。また、レコードが固定長であったとしても、レフィックス圧縮があるた\\\n    め、先行するレコードを読み込む必要があり、ブロックの途中に直接移動はできません。\\\n\n\n    しかし、ブロックには数百から数千のレコードが含まれる可能性があり、線形検索は非常に非効率です。この問題に対処するために、「reftable」フォーマッ\\\n    トは各ブロックに「再起点」と呼ばれるポイントをエンコードします。再起点は圧縮されていないレコードであり、ここではプレフィックス圧縮がリセットされます。\\\n    したがって、再起点のレコードは常に完全なキーを含んでおり、先行するレコードをスキップしながら直接移動してレコードを読み込むことが可能になります。これら\\\n    の再起点は各ブロックのフッターにリストされています。\n\n\n    この情報を用いることで、ブロック全体を線形検索する必要がなくなります。代わりに、再起点のバイナリ検索を行い、目的のキーより大きい最初の再起点を探します\\\n    。そこから、目的のレコードが_前の_再起点から特定された再起点までのセクションに存在することがわかります。\n\n\n    したがって、レコードを検索する最初の手順（ブロックのバイナリ検索、レコードの線形検索）は次のようになります。\n\n\n    1. ブロックのバイナリ検索を行い、目的のレコードが含まれるブロックを特定します。\n\n\n    2. 再起点のバイナリ検索を行い、目的のレコードが含まれるブロックのサブセクションを特定します。\n\n\n    3. 特定したサブセクション内でレコードの線形検索を行います。\n\n\n    ![レコードの線形検索](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749\\\n    675179/Blog/Content%20Images/Frame_4_-_Restart_points.svg)\n\n\n    ### インデックス\n\n\n    ブロック内のレコードの検索はかなり効率化されましたが、ブロック自体の位置を特定するのはまだ効率的とはいえません。数個のブロックであればバイナリ検索でも\\\n    十分に効率的です。しかし、数百万もの参照を含むリポジトリには数百から数千のブロックが存在します。この場合、追加のデータ構造がなければ、平均して対数的に\\\n    多くのディスクアクセスが必要になります。\n\n\n    この問題を避けるために、各セクションの後にブロックを効率的に検索するためのインデックスセクションを追加できます。各インデックスレコードには次の情報が含\\\n    まれます。\n\n\n    - インデックス化されているブロックの位置。\n\n    - インデックス化されているブロックの最後のレコードのキー。\n\n\n    3つ以下のブロックであれば、バイナリ検索は最大2回のディスク読み取りで目的のブロックを特定できます。この読み取り回数は、インデックスを使用する場合も同\\\n    じです。具体的には、インデックス自体を読み取るための1回と、目的のブロックを読む取るための1回です。したがって、インデックスは実際に読み取り回数を減ら\\\n    す場合、つまりインデックス化されたブロックが4つ以上ある場合にのみ作成されます。\n\n\n    次の疑問は、インデックス自体が複数のブロックにまたがるほど大きくなった場合はどうすべきかという点です。その答えは、そのインデックスをインデックス化する\\\n    ために別のインデックスを作成するというものです。この複数階層のインデックスは、数十万もの参照があるリポジトリでのみ必要となります。\n\n\n    次のインデックスを使用することで、レコードの検索手順をさらに効率化できます。\n\n    1. テーブルのフッターを見てインデックスがあるかどうかを確認します。\n\n    \\t-\n    インデックスがあれば、バイナリ検索を行い、目的のブロックを特定します。このブロックがインデックスブロック自体を指している場合は、目的のレコードタイプに\\\n    到達するまでこの手順を繰り返します。\n\n    \\t- インデックスがなければ、先ほどのようにブロックのバイナリ検索を行います。\n\n    2. 再起点のバイナリ検索を行い、目的のレコードが含まれているブロックのサブセクションを特定します。\n\n    3. 特定したサブセクション内でレコードの線形検索を行います。\n\n\n    ## 複数のテーブル\n\n\n    ここまでは、単一のテーブルを読み取る方法について説明してきましたが、`tables.list`という名前が示すように、「reftable」データベース\\\n    には複数のテーブルを格納できます。\n\n\n    リポジトリ内の参照を更新するたびに、新しいテーブルが作成され、`tables.list`に追加されます。したがって、最終的には次のように複数のテーブル\\\n    が存在することになります。\n\n\n    ```shell\n\n    $ tree .git/reftable/\n\n    .git/reftable/\n\n    ├── 0x000000000001-0x000000000007-8dcd8a77.ref\n\n    ├── 0x000000000008-0x000000000008-30e0f6f6.ref\n\n    └── tables.list\n\n\n    $ cat .git/reftable/tables.list\n\n    0x000000000001-0x000000000007-8dcd8a77.ref\n\n    0x000000000008-0x000000000008-30e0f6f6.ref\n\n    ```\n\n\n    リポジトリの実際の状態を読み取るためには、これらの複数のテーブルを単一の仮想テーブルにマージする必要があります。\n\n\n    ここで疑問が生じます。それは、参照が更新されるたびにテーブルが作成され、同じ参照が複数回更新される場合、「reftable」フォーマットは特定の参照の\\\n    最新の値をどのように把握するのか、ということです。直感的には、最新のテーブルに含まれる参照の値が最新であると仮定できます。\n\n\n    実際には、各レコードには「更新インデックス」と呼ばれるものがあり、これがレコードの「優先度」をエンコードしています。たとえば、同じ名前の2つの参照レコ\\\n    ードが存在する場合、更新インデックスが高い方が低い方を上書きします。\n\n\n    これらの更新インデックスは、上のファイル構造で確認できます。長い16進文字列（例：`0x000000000001`）が更新インデックスであり、テーブル\\\n    名の左側がテーブルに含まれる最小の更新インデックス、そして右側が最大の更新インデックスを示しています。\n\n\n    テーブルのマージは、参照レコードのキーと更新インデックスによって順序付けられた[優先キュー](https://en.wikipedia.org/wik\\\n    i/Priority_queue)を介して行われます。すべての参照レコードをスキャンする場合、次の手順で行います。\n\n\n    1. 各テーブルの最初のレコードを優先キューに追加します。\n\n\n    ![優先キューに最初のレコードを追加する](https://res.cloudinary.com/about-gitlab-com/image/upl\\\n    oad/v1749675179/Blog/Content%20Images/Frame_5_-_Priority_queue_1.svg)\n\n\n    2.\n    優先キューの先頭を取り出します。このキューは更新インデックス順に並んでいるため、先頭にあるレコードは最新のバージョンでなければなりません。そのテーブル\\\n    の次の項目を優先キューに追加します。\n\n\n    ![優先キューの先頭を取り出す](https://res.cloudinary.com/about-gitlab-com/image/upload/v\\\n    1749675179/Blog/Content%20Images/Frame_6_-_Priority_queue_2.svg)\n\n\n    3.\n    同じ名前を持つすべてのレコードをキューから削除します。これらのレコードは上書きされているため表示されません。レコードを削除した各テーブルについては、そ\\\n    の次のレコードを優先キューに追加します。\n\n\n    ![同じ名前を持つすべてのレコードをキューから削除する](https://res.cloudinary.com/about-gitlab-com/im\\\n    age/upload/v1749675179/Blog/Content%20Images/Frame_7_-_Priority_queue_3.svg)\n\n\n    これを繰り返して、他のキーのレコードを読み取ります。\n\n\n    テーブルには、レコードが削除されたことを示す特殊な「トゥームストーン」レコードが含まれている場合があります。このように、すべてのテーブルを書き換えるこ\\\n    となく、レコードを削除できます。\n\n\n    ### 自動圧縮\n\n\n    優先キューの考え方はシンプルですが、このアプローチでは、マージするテーブルの数が数百個、あるいは数十個であっても、非常に非効率になります。参照を更新す\\\n    るたびに新しいテーブルが`tables.list`ファイルに付加されるのは事実ですが、他にも重要な特徴があります。\n\n\n    それが、自動圧縮です。新しいテーブルがテーブルリストに付加された後、「reftable」バックエンドは一部のテーブルをマージする必要があるかどうかを確\\\n    認します。これは、シンプルなルールを使って行われます。具体的には、テーブルのリストがファイルサイズの[幾何数列](https://en.wikiped\\\n    ia.org/wiki/Geometric_progression)を形成しているかどうかをチェックします。すべてのテーブル`n`は、その次に新しいテ\\\n    ーブル`n+1`の2倍以上のサイズでなければなりません。この幾何数列が維持されなかった場合、バックエンドはテーブルを圧縮して幾何数列を復元します。\n\n\n    時間が経つにつれて、次のような構造になります。\n\n\n    ```shell\n\n    $ du --apparent-size .git/reftable/*\n\n    429    .git/reftable/0x000000000001-0x00000000bd7c-d9819000.ref\n\n    101    .git/reftable/0x00000000bd7d-0x00000000c5ac-c34b88a4.ref\n\n    32    .git/reftable/0x00000000c5ad-0x00000000cc6c-60391f53.ref\n\n    8    .git/reftable/0x00000000cc6d-0x00000000cdc1-61c30db1.ref\n\n    3    .git/reftable/0x00000000cdc2-0x00000000ce67-d9b55a96.ref\n\n    1    .git/reftable/0x00000000ce68-0x00000000ce6b-44721696.ref\n\n    1    .git/reftable/tables.list\n\n    ```\n\n\n    すべてのテーブルにおいて、`size(n) > size(n+1) * 2`という性質が維持されていることに注目してください。\n\n\n    自動圧縮がもたらすメリットのひとつは、「reftable」バックエンドのメンテナンスが自動化されることです。これにより、リポジトリで`git\n    pack-refs`を実行する必要がなくなります。\n\n\n    ## さらに詳しく知りたい方へ\n\n\n    この記事では、新しい「reftable」フォーマットの仕組みについて解説しました。さらに詳しく知りたい場合は、Gitプロジェクトで提供される[テクニカ\\\n    ルドキュメント](https://git-scm.com/docs/reftable)をご参照ください。\n\n\n    > [Git\n    2.45.0の新機能](https://about.gitlab.com/ja-jp/blog/whats-new-in-git-2-45-0/)では\\\n    、このバージョンにおけるその他の変更点をご確認いただけます。\n\n\n    *監修：川瀬 洋平 [@ykawase](https://gitlab.com/ykawase)\u003Cbr>\n\n    （GitLab合同会社 カスタマーサクセス本部 シニアカスタマーサクセスマネージャー）*\\n\"\n  category: open-source\n  tags:\n    - git\n    - tutorial\n    - open source\n    - performance\n  updatedDate: '2025-02-04'\nconfig:\n  slug: a-beginners-guide-to-the-git-reftable-format\n  featured: true\n  template: BlogPost\n",{"title":5,"description":17,"ogTitle":5,"ogDescription":17,"noIndex":33,"ogImage":19,"ogUrl":34,"ogSiteName":35,"ogType":36,"canonicalUrls":34},false,"https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format","https://about.gitlab.com","article","ja-jp/blog/a-beginners-guide-to-the-git-reftable-format",[22,23,11,25],[22,23,24,25],"ev1qjMYycYHB3M0y7eS8IilMM73yFzplwAIkd8C07ok",{"data":42},{"logo":43,"freeTrial":48,"sales":53,"login":58,"items":63,"search":372,"minimal":405,"duo":422,"switchNav":431,"pricingDeployment":442},{"config":44},{"href":45,"dataGaName":46,"dataGaLocation":47},"/ja-jp/","gitlab logo","header",{"text":49,"config":50},"無料トライアルを開始",{"href":51,"dataGaName":52,"dataGaLocation":47},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp&glm_content=default-saas-trial/","free trial",{"text":54,"config":55},"お問い合わせ",{"href":56,"dataGaName":57,"dataGaLocation":47},"/ja-jp/sales/","sales",{"text":59,"config":60},"サインイン",{"href":61,"dataGaName":62,"dataGaLocation":47},"https://gitlab.com/users/sign_in/","sign in",[64,91,188,193,294,354],{"text":65,"config":66,"cards":68},"プラットフォーム",{"dataNavLevelOne":67},"platform",[69,75,83],{"title":65,"description":70,"link":71},"DevSecOpsに特化したインテリジェントオーケストレーションプラットフォーム",{"text":72,"config":73},"プラットフォームを探索",{"href":74,"dataGaName":67,"dataGaLocation":47},"/ja-jp/platform/",{"title":76,"description":77,"link":78},"GitLab Duo Agent Platform","ソフトウェアライフサイクル全体を支えるエージェント型AI",{"text":79,"config":80},"GitLab Duoのご紹介",{"href":81,"dataGaName":82,"dataGaLocation":47},"/ja-jp/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":84,"description":85,"link":86},"GitLabが選ばれる理由","エンタープライズがGitLabを選ぶ主な理由をご覧ください",{"text":87,"config":88},"詳細はこちら",{"href":89,"dataGaName":90,"dataGaLocation":47},"/ja-jp/why-gitlab/","why gitlab",{"text":92,"left":14,"config":93,"link":95,"lists":99,"footer":170},"製品",{"dataNavLevelOne":94},"solutions",{"text":96,"config":97},"すべてのソリューションを表示",{"href":98,"dataGaName":94,"dataGaLocation":47},"/ja-jp/solutions/",[100,125,148],{"title":101,"description":102,"link":103,"items":108},"自動化","CI/CDと自動化でデプロイを加速",{"config":104},{"icon":105,"href":106,"dataGaName":107,"dataGaLocation":47},"AutomatedCodeAlt","/ja-jp/solutions/delivery-automation/","automated software delivery",[109,113,116,121],{"text":110,"config":111},"CI/CD",{"href":112,"dataGaLocation":47,"dataGaName":110},"/ja-jp/solutions/continuous-integration/",{"text":76,"config":114},{"href":81,"dataGaLocation":47,"dataGaName":115},"gitlab duo agent platform - product menu",{"text":117,"config":118},"ソースコード管理",{"href":119,"dataGaLocation":47,"dataGaName":120},"/ja-jp/solutions/source-code-management/","Source Code Management",{"text":122,"config":123},"自動化されたソフトウェアデリバリー",{"href":106,"dataGaLocation":47,"dataGaName":124},"Automated software delivery",{"title":126,"description":127,"link":128,"items":133},"セキュリティ","セキュリティを犠牲にすることなくコード作成を高速化",{"config":129},{"href":130,"dataGaName":131,"dataGaLocation":47,"icon":132},"/ja-jp/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[134,138,143],{"text":135,"config":136},"アプリケーションセキュリティテスト",{"href":130,"dataGaName":137,"dataGaLocation":47},"Application security testing",{"text":139,"config":140},"ソフトウェアサプライチェーンの安全性",{"href":141,"dataGaLocation":47,"dataGaName":142},"/ja-jp/solutions/supply-chain/","Software supply chain security",{"text":144,"config":145},"ソフトウェアコンプライアンス",{"href":146,"dataGaName":147,"dataGaLocation":47},"/ja-jp/solutions/software-compliance/","software compliance",{"title":149,"link":150,"items":155},"測定",{"config":151},{"icon":152,"href":153,"dataGaName":154,"dataGaLocation":47},"DigitalTransformation","/ja-jp/solutions/visibility-measurement/","visibility and measurement",[156,160,165],{"text":157,"config":158},"可視性と測定",{"href":153,"dataGaLocation":47,"dataGaName":159},"Visibility and Measurement",{"text":161,"config":162},"バリューストリーム管理",{"href":163,"dataGaLocation":47,"dataGaName":164},"/ja-jp/solutions/value-stream-management/","Value Stream Management",{"text":166,"config":167},"分析とインサイト",{"href":168,"dataGaLocation":47,"dataGaName":169},"/ja-jp/solutions/analytics-and-insights/","Analytics and insights",{"title":171,"items":172},"GitLabが活躍する場所",[173,178,183],{"text":174,"config":175},"大企業",{"href":176,"dataGaLocation":47,"dataGaName":177},"/ja-jp/enterprise/","enterprise",{"text":179,"config":180},"スモールビジネス",{"href":181,"dataGaLocation":47,"dataGaName":182},"/ja-jp/small-business/","small business",{"text":184,"config":185},"公共部門",{"href":186,"dataGaLocation":47,"dataGaName":187},"/ja-jp/solutions/public-sector/","public sector",{"text":189,"config":190},"価格",{"href":191,"dataGaName":192,"dataGaLocation":47,"dataNavLevelOne":192},"/ja-jp/pricing/","pricing",{"text":194,"config":195,"link":197,"lists":201,"feature":281},"リソース",{"dataNavLevelOne":196},"resources",{"text":198,"config":199},"すべてのリソースを表示",{"href":200,"dataGaName":196,"dataGaLocation":47},"/ja-jp/resources/",[202,235,253],{"title":203,"items":204},"はじめに",[205,210,215,220,225,230],{"text":206,"config":207},"インストール",{"href":208,"dataGaName":209,"dataGaLocation":47},"/ja-jp/install/","install",{"text":211,"config":212},"クイックスタートガイド",{"href":213,"dataGaName":214,"dataGaLocation":47},"/ja-jp/get-started/","quick setup checklists",{"text":216,"config":217},"学ぶ",{"href":218,"dataGaLocation":47,"dataGaName":219},"https://university.gitlab.com/","learn",{"text":221,"config":222},"製品ドキュメント",{"href":223,"dataGaName":224,"dataGaLocation":47},"https://docs.gitlab.com/ja-jp/","product documentation",{"text":226,"config":227},"ベストプラクティスビデオ",{"href":228,"dataGaName":229,"dataGaLocation":47},"/ja-jp/getting-started-videos/","best practice videos",{"text":231,"config":232},"インテグレーション",{"href":233,"dataGaName":234,"dataGaLocation":47},"/ja-jp/integrations/","integrations",{"title":236,"items":237},"検索する",[238,243,248],{"text":239,"config":240},"お客様成功事例",{"href":241,"dataGaName":242,"dataGaLocation":47},"/ja-jp/customers/","customer success stories",{"text":244,"config":245},"ブログ",{"href":246,"dataGaName":247,"dataGaLocation":47},"/ja-jp/blog/","blog",{"text":249,"config":250},"リモート",{"href":251,"dataGaName":252,"dataGaLocation":47},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":254,"items":255},"つなげる",[256,261,266,271,276],{"text":257,"config":258},"GitLabサービス",{"href":259,"dataGaName":260,"dataGaLocation":47},"/ja-jp/services/","services",{"text":262,"config":263},"コミュニティ",{"href":264,"dataGaName":265,"dataGaLocation":47},"/community/","community",{"text":267,"config":268},"フォーラム",{"href":269,"dataGaName":270,"dataGaLocation":47},"https://forum.gitlab.com/","forum",{"text":272,"config":273},"イベント",{"href":274,"dataGaName":275,"dataGaLocation":47},"/events/","events",{"text":277,"config":278},"パートナー",{"href":279,"dataGaName":280,"dataGaLocation":47},"/ja-jp/partners/","partners",{"background":282,"textColor":283,"text":284,"image":285,"link":289},"#2f2a6b","#fff","ソフトウェア開発の未来への洞察",{"altText":286,"config":287},"ソースプロモカード",{"src":288},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":290,"config":291},"最新情報を読む",{"href":292,"dataGaName":293,"dataGaLocation":47},"/ja-jp/the-source/","the source",{"text":295,"config":296,"lists":298},"会社情報",{"dataNavLevelOne":297},"company",[299],{"items":300},[301,306,312,314,319,324,329,334,339,344,349],{"text":302,"config":303},"GitLabについて",{"href":304,"dataGaName":305,"dataGaLocation":47},"/ja-jp/company/","about",{"text":307,"config":308,"footerGa":311},"採用情報",{"href":309,"dataGaName":310,"dataGaLocation":47},"/jobs/","jobs",{"dataGaName":310},{"text":272,"config":313},{"href":274,"dataGaName":275,"dataGaLocation":47},{"text":315,"config":316},"経営陣",{"href":317,"dataGaName":318,"dataGaLocation":47},"/company/team/e-group/","leadership",{"text":320,"config":321},"チーム",{"href":322,"dataGaName":323,"dataGaLocation":47},"/company/team/","team",{"text":325,"config":326},"ハンドブック",{"href":327,"dataGaName":328,"dataGaLocation":47},"https://handbook.gitlab.com/","handbook",{"text":330,"config":331},"投資家向け情報",{"href":332,"dataGaName":333,"dataGaLocation":47},"https://ir.gitlab.com/","investor relations",{"text":335,"config":336},"トラストセンター",{"href":337,"dataGaName":338,"dataGaLocation":47},"/ja-jp/security/","trust center",{"text":340,"config":341},"AI Transparency Center",{"href":342,"dataGaName":343,"dataGaLocation":47},"/ja-jp/ai-transparency-center/","ai transparency center",{"text":345,"config":346},"ニュースレター",{"href":347,"dataGaName":348,"dataGaLocation":47},"/company/contact/#contact-forms","newsletter",{"text":350,"config":351},"プレス",{"href":352,"dataGaName":353,"dataGaLocation":47},"/press/","press",{"text":54,"config":355,"lists":356},{"dataNavLevelOne":297},[357],{"items":358},[359,362,367],{"text":54,"config":360},{"href":56,"dataGaName":361,"dataGaLocation":47},"talk to sales",{"text":363,"config":364},"サポートを受ける",{"href":365,"dataGaName":366,"dataGaLocation":47},"https://support.gitlab.com","support portal",{"text":368,"config":369},"カスタマーポータル",{"href":370,"dataGaName":371,"dataGaLocation":47},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":373,"login":374,"suggestions":381},"閉じる",{"text":375,"link":376},"リポジトリとプロジェクトを検索するには、次にログインします",{"text":377,"config":378},"GitLab.com",{"href":61,"dataGaName":379,"dataGaLocation":380},"search login","search",{"text":382,"default":383},"提案",[384,386,391,393,397,401],{"text":76,"config":385},{"href":81,"dataGaName":76,"dataGaLocation":380},{"text":387,"config":388},"コード提案（AI）",{"href":389,"dataGaName":390,"dataGaLocation":380},"/ja-jp/solutions/code-suggestions/","Code Suggestions (AI)",{"text":110,"config":392},{"href":112,"dataGaName":110,"dataGaLocation":380},{"text":394,"config":395},"GitLab on AWS",{"href":396,"dataGaName":394,"dataGaLocation":380},"/ja-jp/partners/technology-partners/aws/",{"text":398,"config":399},"GitLab on Google Cloud",{"href":400,"dataGaName":398,"dataGaLocation":380},"/ja-jp/partners/technology-partners/google-cloud-platform/",{"text":402,"config":403},"GitLabを選ぶ理由",{"href":89,"dataGaName":404,"dataGaLocation":380},"Why GitLab?",{"freeTrial":406,"mobileIcon":410,"desktopIcon":415,"secondaryButton":418},{"text":49,"config":407},{"href":408,"dataGaName":52,"dataGaLocation":409},"https://gitlab.com/-/trials/new/","nav",{"altText":411,"config":412},"GitLabアイコン",{"src":413,"dataGaName":414,"dataGaLocation":409},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":411,"config":416},{"src":417,"dataGaName":414,"dataGaLocation":409},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":203,"config":419},{"href":420,"dataGaName":421,"dataGaLocation":409},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp/get-started/","get started",{"freeTrial":423,"mobileIcon":427,"desktopIcon":429},{"text":424,"config":425},"GitLab Duoの詳細について",{"href":81,"dataGaName":426,"dataGaLocation":409},"gitlab duo",{"altText":411,"config":428},{"src":413,"dataGaName":414,"dataGaLocation":409},{"altText":411,"config":430},{"src":417,"dataGaName":414,"dataGaLocation":409},{"button":432,"mobileIcon":437,"desktopIcon":439},{"text":433,"config":434},"/switch",{"href":435,"dataGaName":436,"dataGaLocation":409},"#contact","switch",{"altText":411,"config":438},{"src":413,"dataGaName":414,"dataGaLocation":409},{"altText":411,"config":440},{"src":441,"dataGaName":414,"dataGaLocation":409},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":443,"mobileIcon":448,"desktopIcon":450},{"text":444,"config":445},"料金ページに戻る",{"href":191,"dataGaName":446,"dataGaLocation":409,"icon":447},"back to pricing","GoBack",{"altText":411,"config":449},{"src":413,"dataGaName":414,"dataGaLocation":409},{"altText":411,"config":451},{"src":417,"dataGaName":414,"dataGaLocation":409},{"title":453,"button":454,"config":459},"エージェント型AIがソフトウェア配信をどのように変革するかをご覧ください",{"text":455,"config":456},"GitLab Transcendを今すぐ視聴",{"href":457,"dataGaName":458,"dataGaLocation":47},"/ja-jp/events/transcend/virtual/","transcend event",{"layout":460,"icon":461,"disabled":14},"release","AiStar",{"data":463},{"text":464,"source":465,"edit":471,"contribute":476,"config":481,"items":486,"minimal":689},"GitはSoftware Freedom Conservancyの商標です。当社は「GitLab」をライセンスに基づいて使用しています",{"text":466,"config":467},"ページのソースを表示",{"href":468,"dataGaName":469,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":472,"config":473},"このページを編集",{"href":474,"dataGaName":475,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":477,"config":478},"ご協力をお願いします",{"href":479,"dataGaName":480,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":482,"facebook":483,"youtube":484,"linkedin":485},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[487,532,585,628,655],{"title":189,"links":488,"subMenu":503},[489,493,498],{"text":490,"config":491},"プランの表示",{"href":191,"dataGaName":492,"dataGaLocation":470},"view plans",{"text":494,"config":495},"Premiumを選ぶ理由",{"href":496,"dataGaName":497,"dataGaLocation":470},"/ja-jp/pricing/premium/","why premium",{"text":499,"config":500},"Ultimateを選ぶ理由",{"href":501,"dataGaName":502,"dataGaLocation":470},"/ja-jp/pricing/ultimate/","why ultimate",[504],{"title":54,"links":505},[506,508,510,512,517,522,527],{"text":54,"config":507},{"href":56,"dataGaName":57,"dataGaLocation":470},{"text":363,"config":509},{"href":365,"dataGaName":366,"dataGaLocation":470},{"text":368,"config":511},{"href":370,"dataGaName":371,"dataGaLocation":470},{"text":513,"config":514},"ステータス",{"href":515,"dataGaName":516,"dataGaLocation":470},"https://status.gitlab.com/","status",{"text":518,"config":519},"利用規約",{"href":520,"dataGaName":521,"dataGaLocation":470},"/terms/","terms of use",{"text":523,"config":524},"プライバシーに関する声明",{"href":525,"dataGaName":526,"dataGaLocation":470},"/ja-jp/privacy/","privacy statement",{"text":528,"config":529},"Cookie 優先設定",{"dataGaName":530,"dataGaLocation":470,"id":531,"isOneTrustButton":14},"cookie preferences","ot-sdk-btn",{"title":92,"links":533,"subMenu":542},[534,538],{"text":535,"config":536},"DevSecOpsプラットフォーム",{"href":74,"dataGaName":537,"dataGaLocation":470},"devsecops platform",{"text":539,"config":540},"AI支援開発",{"href":81,"dataGaName":541,"dataGaLocation":470},"ai-assisted development",[543],{"title":544,"links":545},"トピック",[546,550,555,560,565,570,575,580],{"text":110,"config":547},{"href":548,"dataGaName":549,"dataGaLocation":470},"/ja-jp/topics/ci-cd/","cicd",{"text":551,"config":552},"GitOps",{"href":553,"dataGaName":554,"dataGaLocation":470},"/ja-jp/topics/gitops/","gitops",{"text":556,"config":557},"DevOps",{"href":558,"dataGaName":559,"dataGaLocation":470},"/ja-jp/topics/devops/","devops",{"text":561,"config":562},"バージョン管理",{"href":563,"dataGaName":564,"dataGaLocation":470},"/ja-jp/topics/version-control/","version control",{"text":566,"config":567},"DevSecOps",{"href":568,"dataGaName":569,"dataGaLocation":470},"/ja-jp/topics/devsecops/","devsecops",{"text":571,"config":572},"クラウドネイティブ",{"href":573,"dataGaName":574,"dataGaLocation":470},"/ja-jp/topics/cloud-native/","cloud native",{"text":576,"config":577},"コーディングのためのAI",{"href":578,"dataGaName":579,"dataGaLocation":470},"/ja-jp/topics/devops/ai-for-coding/","ai for coding",{"text":581,"config":582},"エージェント型AI",{"href":583,"dataGaName":584,"dataGaLocation":470},"/ja-jp/topics/agentic-ai/","agentic ai",{"title":586,"links":587},"ソリューション",[588,591,593,598,602,605,608,611,613,615,618,623],{"text":135,"config":589},{"href":130,"dataGaName":590,"dataGaLocation":470},"Application Security Testing",{"text":122,"config":592},{"href":106,"dataGaName":107,"dataGaLocation":470},{"text":594,"config":595},"アジャイル開発",{"href":596,"dataGaName":597,"dataGaLocation":470},"/ja-jp/solutions/agile-delivery/","agile delivery",{"text":599,"config":600},"SCM",{"href":119,"dataGaName":601,"dataGaLocation":470},"source code management",{"text":110,"config":603},{"href":112,"dataGaName":604,"dataGaLocation":470},"continuous integration & delivery",{"text":161,"config":606},{"href":163,"dataGaName":607,"dataGaLocation":470},"value stream management",{"text":551,"config":609},{"href":610,"dataGaName":554,"dataGaLocation":470},"/ja-jp/solutions/gitops/",{"text":174,"config":612},{"href":176,"dataGaName":177,"dataGaLocation":470},{"text":179,"config":614},{"href":181,"dataGaName":182,"dataGaLocation":470},{"text":616,"config":617},"公共機関",{"href":186,"dataGaName":187,"dataGaLocation":470},{"text":619,"config":620},"教育",{"href":621,"dataGaName":622,"dataGaLocation":470},"/ja-jp/solutions/education/","education",{"text":624,"config":625},"金融サービス",{"href":626,"dataGaName":627,"dataGaLocation":470},"/ja-jp/solutions/finance/","financial services",{"title":194,"links":629},[630,632,634,636,639,641,643,645,647,649,651,653],{"text":206,"config":631},{"href":208,"dataGaName":209,"dataGaLocation":470},{"text":211,"config":633},{"href":213,"dataGaName":214,"dataGaLocation":470},{"text":216,"config":635},{"href":218,"dataGaName":219,"dataGaLocation":470},{"text":221,"config":637},{"href":223,"dataGaName":638,"dataGaLocation":470},"docs",{"text":244,"config":640},{"href":246,"dataGaName":247,"dataGaLocation":470},{"text":239,"config":642},{"href":241,"dataGaName":242,"dataGaLocation":470},{"text":249,"config":644},{"href":251,"dataGaName":252,"dataGaLocation":470},{"text":257,"config":646},{"href":259,"dataGaName":260,"dataGaLocation":470},{"text":262,"config":648},{"href":264,"dataGaName":265,"dataGaLocation":470},{"text":267,"config":650},{"href":269,"dataGaName":270,"dataGaLocation":470},{"text":272,"config":652},{"href":274,"dataGaName":275,"dataGaLocation":470},{"text":277,"config":654},{"href":279,"dataGaName":280,"dataGaLocation":470},{"title":295,"links":656},[657,659,661,663,665,667,669,673,678,680,682,684],{"text":302,"config":658},{"href":304,"dataGaName":297,"dataGaLocation":470},{"text":307,"config":660},{"href":309,"dataGaName":310,"dataGaLocation":470},{"text":315,"config":662},{"href":317,"dataGaName":318,"dataGaLocation":470},{"text":320,"config":664},{"href":322,"dataGaName":323,"dataGaLocation":470},{"text":325,"config":666},{"href":327,"dataGaName":328,"dataGaLocation":470},{"text":330,"config":668},{"href":332,"dataGaName":333,"dataGaLocation":470},{"text":670,"config":671},"Sustainability",{"href":672,"dataGaName":670,"dataGaLocation":470},"/sustainability/",{"text":674,"config":675},"ダイバーシティ、インクルージョン、ビロンギング（DIB）",{"href":676,"dataGaName":677,"dataGaLocation":470},"/ja-jp/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":335,"config":679},{"href":337,"dataGaName":338,"dataGaLocation":470},{"text":345,"config":681},{"href":347,"dataGaName":348,"dataGaLocation":470},{"text":350,"config":683},{"href":352,"dataGaName":353,"dataGaLocation":470},{"text":685,"config":686},"現代奴隷制の透明性に関する声明",{"href":687,"dataGaName":688,"dataGaLocation":470},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":690},[691,693,696],{"text":518,"config":692},{"href":520,"dataGaName":521,"dataGaLocation":470},{"text":694,"config":695},"Cookieの設定",{"dataGaName":530,"dataGaLocation":470,"id":531,"isOneTrustButton":14},{"text":523,"config":697},{"href":525,"dataGaName":526,"dataGaLocation":470},[699],{"id":700,"title":9,"body":28,"config":701,"content":703,"description":28,"extension":27,"meta":707,"navigation":14,"path":708,"seo":709,"stem":710,"__hash__":711},"blogAuthors/en-us/blog/authors/patrick-steinhardt.yml",{"template":702},"BlogAuthor",{"name":9,"config":704},{"headshot":705,"ctfId":706},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661952/Blog/Author%20Headshots/pks-gitlab-headshot.png","pksgitlab",{},"/en-us/blog/authors/patrick-steinhardt",{},"en-us/blog/authors/patrick-steinhardt","SV9Yd_vW69UbvntDP-SEOV9NKT_VwUAj5nfftf2ElSw",[713,727,741],{"content":714,"config":725},{"heroImage":715,"body":716,"authors":717,"updatedDate":719,"date":720,"title":721,"tags":722,"description":724,"category":11},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1776457632/llddiylsgwuze0u1rjks.png","AIがコードを書く時代になりました。それはもはや当然のことです。しかし、計画、セキュリティ、コンプライアンス、デプロイメントはどうでしょうか？これらの課題はまだ残っています。私はコントリビュータープログラムを長年運営してきましたが、コミュニティがこれほどまでにテクノロジーに反応するのを見たことがありませんでした。\n\nそこで私たちは[GitLab Duo Agent Platform](https://about.gitlab.com/ja-jp/gitlab-duo-agent-platform/)を開放し、世界中の開発者に対して、チームがより安全なソフトウェアを迅速にリリースできるAIエージェントの構築を呼びかけました。質問に答えるだけのチャットボットではなく、ワークフローに直接入り込み、イベントに反応し、ユーザーの代わりに行動するエージェントです。GitLab AIハッカソンは、2026年2月9日から3月25日まで、ハッカソンプラットフォームのDevpostで開催されました。Google CloudとAnthropicがコスポンサーとして参加しました。\n\nGoogle CloudおよびAnthropicとともにこのハッカソンを企画した際、私は審査員に4つの観点でスコアリングするよう依頼しました。技術的な完成度、デザイン、潜在的なインパクト、そしてアイデアの質です。参加者が多く集まることを期待していましたが、実際の結果は私たちの予想をはるかに上回るものでした。19名の審査員が18日間かけてすべてのエントリーを審査しました。Google CloudとAnthropicは審査員、賞品、クラウドアクセスを提供しました。コミュニティは、これらの課題を解決したいという思いから、数百ものエージェントとフローを構築したのです。\n\n約7,000人の開発者が参加し、数週間で600以上のエージェントとフローを構築しました。全カテゴリーの賞金総額は、GitLab、Google Cloud、Anthropicから合計65,000ドルに上りました。\n\nベテランエンジニアが退職してチームの知識の半分を持ち去っていくのを目の当たりにしたことがある方なら、なぜグランプリ受賞プロジェクトがこれほど刺さるのか、おわかりいただけるでしょう。\n\nコミュニティが何を作り上げたのか、ぜひご覧ください。\n\n## グランプリ：LORE\n\n[LORE](https://devpost.com/software/lore-living-organizational-record-engine)（Living Organizational Record Engine）は、各質問を適切なエージェントに振り分けるルーターを備えた8つのエージェント、ナレッジグラフ内の循環ループを防ぐロジック、ビジュアルダッシュボード、そしてカーボントラッキングで構成されています。コマンドラインツールには43のテストが付属しています（ハッカソンプロジェクトで43のテストとは、驚くべき数字です）。\n\nLOREが解決するのは、エンジニアの頭の中に蓄積された知識が、退職とともに失われてしまうというリアルな問題です。私の経験上、ハッカソンプロジェクトで43のテストを書くチームはほとんどいません。その数字が、このチームの本気度を物語っています。\n\n審査員のApril Guo氏（Anthropic）はこう記しました。「ハッカソンの作品というより、製品のような完成度です。」\n\n### Google Cloud賞受賞者\n\n[Gitdefender](https://devpost.com/software/gitdefender)がGoogle Cloudグランプリを受賞しました。コードレビューのワークフロー内でセキュリティ上の問題を発見・修正します。バグを検出し、修正を記述し、コードレビューを自動でオープンします。開発者が介入する必要はありません。\n\n[Aegis](https://devpost.com/software/aegis-2m1oq0)がGoogle Cloud準グランプリを受賞しました。すべての判断に対してAIによる説明を提供し、Google Cloudにデプロイされた本番環境にも対応しています。\n\n### Anthropic賞受賞者\n\n[GraphDev](https://devpost.com/software/graphdev)がAnthropicグランプリを受賞しました。コードの依存関係をマッピングし、システムが時間とともにどのように変化したかを可視化します。審査員のAboobacker MK氏（GitLab）は「GitLabのナレッジグラフに関する私たちの取り組みと方向性が一致している」と指摘しました。また審査員のAyush Billore氏（GitLab）は「デモとUXが素晴らしく、システムの変遷や変更による影響範囲を理解するうえで非常に有用です」と述べました。変更を加える前に、その全体的な影響を把握することができます。\n\n[DocSync](https://devpost.com/software/pipeheal)がAnthropicの準グランプリを受賞しました。Detector、Writer、Reviewerの3つのエージェントを使用します。DocSyncが修正に確信を持てる場合はコードレビューをオープンし、そうでない場合は人間が確認するためのイシューを作成します。\n\n## カテゴリー賞受賞者\n\n### 最も技術的に印象的な作品\n\nデータベースのマイグレーションは障害の原因になりがちです。[Time-Traveler](https://devpost.com/software/time-traveler-w3cxp0)は、本番環境のコピーを安全に作成し、そのコピーに対してマイグレーションを実行して結果を報告します。ブリッジで接続された5つのエージェントが動作し、Google Cloudへの実際のデプロイ、実際のPostgreSQLマイグレーション、そして実際のデータを使用します。\n\n### 最もインパクトのある作品\n\n[RedAgent](https://devpost.com/software/redagent)は、AIが生成したセキュリティレポートを検証し、AI分析結果と開発者の行動の間にある信頼のギャップを解消します。セキュリティスキャンにAIを活用しているチームであれば、この問題はご存知でしょう。検証できないという理由でAIの分析結果を無視してしまうチームを、私も多く見てきました。RedAgentは、AIの出力を開発者に届ける前に検証する手段をチームに提供します。\n\n### 最も使いやすい作品\n\n[Launch Control](https://devpost.com/software/launch-control-bgp8az)は洗練されたUXと堅牢なインフラを備え、サステナビリティの面でも高評価を得ました。\n\n## サステナビリティの可能性\n\n5つのプロジェクトが、環境への配慮に対して賞またはボーナスを受賞しました。CI/CDパイプラインと同様に、ソフトウェアデリバリーにはカーボンコストがかかります。そして今や、LLMも大規模なコンピューティングリソースを消費します。私たちはGreen Agentカテゴリーを設け、開発者にそのフットプリントの計測と削減に挑戦してもらいました。GitLabのサステナビリティチームのStacy ClineとKim Buncleが、Green Agentカテゴリーの審査に参加しました。\n\n### Green Agent賞\n\n[GreenPipe](https://devpost.com/software/greenpipe)は、CI/CDパイプラインの環境負荷をスキャンし、カーボンフットプリントレポートを生成します。審査員のKim BuncleとRajesh Agadi氏（Google）の両者から高く評価されました。\n\n### サステナブルデザインボーナス\n\nサステナブルデザインボーナスは、モデルの最適化技術からエネルギー効率の高いアーキテクチャの選択に至るまで、設計において卓越したサステナビリティへの取り組みを示したプロジェクトに授与されました。\n\n* [BugFlow](https://devpost.com/software/bugflow-ai-regression-detective-ci-optimizer)は20分間で1件のバグレポートから10件の修正を実現しました。\n* [DELTA Cyber Reasoning](https://devpost.com/software/delta-cyber-reasoning-system)はセキュリティのための自動ファジングテストです。\n* [CarbonLint](https://devpost.com/software/carbonlint)はエネルギー消費にコード分析を応用しました。\n* [TFGuardian](https://devpost.com/software/tfguardian)はカーボンフットプリントアナライザーなど複数のエージェントを備えています。\n\nサステナブルデザインボーナス受賞者の皆さん、おめでとうございます！\n\n審査員のJens-Joris Decorte氏（TechWolf）は成果をこう述べています：月額コストが556ドルから18ドルに下がり、カーボン排出量が96%削減されました（サステナビリティの観点から見ても、月538ドルのコスト削減です）。\n\n## 特別賞とその他の受賞者\n\n6つのプロジェクトが特別賞を受賞しました：\n\n- [SecurityMonkey](https://devpost.com/software/securitymonkey)は既知の脆弱性をテストブランチに注入し、セキュリティスキャナーがどれだけ検知できるかをスコアリングします。\n- [stregent](https://devpost.com/software/stregent)はCI/CDパイプラインを監視し、開発者がノートPCを開かずにWhatsAppから調査・マージ修正を行えるようにします。\n- [Compliance Sentinel](https://devpost.com/software/compliance-sentinel-autonomous-devsecops-governance)はすべてのマージリクエストのコンプライアンスリスクをスコアリングし、重大な違反が検出された場合はマージをブロックします。\n- [Carbon Tracker](https://devpost.com/software/carbon-tracker-ij25kf)はCI/CDパイプラインの各ジョブのカーボンフットプリントを算出し、最適化のヒントをマージリクエストに投稿します。\n- [RepoWarden](https://devpost.com/software/docuguard)は初のLiving Specification Engineであり、コードが「何をするか」だけでなく「なぜ書かれたか」を記録するAIシステムです。\n- [MR Compliance Auditor](https://devpost.com/software/mr-compliance-auditor)はマージリクエスト全体からエビデンスを収集し、SOC 2コントロールにマッピングして、コンプライアンススコアをライブダッシュボードにストリーミングします。\n\n審査中で私が最も印象に残った言葉は、Luca Chun Lun Lit氏（Anthropic）がstregentのモバイルファーストなアプローチについて述べたものです。「スマートフォンから実質的にコーディングできるというのは、エンジニアリング体験の新たなレベルです。」\n\n> [プロジェクトギャラリー](https://gitlab.devpost.com/project-gallery)で600以上のエントリーをご覧ください。\n\n## 今後の展開\n\nこのハッカソンに参加したすべてのエージェントは、単一プロジェクト内で動作していました。それでも印象的な成果を上げています。一部の参加者は、リポジトリ内のコードの関係性や依存関係を把握するために、ローカルのナレッジグラフをエージェントと並行して動かしていました。LOREはプロジェクトの履歴を記録し、Gitdefenderは脆弱性を発見します。より豊かなローカルコンテキストとエージェントを組み合わせることで、コントリビューターはすでにより精度の高いツールを構築しつつあります。次回のハッカソンは、コントリビューターが豊かなコンテキストですでに実現していることをさらに発展させます。詳細が公開され次第いち早くお知らせを受け取るには、[contributors.gitlab.com](https://contributors.gitlab.com/)でサインアップしてください。\n\n## さあ、始めましょう\n\nこのハッカソンの舞台裏を支えてくれたLee Tickett氏（GitLab）とMattias Michaux氏（GitLab）に、特別な感謝を申し上げます！\n\n参加してくださったすべての開発者の皆さん、ありがとうございました。約7,000人のみなさんが、GitLab Duo Agent Platformの可能性を証明してくれました。皆さんが作り上げたものを誇りに思いますし、次に何を構築してくれるのか、今から楽しみです。\n\n[GitLab Duo Agent Platform](https://docs.gitlab.com/ja-jp/user/duo_agent_platform/)で自分だけのエージェントを構築しましょう。コミュニティが作成したエージェントは[AIカタログ](https://docs.gitlab.com/ja-jp/user/duo_agent_platform/ai_catalog/)でご覧いただけます。オーケストレーションはあなたが、加速はAIが担います。\n",[718],"Nick Veenhof","2026-04-23","2026-04-22","GitLab AIハッカソン2026：受賞者発表",[723,265],"AI/ML","約7,000人の開発者がGitLab Duo Agent Platform上で600以上のAIエージェントとフローを構築したハッカソンの結果をご紹介。",{"featured":33,"template":15,"slug":726},"gitlab-ai-hackathon-2026-meet-the-winners",{"content":728,"config":739},{"date":729,"heroImage":730,"title":731,"authors":732,"category":11,"body":734,"description":735,"tags":736},"2025-08-04","https://res.cloudinary.com/about-gitlab-com/image/upload/v1754287290/averr2ecwl01q2f9lknf.jpg","git mergeコマンドの基本を徹底解説",[733],"GitLab Team","## 目次\n\n1. [git mergeとは？](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#git-merge%E3%81%A8%E3%81%AF%EF%BC%9F)\n2. [git mergeコマンドの基本](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#git-merge%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E5%9F%BA%E6%9C%AC)\n3. [マージ先のブランチを準備する](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#%E3%83%9E%E3%83%BC%E3%82%B8%E5%85%88%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E6%BA%96%E5%82%99%E3%81%99%E3%82%8B)\n4. [最新のリモートコミットをフェッチする](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#%E6%9C%80%E6%96%B0%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E3%83%95%E3%82%A7%E3%83%83%E3%83%81%E3%81%99%E3%82%8B)\n5. [早送りマージと３ウェイマージ](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#%E6%97%A9%E9%80%81%E3%82%8A%E3%83%9E%E3%83%BC%E3%82%B8%E3%81%A8%EF%BC%93%E3%82%A6%E3%82%A7%E3%82%A4%E3%83%9E%E3%83%BC%E3%82%B8)\n6. [git mergeによるコンフリクトの解決](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#git-merge%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%95%E3%83%AA%E3%82%AF%E3%83%88%E3%81%AE%E8%A7%A3%E6%B1%BA)\n7. [git mergeコマンドのベストプラクティス](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#git-merge%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E3%83%99%E3%82%B9%E3%83%88%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B9)\n8. [GitLabでgit mergeを使う](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#git-merge%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E3%83%99%E3%82%B9%E3%83%88%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B9)\n9. [git merge のFAQ](https://about.gitlab.com/ja-jp/blog/git-merge-command-overview/#git-merge%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89-%E3%81%AEfaq)\n\n## git mergeとは？\n\ngit mergeとは、分岐したブランチをmerge（マージ、統合すること）するコマンドのことです。別のリポジトリからの変更を組み込む際にも使われ、git pull（git fetchとgit mergeを組み合わせたもの）の一部としても機能します。チームで開発を実施するときなどにmainブランチから作業用ブランチを作り、テストをしてからマージ、プッシュすることも多いでしょう。\n\nたとえば、main ブランチに基づいて作成された新しいブランチ’feature’があるとします。この feature ブランチを main にマージするのに使われるのがgit mergeコマンドです。\n\n## git mergeコマンドの基本\n\ngit mergeの基本的なコードは次のようになります。\n\n```shell\ngit merge BRANCH_NAME\n```\n\nブランチ名は、取り込みたいブランチの名前を入力します。\n\n一見簡単そうですが、マージをスムーズに実行するにはいくつか準備が必要となりますので、次の章で確認しましょう。\n\n## マージ先のブランチを準備する\n\ngit status を実行して、HEAD が取り込む先のブランチであることを確認します。必要に応じて\n\n```shell\ngit checkout BRANCH_NAME\n```\n\nを実行して、マージする先のブランチに切り替えます。\n\n## 最新のリモートコミットをフェッチする\n\nリモートで変更を加えたら、マージ先ブランチとマージ元ブランチに最新の変更内容を反映させます。その際は、[git fetchとgit pull](https://about.gitlab.com/ja-jp/blog/what-is-the-difference-between-git-fetch-and-git-pull/)を使います。その後、リモートで加えた変更内容がmainブランチに反映されていることを確認します。\n\n## 早送りマージと３ウェイマージ\n\n早送りマージは、ブランチが分岐していない場合にのみ使えるコマンドです。早送りマージでは、マージ自体は行われませんが、ブランチの先頭とブランチの末尾の履歴を結合することで、旧ブランチからアクセスできたコミットが、新ブランチからも利用できるようになります。\n\n強制的に早送りマージを実施する場合は以下のコードを使います（分岐がある場合など早送りマージができない場合にはエラーとなりマージはできません）\n\n```shell\ngit merge --ff-only\n```\n\n一方、ブランチが分岐している場合には、早送りマージを適用することはできず、マージする手段は３ウェイマージに限られます。３ウェイマージは、3 つのコミット （2 つのブランチのそれぞれ先端のコミットと履歴を統合するために生成される専用のコミット）を使用してマージコミットを生成することから来ています。\n\n```shell\ngit checkout BRANCH_NAME\n```\n\nを使うと、早送りマージが可能な時は早送りマージを実施し、できない時に３ウェイマージを実施します。\n\n## git mergeによるコンフリクトの解決\n\nマージの基本を理解すると、同じ箇所を同時に更新してしまったらどうなるのか、という疑問を持たれる方もいるのではないでしょうか。この場合、Git側ではどちらを優先すべきか判断ができず、手作業でコンフリクトを解決することを求めます。\n\nエラーメッセージは次のように表示されます。\n\n```shell\ngit merge BRANCH_NAME\nAuto-merging index.html\nCONFLICT (content): Merge conflict in index.html\nAutomatic merge failed; fix conflicts and then commit the result.\n```\n\nコンフリクトを解決するまで、処理は中断されます。どのファイルでコンフリクトが発生してマージできなかったのを確認するにはgit status を実行します。\n\n```shell\ngit status\n```\n\n未解決のコンフリクトについては unmerged として表示されます。標準的なコンフリクトマーカーがファイルに追加されるため、該当ファイルから修正できます。git addを実行して、コンフリクトが解決したことを Git に通知します。続いて通常の git commit を実行してマージ コミットを生成します。\n\n## git mergeコマンドのベストプラクティス\n\ngit mergeコマンドでよく起こる問題として、他のデベロッパーが加えた変更を破棄してしまうことが挙げられます。個々人がこまめにgit mergeを実行することで、変更を破棄してしまう問題は避けることができますが、マージそのもののコストが膨れ上がる可能性があります。複雑なコンフリクトが出ない場合に自動マージしてくれるようなツールの導入は、git mergeを使うチームの大きな手助けになるはずです。\n\n## GitLabでgit mergeを使う\n\ngit mergeのベストプラクティスとしてツールの使用をおすすめしましたが、[GitLab](https://about.gitlab.com/ja-jp/)なら自動マージ機能のほかにもリモートリポジトリのホスティング、インターフェースの提供、変更内容のコードレビュー、プッシュされたコードの自動ビルド、テスト、デプロイまでを一括で管理できます。\n\ngit mergeで起きるコンフリクトを自動で解決できるGitLabの無料トライアルは[こちら](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp/&glm_content=default-saas-trial)からお申し込みいただけます。\n\n## git mergeコマンド のFAQ\n\n### git mergeコマンドとは何ですか？\n\ngit mergeとは、分岐したブランチをmerge（マージ、統合すること）するコマンドのことです。\n\n### mainブランチにマージするにはどうしたらいいですか？\n\nまず、\u003Ccode>git checkout BRANCH_NAME\u003C/code>を使ってmainブランチに移動します。\n\n次に\u003Ccode>git merge BRANCH_NAME\u003C/code>を使ってマージしたいブランチを指定します。\n\nマージ先ブランチ名）master\\\nマージするブランチ名）feature1の場合には\n\n```xml\n\u003Ccode>git checkout master\u003C/code>\n\u003Ccode>git merge feature1\u003C/code>\n```\n\n\\\nとなります。\n\n### git mergeとgit rebaseの違いは何ですか？\n\ngit mergeとgit rebaseはどちらもブランチを結合するコマンドです。mergeが新しいコミットを生成してコミット履歴が分散してしまうのに対し、rebaseはコミット履歴をひとつのブランチにまとめます。rebaseはログを整理する目的で使われることが多いですが、別のブランチで他のメンバーが加えた変更の履歴を消してしまう可能性などがあるので、上級者向けのコマンドといえます。\n\n*監修：知念 梨果* *[@rikachinen](https://gitlab.com/rikachinen)（GitLab合同会社 カスタマーサクセス本部 カスタマーサクセスエンジニア）*\n","この記事では、git mergeコマンドについてコマンドの基本的な使い方からリクエストコードまで解説します。",[737,22,23,738],"collaboration","workflow",{"featured":14,"template":15,"slug":740},"git-merge-command-overview",{"content":742,"config":751},{"title":743,"description":744,"authors":745,"heroImage":746,"date":747,"body":748,"category":11,"tags":749},"オープンソースソフトウェア（OSS）とは？詳しく解説​","オープンソースの意味や、メリットとデメリットについて、分かりやすく解説します。",[733],"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752720740/g9x8oi988xuhioglpczi.jpg","2025-07-17","## オープンソースとは？\n\nオープンソースとは、ソフトウェアのコードが公開され、誰もが利用、改良、再配布できるという仕組みのことを指します。「オープンソースソフトウェア」と同義で使用されることが多いです。\n\n## オープンソースソフトウェア（OSS）とは？\n\nオープンソースソフトウェアはOSSとも記述され、Open Source Softwareの略称です。一般的な商用ソフトウェアとは異なり、誰でも利用、改良、再配布ができるようソースコードが公開されています。これにより個人や企業のデベロッパーは、各々の環境に合わせてソフトウェアを自由に改変し、特定の用途や問題に最適化することが容易にできます。ただし、OSSによってはライセンス制約が存在する場合もあります。\n\nフリー（無料）ソフトと混同されることがありますが、フリーソフトのほとんどはソースコードが非公開です。よって、ソースコードが公開されているかどうかで、OSSかの判断をするのが一般的です。\n\n## オープンソースソフトウェアの基本原則\n\nオープンソフトウェアに明確な定義はありませんが、「ソースコードが公開されていること」以外にも広く認知されている要件があります。これら要件は、米国のOpen Source Initiative（OSI）という団体が提唱した以下10項目を指すのが一般的です。\n\n* 再配布の自由\n* ソースコードの配布\n* 派生ソフトウェアの配布許可\n* 作成者のオリジナルコードの完全性\n* 個人やグループに対する差別禁止\n* 使用分野に対する差別禁止\n* ライセンスの配布\n* 特定製品でのみ有効なライセンスの禁止\n* 他ソフトウェアを制限するライセンスの禁止\n* ライセンスの技術的中立\n\n要約するとOSSの基本原則は、ユーザーやデベロッパーに自由を提供し、協力的な環境を促進することと言えます。ただし、「自由」ではあるものの、ライセンスによって一定のルールは設定されています。例えば、GPLやMITライセンスは、OSSに付随するライセンスの利用や再配布、改変の範囲を規定し、自由利用を促進しつつも、デベロッパーやユーザーの権利を保護しています。OSS利用の際は、こういったライセンスルールを理解し、遵守することを忘れないようにしましょう。ライセンスについては後ほど詳しく解説します。\n\n## オープンソースソフトウェアの具体例\n\nどういったソフトウェアがOSSなのかと問われると、すぐには思いつかないかもしれません。実際に、どういったソフトが様々な分野で活躍しているのかいくつかご紹介しましょう。\n\n### WordPress\n\nWordPressという名前は、誰もが一度は聞いたことがあるでしょう。WordPressはウェブサイトを簡単に作成できるコンテンツ管理システム（CMS）で、世界中でもっとも利用されているCMSとなっています。ウェブサイトデベロッパーは自由にカスタマイズを行うことができ、また、活発なコミュニティで互いをサポートし合うことにより、新たな拡張機能の開発等に貢献しています。\n\n### GIMP\n\nGIMPは、イラストレーター、グラフィックデザイナー、フォトグラファー、サイエンティストなど画像を扱う専門家に人気の画像編集ソフトウェアです。ユーザーは無料でダウンロードして利用でき、WordPressと同じく活発なコミュニティが、日々のバグ修正や、新プラグインを開発をサポートしています。\n\n### Brave Browser\n\nBraveは、ユーザーのプライバシー保護を主眼としたウェブブラウザであり、広告やトラッキングを防止してくれます。さらに、独自の暗号通貨（BAT）や検索システムを開発しているなどの理由で、デベロッパー間では人気のブラウザの一つです。Braveもオープンソースであるため、個人が自由にブラウザ機能をカスタマイズしたり、新たに機能を追加したりすることができる仕様となっています。\n\n### GitLabのオープンソースプロジェクト\n\n[GitLabプラットフォーム](https://about.gitlab.com/ja-jp/)を利用して開発されているオープンソースプロジェクトをいくつかご紹介します。\n\n#### Drupal\n\nDrupalはWordPressと同様に、オープンソースのコンテンツ管理システム（CMS）です。堅牢性と拡張性の高さが評価されており、NASAや経済産業省といった政府機関や、Teslaなどの企業に採用されています。\n\n#### VLC\n\nWindowsやMacにとどまらず、LinuxやiOS等でも使うことできる、メディアプレイヤーです。多様な種類の音声や動画ファイルを再生でき、様々なファイル形式に対応しています。広告等、ユーザーにとって不要な機能が一切搭載されておらず、世界中で広く利用されています。\n\n#### LibreOffice\n\nMicrosoft Officeとよく比較されることがあるのが、LibreOfficeです。無料で利用することができ、様々なオフィスツールを提供することから、たくさんの企業や個人に使用されています。\n\n## オープンソース開発のメリットとデメリット\n\nOSSの開発には様々なメリットとデメリットがあります。開発手法についての議論は付きませんが、ここでは言及されることが多いポイントをいくつか挙げてみます。\n\n### メリット\n\n#### コミュニティによる自発的なサポートと開発\n\nオープンソース開発は通常、世界中のデベロッパーが参加した活発なコミュニティを形成しています。多種多様なバックグランドを持つ個々のユーザーたちがお互いにアイデアやフィードバック、サポートし合うことを基本とし、継続的な開発とサポートをしてくれます。\n\n#### 高い透明性に担保された信頼とセキュリティ\n\nOSSの信頼とセキュリティは、誰もがソースコードを参照できることで実現されています。\n\nまず、たくさんのデベロッパーの目に触れるため、脆弱性やバグが比較的早い段階で発見されます。これにより、セキュリティを高レベルに引き上げることができます。そして、ソースコードが公開されているため、不正な動作やバックドアの存在といったリスクを排除しやすく、ソフトウェアの信頼性を高めてくれます。\n\n#### 開発にかかる時間と費用の削減\n\nオープンソースソフトウェアは大抵が無料で、自由にソースコードを改変できます。よって、ライセンス料とスクラッチ開発が不要であり、個人や企業の費用と開発時間を大幅に削減してくれます。\n\n### デメリット\n\n#### 開発プロジェクトの継続性\n\nオープンソース開発は、有志が中心となって行われる場合が多いため、プロジェクトが遅延したり、突然中止となったりするリスクがあります。また、安定した開発スケジュールが維持されないこともあります。\n\nプロジェクトの多くは無償、スポンサー、寄付で成り立っていることが一般的なので、開発コアメンバーが抜けた、資金が枯渇してしまった、などの理由から開発自体が立ち行かなくなることもあります。\n\n#### 責任の所在が曖昧\n\nコミュニティ主導で開発が進められる場合、ユーザーにバグや他ソフトと統合できないといった問題が発生しても商用ソフトウェアとは異なり、自己解決しなくてはならないケースが通常です。迅速かつ的確なサポートが受けづらいケースも、発生することがあります。\n\n#### ライセンスの準拠で\n\n当然ながら、OSSにもライセンスが存在します。無条件に利用や再配布ができるわけではないので、しっかりとライセンスを理解した上で使用しなければいけません。ライセンス規約に違反してしまい、過去には訴訟に発展したケースもあるため、注意が必要です。詳しくは後ほど解説します。\n\n### オープンソースの課題とGitLabのアプローチ\n\nGitLabというプラットフォームが、OSSにおける課題に対してどう取り組んでいるかについて、いくつかご紹介しましょう。詳細を知りたい場合は、[オープンソースプロジェクト向けのGitLabソリューション](https://about.gitlab.com/ja-jp/solutions/open-source/)を読んでみてください。\n\n#### 脆弱性の早期発見と修正\n\nオープンソースは、コードが公開されているため、悪意のある人物が脆弱性を発見してしまうリスクがあります。\n\n[DevSecOpsプラットフォーム](https://about.gitlab.com/ja-jp/topics/devsecops/)であるGitLabは、開発プロセス全体においてセキュリティを重要視しています。静的アプリケーションセキュリティテスト（SAST）や依存関係スキャンといった強力なツールが、早期の脆弱性発見と修正を実現する仕組みを実現します。\n\n#### サポートの補完\n\nOSSはコミュニティによるサポートが中心となり、的確なサポートや迅速な対応を受けられないケースが発生することがあります。\n\n[商用版GitLab](https://about.gitlab.com/ja-jp/pricing/)には、「GitLab Premium」「GitLab Ultimate」があり、公式サポートという選択肢が用意されています。また、コミュニティの結束を高める働きかけをすることで自発的サポートも促進しています。\n\n#### コミュニティの活性化\n\n活発なコミュニティなしに、OSSを成功させることはできませんが、これを維持するのは容易ではありません。\n\nGitLabは、[GitLabフォーラム](https://forum.gitlab.com/c/community/gitlab-for-open-source/49)を運営したり、[オープンソース団体向けプログラム](https://about.gitlab.com/ja-jp/solutions/open-source/join/)を実施、GitLabハッカソンやオンラインイベントを開催したりすることで、デベロッパー同士の繋がりを促進、コミュニティの活性化と拡大に貢献しています。\n\n## オープンソースのライセンスとその重要性\n\nオープンソースのライセンスは、ソフトウェアの利用、配布、変更等に関する権利と制限を明記したものであり、法的拘束力を持ちます。よって、ソフト利用者はこれをしっかりと理解した上で、トラブル回避をすることが望ましいといえます。\n\nまた、ソフトウェアデベロッパーがどのライセンス規約にするかを考える場合には、透明性を重視するのか、自由度を重視するのかなどにより選択するライセンスが異なってきます。ここでは、いくつか代表的なものをご紹介しましょう。\n\n以下に表としてまとめてみました。\n\n![オープンソース　ライセンスのタイプと代表例](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752720035/v9ld6h78ilk22x30nged.jpg)\n\n### コピーレフト\n\nコピーレフトライセンスは、元となるソフトウェアを再配布する時には、派生物も元OSSと同じ条件下で行う必要があるというものです。このタイプのライセンスは、非常に伝播性が強いのが特徴です。\n\nまたコピーレフトという言葉は、「コピーライト」をもじったものから誕生しました。\n\n### 準コピーレフト\n\nコピーレフトと比べ、伝播性が多少弱いのが準コピーレフトです。元のOSSのソースコードを再利用した時に、元のライセンスと同条件で再配布する必要があります。\n\n### 非コピーレフト\n\nパーミッシブライセンスとも呼ばれます。名前の通りですが、元のOSSと同条件のライセンスにする必要がありません。ソースコードの公開義務がないため、商用利用されることが多いです。\n\n## よくある質問\n\n### オープンソースソフトウェア（OSS）とは何ですか？\n\nOSSとは、ソースコードが公開され、誰でも自由に利用、修正、配布できるソフトウェアのことです。\n\n### OSSのセキュリティは安心ですか？\n\nOSSライセンスは、ソフトウェアの利用や再配布に関する自由と制約を明確に定義したものです。\n\n### OSSのライセンスにはどんな種類がありますか？\n\nライセンスにはGPL、MIT、Apache Licenseなど、異なる自由度や利用条件を持つものがあり、コピーレフト、準コピーレフト、非コピーレフトの３つに大別されます。\n\n### なぜ企業がOSSを採用するのですか？\n\nコスト削減、柔軟性、信頼性向上、技術コミュニティとの連携が理由となる場合が多いです。またGitLabでは、[オープンソースプロジェクト向けのソリューション](https://about.gitlab.com/ja-jp/solutions/open-source/)を提供しています。ぜひご確認ください。\n\n*監修：佐々木 直晴* [@naosasaki](https://gitlab.com/naosasaki)*（GitLab合同会社 ソリューションアーキテクト本部 シニアソリューションアーキテクト）*",[737,265,24,750],"security",{"featured":14,"template":15,"slug":752},"what-is-open-source",{"header":754,"blurb":755,"button":756,"secondaryButton":760},"今すぐ開発をスピードアップ","DevSecOpsに特化したインテリジェントオーケストレーションプラットフォームで実現できることをご確認ください。\n",{"text":49,"config":757},{"href":758,"dataGaName":52,"dataGaLocation":759},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/ja-jp/","feature",{"text":54,"config":761},{"href":56,"dataGaName":57,"dataGaLocation":759},{"promotions":763},[764,778,790,801],{"id":765,"categories":766,"header":768,"text":769,"button":770,"image":775},"ai-modernization",[767],"ai-ml","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":771,"config":772},"Get your AI maturity score",{"href":773,"dataGaName":774,"dataGaLocation":247},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":776},{"src":777},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":779,"categories":780,"header":782,"text":769,"button":783,"image":787},"devops-modernization",[781,569],"product","Are you just managing tools or shipping innovation?",{"text":784,"config":785},"Get your DevOps maturity score",{"href":786,"dataGaName":774,"dataGaLocation":247},"/assessments/devops-modernization-assessment/",{"config":788},{"src":789},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":791,"categories":792,"header":793,"text":769,"button":794,"image":798},"security-modernization",[750],"Are you trading speed for security?",{"text":795,"config":796},"Get your security maturity score",{"href":797,"dataGaName":774,"dataGaLocation":247},"/assessments/security-modernization-assessment/",{"config":799},{"src":800},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":802,"paths":803,"header":806,"text":807,"button":808,"image":813},"github-azure-migration",[804,805],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":809,"config":810},"See how GitLab compares to GitHub",{"href":811,"dataGaName":812,"dataGaLocation":247},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":814},{"src":789},1777493678667]