Git プロジェクトは、 可能な限り下位互換性を確保することを狙っています。 マイナー・リリースでは、 セキュリティ上の脆弱性など、 非常に強い理由がない限り、下位互換性が失われることはありません。

それでも、 Git プロジェクトはとにかく古くからあるあるため、 変化する世界に合わせてプロジェクトを維持するために最終的に必要となる、 下位互換性のない変更のバックログが蓄積するのは当然のことです。 こういう変更はいくつかのカテゴリに分類されます:

  • デフォルトを長年に渡り確立されてきたものに変更する。

  • 概念をより優れたデザインで置き換える。

  • 大きく機能が足りない点があり、 かつ、 修正できないため、 置き換えできずに削除する、 概念やコマンドや構成やオプション。

ユーザーから見える振る舞いの変更を引き起こす可能性があっても、 軽微なバグの修正は、 このリストには入れません。

Git プロジェクトは、 古いバージョンとの下位互換性を意図的に破壊する破壊的なバージョンを不定期にリリースします。 これは、 Git が今後とも有意義であり続け、 安全性や保守性を維持できるようにするために行われます。 通常、 破壊的最新バージョンのリリース頻度は数年ごとに見られます。 過去には以下の主要な破壊的リリースがありました:

  • 2008年8月リリースの Git 1.6.0

  • 2014年5月リリースの Git 2.0

最近では、 Git 2.0 から初めた <メジャー>.<マイナー> 形式のリリース番号を使用しています。 将来のリリースについては、 次の最新リリースを作成するときにリリース番号の <メジャー> をインクリメントする予定です。 Git 2.0 より前は、 リリース番号形式は 1.<major>.<minor> でしたが、これは「通常の」互換性を損なうリリースのために <major> をインクリメントすることを目的としており、 非常に大きな下位互換性破壊を伴う重大な変更のために Git 2.0 への飛躍を予約しておいたものです。

このドキュメントの目的は、 将来の最新リリースで予定されている非推奨(deprecations)を追跡することです。 さらに、 このドキュメントでは、 非推奨にならないものについても追跡します。 これは、 議論が非推奨を支持する場合と、 非推奨を拒否する場合の両方を議論の結果の文書に文書化するために行われます。

項目には、 メーリング・リストでの議論を読まなくても簡単に理解できるような、 記載の変更を、行う理由・行わない理由の明確な概要が含まれている必要があります。 変更する機能の代替手段がある場合は、 それをユーザーに提示すべきです。

すべての項目には、 非推奨が議論された、 関連するメーリング・リストのスレッドへの参照を添付する必要があります。 これらの参照はメッセージ ID を使用しており以下によりアクセスできます

https://lore.kernel.org/git/$message_id/

これにより、 メッセージとそれにまつわる議論を確認します。 このような参照は、 当時、 そのプロジェクトがどのようにして説明された項目に関して合意に達したかを見つけやすくするためにあります。

プロジェクトを取り巻く環境は時間の経過とともに変化するため、 これは随時更新される文書です。 状況が変化した場合、 何かを廃止または変更するという、 以前決定したことをしばしば再検討する必要がある場合があります。 したがって、 このリストにある項目を「解決済みなので、 これを再度取り上げて時間を無駄にする必要はありません」という意味に受け取らないでください。

手順

重大な変更を加えたいことについて話し合い、 そして特定のバージョン境界で重大な変更を行うことを宣言し、 そしてこれらの決定をこの文書に記録することは必要ですが、 それで充分ではありません。 このような変更は多数になることが予想され、 その設計と実装は長期間にわたることが予想されるため、 長い時間をかけて準備し、 そのようなバージョン境界で簡単にデプロイできる必要があります。

この処理手順を支援するために、 破壊的変更はコンパイル時スイッチ WITH_BREAKING_CHANGES で保護されなければなりません。 これを使用してビルドすると、 結果として得られる Git バイナリとそのドキュメントは、 次の大きなバージョン境界に予定されている重大な変更がすでに有効であるかのように振る舞います。 これらの重大な変更を含む進行中のバージョンの Git を実行するための CI ジョブもあります。

Git 3.0

以下のサブセクションでは、 Git 3.0 の破壊的な変更について説明します。 この最新バージョンのリリース予定日は全く決まっていません。

提案されている変更および削除には、 行う「準備ができている(ready)」項目のみが含まれています。 言い換えれば、 これは、 代替機能がすでに実装されている場合に備えて、 変更または置き換えるべき機能の欲しい物リスト(wishlist)であることを想定していません。

