日本語 ▾ トピック ▾ 最新バージョン ▾ git-merge-tree は 2.49.0 で最終更新されました

名前

git-merge-tree - インデックスや作業ツリーに触れずにマージを実行する

概要

git merge-tree [--write-tree] [<options>] <branch1> <branch2>
git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2> (deprecated)

説明

このコマンドには、現代的な --write-tree モードと非推奨の --trivial-merge モードがあります。末尾の DEPRECATED DESCRIPTION セクションを除き、このドキュメントの残りの部分は現代的な --write-tree モードについて説明しています。

マージを実行しますが、新しいコミットは作成せず、作業ツリーやインデックスからの読み込みや書き込みも行いません。

実行されるマージは、「本物の」git-merge[1] と同じ機能を使用します。

  • 個々のファイルに対する3者間コンテンツマージ

  • 名前変更の検出

  • 適切なディレクトリ/ファイル競合の処理

  • 再帰的な祖先統合 (つまり、複数のマージベースがある場合に、それらをマージすることで仮想的なマージベースを作成する)

  • など。

マージが完了すると、新しいトップレベルツリーオブジェクトが作成されます。詳細は以下の OUTPUT を参照してください。

オプション

--stdin

マージするコミットをコマンドラインからではなく標準入力から読み取ります。詳細については、以下の INPUT FORMAT を参照してください。-z を暗示します。

-z

<Conflicted file info> セクションでファイル名を引用符で囲まず、各ファイル名の末尾に改行ではなくNUL文字を付けます。また、メッセージセクションを改行ではなくNUL文字で始めます。詳細については、以下の OUTPUT を参照してください。

--name-only

競合するファイルの情報セクションで、競合するファイルに対して (モード、OID、ステージ、パス) のタプルをリストとして出力する代わりに、競合するファイル名のリストのみを提供します (複数の競合ステージがある場合でも、ファイル名を複数回リストしない)。

--[no-]messages

「Auto-merging <path>」やCONFLICT通知などの情報メッセージを標準出力の末尾に書き込みます。指定されていない場合、マージ競合がある場合はこれらのメッセージを含み、そうでない場合は省略するのがデフォルトです。

--allow-unrelated-histories

指定された2つのブランチが共通の履歴を共有しない場合、merge-tree はデフォルトでエラーになります。このフラグを指定すると、そのチェックを上書きし、マージを続行できます。

--merge-base=<tree-ish>

<branch1> と <branch2> のマージベースを見つける代わりに、マージのマージベースを指定します。複数のベースを指定することは現在サポートされていません。このオプションは --stdin と互換性がありません。

マージベースが直接提供されるため、<branch1> と <branch2> はコミットを指定する必要がなく、ツリーで十分です。

-X<option>
--strategy-option=<option>

マージ戦略固有のオプションをマージ戦略に渡します。詳細は git-merge[1] を参照してください。

出力

マージが成功した場合、git-merge-tree の出力は単に1行です

<OID of toplevel tree>

一方、競合するマージの場合、出力はデフォルトで次の形式になります

<OID of toplevel tree>
<Conflicted file info>
<Informational messages>

これらについては以下で個別に説明します。

ただし、例外があります。--stdin が渡された場合、先頭に余分なセクションがあり、末尾にNUL文字があり、入力の各行に対してすべてのセクションが繰り返されます。したがって、最初のマージが競合し、2番目のマージがクリーンである場合、出力は次の形式になります

<Merge status>
<OID of toplevel tree>
<Conflicted file info>
<Informational messages>
NUL
<Merge status>
<OID of toplevel tree>
NUL

マージステータス

これは、NUL文字が続く整数ステータスです。整数ステータスは

0: merge had conflicts
1: merge was clean

トップレベルツリーのOID

これは、git merge の最後に作業ツリーにチェックアウトされる内容を表すツリーオブジェクトです。競合があった場合、このツリー内のファイルには競合マーカーが埋め込まれている可能性があります。このセクションの後は常に改行 (または -z が渡された場合はNUL) が続きます。

