Git 2.56の主な変更点:競合解決の安全性と大規模リポジトリの性能を改善のアイキャッチ画像

Git アップデート情報

Git 2.56の主な変更点:競合解決の安全性と大規模リポジトリの性能を改善

※本記事は広告が含まれる場合があります。

Git 2.56.0が公開されました。今回の更新では、マージ競合の解決後に意図しない変更をステージしにくくする機能に加え、履歴探索やリポジトリの再パックに関する改善が加わっています。

みつた

こんにちは。Git 2.56では、競合を解決したパスだけを安全にステージできるようになり、マージベース探索や大規模リポジトリでの再パックにも改善が加わりました。

この記事のチェックポイント

  • git add --resolvedは、競合していたパスだけを対象にし、競合マーカーが残る場合はステージしない
  • マージベース探索の停止条件が改善され、大規模リポジトリでの処理時間が短縮した事例がある
  • path-walk再パックがビットマップとデルタアイランドに対応したが、既定では有効にならない
  • 実験的なgit historyへのdrop追加など、日常的な操作に関わる更新もある

競合を解決したパスだけをステージする

マージ競合の解決では、ファイルを編集した後、そのパスをステージして解決済みであることをGitに伝えます。一方、git add -uは変更された追跡対象のパスをまとめてステージするため、競合とは無関係なローカル変更まで含める可能性があります。

Git 2.56で追加されたgit add --resolvedは、インデックス上で現在競合しているパスだけを対象にします。ステージする前に、対象の通常ファイルに競合マーカーが残っていないか確認し、見つかった場合は該当パスを報告してインデックスを変更しません。パスを指定して対象を絞ることもできますが、指定した範囲内に競合マーカーが残る通常ファイルがあれば、その範囲のファイルは一つもステージされません。

たとえばrecipe.txtの競合を解決し、notes.txtに無関係な変更がある場合、git add --resolvedで前者をステージし、後者は未ステージのまま残せます。なお、このモードはgit add -uやgit add -Aとは併用できません。

マージベース探索を効率化

Gitはマージや3点ドットの差分表示などで、コミット間の共通祖先であるマージベースを探します。複数のマージベースが存在する場合もあるため、候補を一つ見つけただけでは探索を終えられません。

Git 2.56では、探索待ちのコミットのうち、片側からしか到達していないものの数を追跡するようになりました。新たな合流点が現れないと判断できる段階で探索を止めつつ、すべてのマージベースを返します。

参照元が挙げる一つのモノレポの事例では、処理時間が0.68秒から0.01秒になりました。また、git merge-base --all v4.8 v4.9を使ったLinuxカーネルの事例では、探索ステップが167,441回から3,887回に、処理時間が0.29秒から0.01秒に減っています。これらは個別の計測結果です。

path-walk再パックの利用条件を拡大

path-walkによる再パックは、オブジェクトをツリー内の位置に沿ってたどり、同じパスの異なるバージョンを近くに集めてデルタを探します。参照元のFluent UIリポジトリを使ったベンチマークでは、通常のビットマップ付き再パックで558.5MBだったパックが、--path-walkでは164.4MBになりました。

従来、path-walk再パックは到達可能性ビットマップとデルタアイランドに対応していませんでした。Git 2.56ではこの二つの制約が取り除かれ、ビットマップ用のコミット選択や、デルタアイランドの分離ルールを保つための処理が可能になっています。ただし、path-walk再パックが既定で有効になるわけではありません。

このほかの更新

  • 実験的なgit historyにdropが追加されました。指定したコミットを取り除き、その子孫を親コミット上に再適用します。マージコミットを含む履歴には使えず、ルートコミットやマージコミット自体も削除できません。
  • git branch --delete-mergedに、条件に合うローカルブランチをまとめて削除する形式が追加されました。--dry-runを付ければ、削除せずに対象を確認できます。
  • git bisect runに--reset-when-found[=<where>]が追加されました。原因コミットの発見後、二分探索の状態を片付ける操作を組み合わせられます。
  • git log --followは、親コミットごとにパスを記録するようになりました。親によって異なる名前に変更されたパスを、探索順序に左右されず追跡できます。

Git 2.56は、競合解決時の操作から大規模リポジトリの処理まで、幅広い場面に関わる更新を含んでいます。

情報元・出典:

-Git, アップデート情報