変更されるもの

  • 新しいリポジトリのデフォルトのハッシュ関数は、「sha1」から「sha256」に変更されます。 SHA-1 は 2011 年に NIST によって非推奨になり、 現在では FIPS 140-2 および同様の認証で使用しないことが推奨されています。 さらに、 以下のような SHA-1 の暗号特性を弱める実用的な攻撃がありました:

    • SHAppening (2015): 2^57 演算による SHA-1 に対する実用的な攻撃の最初のデモンストレーション。

    • SHAttered (2017): 2^63 演算による 2 つの有効(valid)な PDF ファイルの生成。

    • Birthday-Near-Collision (2019): この攻撃では、2^68 演算による選択プレフィックス攻撃(chosen prefix attacks)が可能になります。

    • Shambles (2020): この攻撃では、2^63 演算による選択プレフィックス攻撃(chosen prefix attacks)が可能になります。

      既知の攻撃に対しては防御策が講じられていますが、 今後の研究により SHA-1 に対するさらに多くの攻撃が発見されることが予想されます。 ハードウェアの機能が成長し続けることと相まって、 SHA-1 を完全に破れるとみなされるのも時間の問題です。 我々はこれに備えたいので、 新しく初期化されるリポジトリのデフォルトのハッシュ・アルゴリズムを「sha256」に変更します。

      この変更の重要な要件は、 エコシステムが「sha256」オブジェクト形式をサポートする準備ができていることです。 これには、 一般的な Git ライブラリやアプリケーションやフォージ(forges)が含まれます。

      「sha1」オブジェクト形式を廃止する予定は、 現時点では何もありません(no plan)。

  • 新規作成されたリポジトリーでの参照(references)のデフォルト・ストレージ形式を、 「files」形式から「reftable」形式に変更します。 「reftable」形式は、 「files」形式に比べて以下の複数の利点を提供します:

    • 「files」形式では、 大文字小文字のみが異なる2つの参照を、 英大文字小文字を区別しない(case-insensitive)ファイルシステム(Windows や macOS で一般的)で保存することは不可能です。 この問題は、 Windows や macOS プラットフォームでよく発生します。 「reftable」バックエンドは参照名をエンコードするためにファイルシステムのパスを使用しないため、 この問題が解消されます。

    • 同様に、 macOS は ユニコード文字を含むパス名を正規化(normalize)します。 これにより、「files」バックエンドでは、 異なるエンコード形式で表現されたユニコード文字を持つ 2 つの名前を保存することができません。 この問題も、「reftable」バックエンドでは発生しません。

    • 「files」バックエンドで参照を削除する場合、 Git は「packed-refs」ファイル全体を書き直す必要があります。 大規模なリポジトリーで参照数が非常に多い場合、 このファイルは簡単に数十メガバイトのサイズになり、 極端なケースではギガバイト単位になることがあります。 一方、「reftable」バックエンドは削除された参照に対して墓石マーカー(tombstone markers)を使用するため、 データ全体を書き直す必要がありません。

    • 「files」バックエンドでのリポジトリーの維持保守(housekeeping)は、 通常、 参照のすべてを一度に再パックする操作を行います。 これはかなり高コストであり、 その結果、 維持保守は、 参照読み込み操作を遅くする緩い参照(loose references)の蓄積数と、 それらの緩い参照を「packed-refs」ファイルに圧縮する間のトレード・オフとなります。 「reftable」バックエンドは、 書き込みごとに幾何学的コンパクト化(geometric compaction)を使用し、 高コストな作業を分散化(amortizes costs)してバックエンドが常に良好にメンテナンスされた状態を保ちます。

    • 複数の参照を一度に書き込む操作は、「files」バックエンドではアトミックではありません。 その結果、 参照トランザクションがディスクにコミットされている最中に参照を読み込むと、 Gitは中間状態を認識してしまう可能性があります。

    • 多くの参照を一度に書き込むのは、「files」バックエンドでは各参照が別々のファイルとして作成されるため遅くなります。「reftable」バックエンドは、「files」バックエンドに比べて桁違いに優れたパフォーマンスを発揮します。

    • 「reftable」バックエンドは、 参照名に対してプレフィックス圧縮を適用したバイナリ形式を使用します。 その結果、「packed-refs」ファイルに比べてストレージ使用量が少なくなります。

      「reftable」バックエンドから即時にな恩恵を受けたいユーザーは、 引き続き「init.defaultRefFormat」設定を手動で設定して「reftable」形式を選択できます。 しかし、 デフォルトは重要であり、 我々は全体のユーザーが新しいバックエンドをデフォルトで使用することで、 プラットフォーム固有の癖が少なく、 より良い体験を得られると考えています。

      この変更の前提条件は、 エコシステムが reftable 形式をサポートする準備ができていることです。 特に重要なのは、JGit や libgit2 やGitoxide などの Git の代替実装がこれをサポートする必要があるということです。

  • 新規作成されたリポジトリーでは、 デフォルトのブランチ名が main になります。 我々は、 デフォルト名が変更されることを、 675704c74dd (init: provide useful advice about init.defaultBranch, 2020-12-11) 以来警告してきました。 この新しい名前は、 多くの大手 Git ホスティング・サービス(Git forges)で新規リポジトリに使用されるデフォルト・ブランチ名と一致します。

  • Git はビルド・プロセスで Rust が必須の要件になります。 Git はすでに Git 2.49 から Rust を採用し始めていますが、 現時点では Rust で書かれたすべての部分はオプションです。 これには以下が含まれます:

    • contrib/ の一部である libgit.a をラップした Rust ラッパーで、 Git 2.49 で導入されました。

    • C と Rust のコードベース間の相互運用性をテストするための、 Rust による代替実装を持つサブシステム。

    • 完全に機能する Git クライアントにとってミッション・クリティカルではない、 新しく書かれた機能。

      これらの変更は、 Git のディストリビューターがビルド・プロセスで Rust が必須になる準備をするための観測気球を意図しています。 Rust の導入には以下の複数のマイルストーンがあります:

      1. 最初に、 Git 2.52 では Meson によって Rust のサポートが自動検出され、 Makefile では無効化されるため、 プロジェクトが初期のインフラを整理できます。

      2. Git 2.53 では、 両方のビルド・システムで Rust のサポートがデフォルトで有効になります。 その結果、 ビルド・ホストで Rust が利用可能でない場合、 デフォルトでビルドが失敗します。 Rust の使用はビルド・フラグで明示的に無効化可能です。

      3. Git 3.0 では、 ビルド・オプションが削除され、 Rust のサポートが必須になります。

      Meson と Makefile ベースのシステムの両方で、 Rust を明示的に有効化するには、 それぞれ meson configure -Drust=enabledmake WITH_RUST=YesPlease を使用できます。

      Git プロジェクトは、 Git 3.0 の直前のバージョンを長期サポート・リリースとして宣言します。 この長期リリースは、 少なくとも 4 リリース・サイクル分の重要なバグ修正と、 6 リリースサイクル分のセキュリティ修正を受け取ります。 ディストリビューターがその長期リリースの寿命をさらに延長する必要がある場合、 Git プロジェクトはメンテナー・シップをディストリビューターに引き継ぎます。 この長期リリースがコミュニティにどのように引き継がれるかについての詳細は、 Git プロジェクトが正式なサポートを終了することを決定した後に議論される予定です。

      Git 3.0 で Rust を必須にする前に、 下流のディストリビューションへの影響を評価します。下流ディストリビューションへの影響が大きいと判断した場合、 この変更を後続のマイナー・リリースに延期する可能性があります。 この評価では、 Rust をオプションのコンポーネントにしておくことがどの程度苦痛であるかという我々自身の経験も考慮されます。