競合ファイル情報

これは、次の形式の行のシーケンスです

<mode> <object> <stage> <filename>

ファイル名は、設定変数 core.quotePath の説明に従って引用符で囲まれます (git-config[1] を参照)。ただし、--name-only オプションが渡された場合、モード、オブジェクト、ステージは省略されます。-z が渡された場合、「行」は改行文字ではなくNUL文字で終端されます。

情報メッセージ

このセクションでは、通常は競合に関する情報メッセージを提供します。このセクションの形式は、-z が渡されるかどうかによって大きく異なります。

-z が渡された場合

出力形式は、0個以上の競合情報レコードであり、それぞれ次の形式です

<list-of-paths><conflict-type>NUL<conflict-message>NUL

ここで <list-of-paths> は次の形式です

<number-of-paths>NUL<path1>NUL<path2>NUL...<pathN>NUL

そして、<conflict-message> の中の競合または情報メッセージによって影響を受けるパス (またはブランチ名) を含みます。また、<conflict-type> は、次のような競合のタイプを説明する安定した文字列です

  • 「自動マージ」

  • 「競合 (名前変更/削除)」

  • 「競合 (サブモジュールにマージベースがない)」

  • 「競合 (バイナリ)」

そして <conflict-message> は、競合に関するより詳細なメッセージであり、多くの場合 (常にではありませんが) <stable-short-type-description> が埋め込まれています。これらの文字列は、将来のGitバージョンで変更される可能性があります。いくつかの例

  • 「<file> を自動マージ中」

  • 「競合 (名前変更/削除): <oldfile> が名前変更されました…​しかし…​で削除されました」

  • 「サブモジュール <submodule> のマージに失敗しました (マージベースなし)」

  • 「警告: バイナリファイルをマージできません: <filename>」

-z が渡されない場合

このセクションは、前のセクションから区切るために空白行で始まり、その後、前のセクションからの <conflict-message> 情報のみを含みます (改行で区切られます)。これらはスクリプトで解析すべきではない非安定な文字列であり、人間が読むためだけのものである。また、<conflict-message> 文字列は通常、埋め込み改行を含みませんが、場合によっては含まれることに注意してください。(ただし、自由形式のメッセージにはNUL文字が埋め込まれることはありません)。したがって、この情報ブロック全体は、すべての競合メッセージの集合体として人間が読むことを意図しています。

終了ステータス

成功し、競合のないマージの場合、終了ステータスは0です。マージに競合がある場合、終了ステータスは1です。何らかのエラーのためにマージが完了 (または開始) できない場合、終了ステータスは0または1以外の値になります (そして出力は未指定です)。--stdin が渡された場合、成功したマージと競合したマージの両方で戻りステータスは0になり、要求されたすべてのマージを完了できない場合は0または1以外の値になります。

使用上の注意

このコマンドは、git-hash-object[1]git-mktree[1]git-commit-tree[1]git-write-tree[1]git-update-ref[1]git-mktag[1] と同様の低レベルのプラミングとして意図されています。したがって、一連のステップの一部として使用できます。

vi message.txt
BRANCH1=refs/heads/test
BRANCH2=main
NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2) || {
    echo "There were conflicts..." 1>&2
    exit 1
}
NEWCOMMIT=$(git commit-tree $NEWTREE -F message.txt \
    -p $BRANCH1 -p $BRANCH2)
git update-ref $BRANCH1 $NEWCOMMIT

終了ステータスがゼロ以外の場合、このシーケンスの NEWTREE はツリーだけでなく、はるかに多くの出力を含むことに注意してください。

競合の場合、出力には git-merge[1] で得られるものと同じ情報が含まれます。

入力形式

git merge-tree --stdin の入力形式は完全にテキストベースです。各行は次の形式です

[<base-commit> -- ]<branch1> <branch2>