削除されるもの

  • grafts コミットのサポートは、 git-replace(1) に置き換えられて久しいです。 grafts は 置換 refs (replacement refs)よりも劣っています:

    • grafts はローカルのみのメカニズムであり、 リポジトリ間にまたがって共有することができません。

    • grafts は、リポジトリ間でオブジェクトを転送するときに診断が難しい問題を引き起こす可能性があります。

      e650d0643b (文書: mark info/grafts as outdated, 2014-03-05)以降、 grafts メカニズムは時代遅れのモノとしてマークされています。 削除されます。

  • git-pack-redundant(1) コマンドを使用して、 重複したパック・ファイルを削除できます。 このサブ・コマンドは耐え難いほど遅いのですが、 これをパフォーマンスのバグとして誰も報告しない理由は、 このコマンドの利用者が存在しないことが原因であると考えられます。 私達はこのコマンドを削除対象に指定し、 コマンドが実行されるたびに利用者に表示される警告を発する事にしました(c3b58472be (pack-redundant: gauge the usage before proposing its removal, 2020-08-25))。

    これまでのところ、 誰かがまだこのコマンドを使用しているという苦情が 1 件ありましたが、 その苦情によって方針を変更することはありませんでした。 それどころか、 非推奨についてはさらに強化しており、 4406522b76 (pack-redundant: escalate deprecation warning to an error, 2023-03-23) 以降は、 利用者が --i-still-use-this オプションを渡さない限り、 コマンドは終了(die)します。

    その後苦情は寄せられていないため、 このコマンドは最終的には削除される予定です。

  • リモートURLの短縮形を $GIT_COMMON_DIR/branches/$GIT_COMMON_DIR/remotes/ に保存するサポートは、 リモート(remotes)をリポジトリー構成(configuration)に保存する方式によって長らく置き換えられてきました。

    この仕組みは元々 f170e4b39d ([PATCH] fetch/pull: short-hand notation for remote repositories., 2005-07-16) で導入され、 6687f8fea2 ([PATCH] Use .git/remote/origin, not .git/branches/origin., 2005-08-20) で .git/branches/ から .git/remotes/ へ切り替えられました。 このコミットではすでに .git/branches/ ディレクトリの将来的な廃止が言及されており、 a1d4aa7424 (Add repository-layout document., 2005-09-01) 以降でこのレイアウトが非推奨とマークされています。 最終的に .git/remotes/ からも構成ベース(config-based)のリモート(remotes)へ移行し始め、 3d3d282146 (Documentation: Grammar correction, wording fixes and cleanup, 2011-08-23) でこのディレクトリをレガシーとしてマークしました。

    ドキュメントでも述べられているように、 これらのディレクトリは現代のリポジトリーではほとんど使用されておらず、 ほとんどのユーザーはこの仕組みの存在すら知りません。 それぞれほぼ20年と14年にわたって非推奨となっており、 この廃止に対して積極的に不満を訴えるユーザーも認識されていません。 さらに、 .git/branches/ ディレクトリは現在では誤解を招く名前となっており、 branches が参照(references)の文脈でほぼ独占的に使用されるため混乱の原因になる可能性があります。

    よって、 これらの機能は削除されます。

  • name-rev コマンドの --stdin オプションのサポートは、Git 2.40 時代に同義の --annotate-stdin を優先して非推奨(ドキュメントからも非表示)となりました。 Git 3.0 では --stdin のサポートが完全に削除されます。

  • git-whatchanged(1) コマンドは10年以上前に有用性を失っており、 タイピングするキー・ストローク数も大まかな同等物である git log --raw より多くなっています。 私たちはこのコマンドの削除を提案し、 コマンドを --i-still-use-this オプションが指定されない限り動作を拒否するように変更し、 このオプションを使用するユーザーに報告を求めました。

    よって、 このコマンドは削除されます。

  • core.commentString=auto のサポートは非​​推奨となり、 Git 3.0 で削除される予定です。

  • core.preferSymlinkRefs=true のサポートは非推奨となっており、 Git 3.0 で削除されます。 シンボリック参照をシンボリック・リンクとして書き込む方式は、 シンボリック参照のテキスト表現を使用したプレーン・ファイルへ段階的に移行されます。

    シンボリック参照は当初、常にシンボリック・リンクとして保存されていました。 これが 9b143c6e15 (Teach update-ref about a symbolic ref stored in a textfile., 2005-09-25) で変更され、 シンボリック参照をプレーン・ファイルに保存するための新しいテキスト形式の symref が導入されました。 9f0bb90d16 (core.prefersymlinkrefs: use symlinks for .git/HEAD, 2006-05-02) で、 Git プロジェクトはデフォルトをシンボリック・リンクからテキスト形式の symref へ切り替えました。

    シンボリック・リンクからの移行は既に、 ほぼ20年前に行われており、 現在これらを好むべき理由は知られていません。 さらに、 シンボリック・リンクは一部のプラットフォームでサポートされていません。

    注意: なお、 このようなシンボリック・リンクの書き込み側のみが非推奨です。 読み込み側のサポートは現時点では維持されます。

廃止されずに新機能に取って代わられたもの

一部の機能は、 特定の方法で設計を改善することを目的として、 新しい代替品を取得しました。 代替品があるからといって古いやり方が自動的に削除されることを意味するものではありません。 このセクションでは、 より新しい代替品を持つこれらの機能を追跡していきます。

  • git-checkout(1) が提供する機能は、 コマンド git-restore(1) と git-switch(1) のペアでカバーされています。 git-checkout(1) の使用は依然として広く普及しており、 この状態がすぐに変化するとは予想できないため、 3 つのコマンドはすべてそのまま残ります。

    この決定は、 当該コマンドのユーザーがほとんどいないことが判明したときは、 再検討されるかもしれません。