1行が -- で区切られている場合、区切り文字の前の文字列はマージのマージベースを指定するために使用され、区切り文字の後の文字列はマージされるブランチを記述します。

避けるべき間違い

競合するファイルを見つけようと結果のトップレベルツリーを調べてはなりません。代わりに Conflicted file info セクションを解析してください。大規模なリポジトリでツリー全体を解析するのは非常に遅いだけでなく、競合マーカーで表現できない多数の種類の競合があります (変更/削除、モード競合、両側で変更されたバイナリファイル、ファイル/ディレクトリ競合、様々な名前変更競合の組み合わせなど)。

空の Conflicted file info リストをクリーンなマージとして解釈してはなりません。終了ステータスを確認してください。個々のファイルが競合していなくてもマージに競合がある場合があります (このカテゴリに分類されるディレクトリの名前変更競合がいくつかあり、将来的には他のものも追加される可能性があります)。

Conflicted file info リストから競合の種類を推測したり、ユーザーに推測させたりしてはなりません。そこにある情報では不十分です。例: 名前変更/名前変更(1to2) 競合 (両側が同じファイルを異なる方法で名前変更した) は、3つの異なるファイルがより高次のステージを持つことになります (ただし、それぞれ1つの高次ステージのみです)。どの3つのファイルが関連しているかを判断する方法はありません (Informational messages セクション以外には)。ファイル/ディレクトリ競合も、正確に1つの高次ステージを持つファイルを生成します。ディレクトリの名前変更に関与している可能性のある競合 ("merge.directoryRenames" が設定されていないか "conflicts" に設定されている場合) も、正確に1つの高次ステージを持つファイルを生成します。すべての場合において、Informational messages セクションには必要な情報がありますが、機械による解析は意図されていません。

Conflicted file info の各パスと、Informational messages の論理競合が1対1のマッピングであると仮定してはなりません。また、1対多のマッピングや多対1のマッピングがあるとも仮定してはなりません。多対多のマッピングが存在し、各パスが1つのマージ内で複数の論理競合タイプを持つことができ、各論理競合タイプが複数のパスに影響を与える可能性があることを意味します。

Informational messages セクションにリストされているすべてのファイル名が競合していたと仮定してはなりません。「Auto-merging <file>」のように、競合のないファイルに対してもメッセージが含まれる場合があります。

Conflicted file info からOIDを取得し、それらを再マージしてユーザーに競合を提示することは避けてください。これにより情報が失われます。代わりに、トップレベルツリーのOID 内で見つかったファイルのバージョンを検索し、それを表示してください。特に、後者には、マージされている元のブランチ/コミットと、名前変更が関係している場合は元のファイル名で注釈が付けられた競合マーカーが含まれます。再マージ時に競合マーカーの注釈に元のブランチ/コミットを含めることはできますが、元のファイル名は Conflicted file info からは利用できないため、ユーザーが競合を解決するのに役立つ情報が失われることになります。

非推奨の説明

DESCRIPTION に従い、このドキュメントの他の部分とは異なり、このセクションは非推奨の --trivial-merge モードについて説明しています。

オプションの --trivial-merge 以外に、このモードはオプションを受け入れません。

このモードは3つの tree-ish を読み込み、単純なマージ結果と競合するステージをセミ差分形式で標準出力に出力します。これは高レベルのスクリプトが結果を消費し、インデックスにマージし直すために設計されたため、<branch1> に一致するエントリは省略されます。この2番目の形式の結果は、3方向の git read-tree -m が行うことと似ていますが、結果をインデックスに保存する代わりに、コマンドはエントリを標準出力に出力します。

この形式は適用範囲が限られているだけでなく (単純なマージは個々のファイルのコンテンツマージ、名前変更検出、適切なディレクトリ/ファイル競合処理などを扱えません)、出力形式も扱いにくく、成功したマージであっても最初の形式よりも一般的にパフォーマンスが劣ります (特に大規模なリポジトリで作業する場合)。

GIT

git[1] スイートの一部

scroll-to-top