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

名称

git-rebase - コミットを別のベースの先端に再適用する

概要

git rebase [-i | --interactive] [<options>] [--exec <cmd>]
	[--onto <newbase> | --keep-base] [<upstream> [<branch>]]
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]
	--root [<branch>]
git rebase (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)

説明

<branch>が指定された場合、git rebaseは他の操作を行う前に自動的にgit switch <branch>を実行します。指定されない場合は、現在のブランチにとどまります。

<upstream>が指定されていない場合、branch.<name>.remoteおよびbranch.<name>.mergeオプションで設定されたアップストリームが使用され(詳細はgit-config[1]を参照)、--fork-pointオプションが仮定されます。現在どのブランチにもいない場合、または現在のブランチに設定されたアップストリームがない場合、リベースは中断されます。

現在のブランチで行われたコミットのうち、<upstream>にはない変更はすべて一時領域に保存されます。これは、git log <upstream>..HEADによって表示されるのと同じコミットの集合です。あるいは、--fork-pointが有効な場合はgit log 'fork_point'..HEAD--fork-pointに関する記述を以下参照)、--rootオプションが指定されている場合はgit log HEADによって表示されるコミットの集合です。

--ontoオプションが指定された場合、現在のブランチは<upstream>または<newbase>にリセットされます。これはgit reset --hard <upstream>(または<newbase>)と全く同じ効果があります。ORIG_HEADはリセット前のブランチの先端を指すように設定されます。

注記
リベース中にその擬似参照を書き込む他のコマンド(例: git reset)が使用された場合、リベースの終了時にORIG_HEADが以前のブランチの先端を指しているとは限りません。しかし、以前のブランチの先端は、現在のブランチの参照ログ(すなわち@{1}gitrevisions[7]を参照)を使用してアクセス可能です。

以前に一時領域に保存されたコミットは、順序通りに1つずつ現在のブランチに再適用されます。HEAD内のコミットで、HEAD..<upstream>内のコミットと同じテキスト変更を導入するものは省略されることに注意してください(つまり、異なるコミットメッセージやタイムスタンプで既にアップストリームに受け入れられたパッチはスキップされます)。

マージの失敗により、このプロセスが完全に自動的に行われない可能性があります。その場合、マージの失敗を解決し、git rebase --continueを実行する必要があります。別のオプションとして、マージの失敗を引き起こしたコミットをgit rebase --skipでバイパスすることもできます。元の<branch>をチェックアウトし、.git/rebase-apply作業ファイルを削除するには、代わりにgit rebase --abortコマンドを使用します。

以下の履歴が存在し、現在のブランチが"topic"であると仮定します。

          A---B---C topic
         /
    D---E---F---G master

この時点から、以下のいずれかのコマンドの結果は

git rebase master
git rebase master topic

次のようになります。

                  A'--B'--C' topic
                 /
    D---E---F---G master

注: 後者の形式は、git checkout topicに続いてgit rebase masterを実行する単なる省略形です。リベースが終了すると、topicがチェックアウトされたブランチのままになります。

もしアップストリームブランチに、あなたが既に行った変更(例えば、パッチをメールで送信し、それがアップストリームに適用された場合など)が含まれている場合、そのコミットはスキップされ、警告が発行されます(mergeバックエンドが使用されている場合)。例えば、以下の履歴(A'Aが同じ変更セットを導入するが、コミッター情報が異なる)でgit rebase masterを実行すると、

          A---B---C topic
         /
    D---E---A'---F master

次のようになります。

                   B'---C' topic
                  /
    D---E---A'---F master

rebase --ontoを使用して、あるブランチに基づいたトピックブランチを別のブランチに移植し、そのトピックブランチが後者のブランチからフォークされたように見せかける方法を以下に示します。

まず、あなたのtopicがブランチnextに基づいていると仮定しましょう。例えば、topicで開発された機能がnextにある何らかの機能に依存している場合です。

    o---o---o---o---o  master
         \
          o---o---o---o---o  next
                           \
                            o---o---o  topic

topicをブランチmasterからフォークさせたいとします。例えば、topicが依存する機能がより安定したmasterブランチにマージされたからです。私たちのツリーを次のようにしたいと考えます。

    o---o---o---o---o  master
        |            \
        |             o'--o'--o'  topic
         \
          o---o---o---o---o  next

以下のコマンドを使用することで、これを実現できます。

git rebase --onto master next topic

--ontoオプションの別の例は、ブランチの一部をリベースすることです。次のような状況の場合、

                            H---I---J topicB
                           /
                  E---F---G  topicA
                 /
    A---B---C---D  master

そのコマンドは

git rebase --onto master topicA topicB

次のようになります。

                 H'--I'--J'  topicB
                /
                | E---F---G  topicA
                |/
    A---B---C---D  master

これは、topicBがtopicAに依存しない場合に役立ちます。

リベースを使ってコミットの範囲を削除することも可能です。次のような状況の場合、

    E---F---G---H---I---J  topicA

そのコマンドは

git rebase --onto topicA~5 topicA~3 topicA

コミットFとGが削除されることになります。

    E---H'---I'---J'  topicA

これは、FとGが何らかの欠陥があったり、topicAの一部であるべきでない場合に役立ちます。--ontoの引数と<upstream>パラメータは、任意の有効なcommit-ishであることに注意してください。

コンフリクトが発生した場合、git rebaseは最初の問題のあるコミットで停止し、ツリーにコンフリクトマーカーを残します。git diffを使用してマーカー(<<<<<<)を見つけ、編集してコンフリクトを解決できます。編集する各ファイルについて、Gitにコンフリクトが解決されたことを伝える必要がありますが、これは通常、次のように行われます。

git add <filename>

手動でコンフリクトを解決し、希望する解決策でインデックスを更新した後、次のようにしてリベースプロセスを続行できます。

git rebase --continue

あるいは、git rebaseを次で元に戻すこともできます。

git rebase --abort

モードオプション

このセクションのオプションは、互いを含め、他のオプションと併用することはできません。

--continue

マージコンフリクトを解決した後、リベース処理を再開します。

--skip

現在のパッチをスキップしてリベース処理を再開します。

--abort

リベース操作を中止し、HEADを元のブランチにリセットします。リベース操作開始時に<branch>が指定されていた場合、HEAD<branch>にリセットされます。それ以外の場合、HEADはリベース操作開始時の状態にリセットされます。

--quit

リベース操作を中止しますが、HEADは元のブランチにリセットされません。その結果、インデックスと作業ツリーも変更されません。--autostashを使用して一時的なスタッシュエントリが作成された場合、それはスタッシュリストに保存されます。

--edit-todo

対話型リベース中にTODOリストを編集します。

--show-current-patch

対話型リベース中、またはコンフリクトによりリベースが停止したときに、現在のパッチを表示します。これはgit show REBASE_HEADと同等です。

オプション

--onto <newbase>

新しいコミットを作成する開始点。--ontoオプションが指定されていない場合、開始点は<upstream>です。既存のブランチ名だけでなく、任意の有効なコミットを指定できます。

特別なケースとして、AとBのマージベースがちょうど1つだけ存在する場合、「A...B」をそのショートカットとして使用できます。AとBのうち最大1つを省略でき、その場合はHEADがデフォルトとなります。

--keep-base

新しいコミットを作成する開始点を、<upstream><branch>のマージベースに設定します。git rebase --keep-base <upstream> <branch>の実行は、git rebase --reapply-cherry-picks --no-fork-point --onto <upstream>...<branch> <upstream> <branch>の実行と同等です。

このオプションは、アップストリームブランチの上に機能を開発している場合に役立ちます。機能の作業中に、アップストリームブランチが進展する可能性があり、その場合、アップストリームの上にリベースし続けるのではなく、ベースコミットをそのまま保持することが最善のアイデアではないかもしれません。ベースコミットが変更されないため、このオプションはコミットの損失を避けるために--reapply-cherry-picksを暗黙的に指定します。

このオプションも--fork-point<upstream><branch>間のマージベースを見つけますが、このオプションはマージベースを新しいコミットが作成される開始点として使用し、一方--fork-pointはマージベースをリベースされるコミットの集合を決定するために使用します。

以下の「非互換オプション」も参照してください。

<upstream>

比較対象のアップストリームブランチ。既存のブランチ名だけでなく、任意の有効なコミットを指定できます。デフォルトは現在のブランチに設定されているアップストリームです。

<branch>

作業ブランチ。デフォルトはHEADです。

--apply

適用戦略を使用してリベースします(内部的にgit-amを呼び出します)。マージバックエンドがapplyバックエンドのすべての機能を処理するようになれば、このオプションは将来的にno-opになる可能性があります。

以下の「非互換オプション」も参照してください。

--empty=(drop|keep|stop)

元は空でなく、どのアップストリームコミットのクリーンなチェリーピックでもないが、リベース後に空になるコミット(既にアップストリームにある変更のサブセットを含むため)をどのように処理するか。

drop

コミットは破棄されます。これがデフォルトの動作です。

keep

コミットは保持されます。このオプションは、-i/--interactiveも指定されていない限り、--execが指定された場合に暗黙的に適用されます。

stop
ask

コミットが適用されるとリベースは停止し、そのコミットを破棄するか、ファイルをさらに編集するか、または空の変更のみをコミットするかを選択できます。このオプションは、-i/--interactiveが指定された場合に暗黙的に適用されます。askstopの非推奨の同義語です。

元々空のコミットは保持され(--no-keep-emptyが指定されていない限り)、クリーンなチェリーピックであるコミット(git log --cherry-mark ...で判断されるもの)は、予備的なステップとして検出され、破棄されます(--reapply-cherry-picksまたは--keep-baseが渡されていない限り)。

以下の「非互換オプション」も参照してください。

--no-keep-empty
--keep-empty

リベース前に空で始まるコミット(つまり、親から何も変更しないコミット)を結果に残しません。デフォルトでは、空で始まるコミットは保持されます。これは、そのようなコミットを作成するにはgit commit--allow-emptyオーバーライドフラグを渡す必要があり、ユーザーが非常に意図的にそのようなコミットを作成し、それを保持したいと考えていることを意味するからです。

このフラグの使用は稀であると予想されます。なぜなら、対話型リベースを開始し、不要なコミットに対応する行を削除するだけで、空で始まるコミットを取り除くことができるからです。このフラグは、外部ツールが多数の空コミットを生成し、それらすべてを削除したい場合のような便利なショートカットとして存在します。

空で始まらないがリベース後に空になるコミットについては、--emptyフラグを参照してください。

以下の「非互換オプション」も参照してください。

--reapply-cherry-picks
--no-reapply-cherry-picks

すべてのクリーンなチェリーピックを、事前に破棄するのではなく再適用します。(もしこれらのコミットがリベース後に空になった場合、つまり既にアップストリームにある変更のサブセットを含む場合、それらの挙動は--emptyフラグによって制御されます。)

--keep-baseがない場合(または--no-reapply-cherry-picksが指定されている場合)、これらのコミットは自動的に破棄されます。これによりすべてのアップストリームコミットを読み込む必要があるため、読み込むべきアップストリームコミットが多数あるリポジトリではコストが高くなる可能性があります。mergeバックエンドを使用する場合、破棄された各コミットに対して警告が発行されます(--quietが指定されていない限り)。また、advice.skippedCherryPicksがfalseに設定されていない限り、アドバイスも発行されます(git-config[1]を参照)。

--reapply-cherry-picksを使用すると、リベースはすべてのアップストリームコミットの読み込みを放棄でき、パフォーマンスが向上する可能性があります。

以下の「非互換オプション」も参照してください。

--allow-empty-message

何もしません。空のメッセージを持つコミットのリベースは以前は失敗していましたが、このオプションはその動作を上書きし、空のメッセージを持つコミットのリベースを許可しました。現在では、空のメッセージを持つコミットがリベースを停止させることはありません。

以下の「非互換オプション」も参照してください。

-m
--merge

マージ戦略を使用してリベースします(デフォルト)。

リベースマージは、作業ブランチからの各コミットを<upstream>ブランチの上に一つずつ再生することで機能します。このため、マージコンフリクトが発生した場合、oursとして報告される側は、<upstream>から始まるこれまでのリベースされたシリーズであり、theirsは作業ブランチです。言い換えれば、両者が入れ替わります。

以下の「非互換オプション」も参照してください。

-s <strategy>
--strategy=<strategy>

デフォルトのortではなく、指定されたマージ戦略を使用します。これは--mergeを意味します。

git rebaseは、与えられた戦略を使用して作業ブランチから<upstream>ブランチのトップに各コミットを再生するため、ours戦略を使用すると、<branch>からのすべてのパッチが単純に空になり、ほとんど意味がありません。

以下の「非互換オプション」も参照してください。

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

<strategy-option>をマージ戦略に渡します。これは--mergeを意味し、戦略が指定されていない場合は-s ortを意味します。-mオプションで述べたように、ourstheirsが逆になることに注意してください。

以下の「非互換オプション」も参照してください。

--rerere-autoupdate
--no-rerere-autoupdate

rerereメカニズムが現在のコンフリクトに対する記録された解決策を再利用して作業ツリー内のファイルを更新した後、解決結果でインデックスも更新することを許可します。--no-rerere-autoupdateは、別途git addで結果をインデックスにコミットする前に、rerereが何をしたかを再確認し、潜在的な誤ったマージを捕捉する良い方法です。

-S[<keyid>]
--gpg-sign[=<keyid>]
--no-gpg-sign

コミットをGPG署名します。keyid引数はオプションで、デフォルトはコミッターの識別情報です。指定する場合は、オプションにスペースなしで付加する必要があります。--no-gpg-signは、commit.gpgSign設定変数と以前の--gpg-signの両方を無効にするのに役立ちます。

-q
--quiet

静かに実行します。--no-statを暗黙的に指定します。

-v
--verbose

詳細に実行します。--statを暗黙的に指定します。

--stat

前回のリベース以降、アップストリームで何が変更されたかのdiffstatを表示します。diffstatは設定オプションrebase.statによっても制御されます。

-n
--no-stat

リベース処理の一部としてdiffstatを表示しません。

--no-verify

このオプションはpre-rebaseフックをバイパスします。githooks[5]も参照してください。

--verify

pre-rebaseフックの実行を許可します。これがデフォルトです。このオプションは--no-verifyを上書きするために使用できます。githooks[5]も参照してください。

-C<n>

各変更の前後に、少なくとも<n>行の周囲のコンテキストが一致することを確認します。周囲のコンテキスト行がそれより少ない場合は、すべて一致する必要があります。デフォルトでは、コンテキストは一切無視されません。--applyを暗黙的に指定します。

以下の「非互換オプション」も参照してください。

--no-ff
--force-rebase
-f

変更されていないコミットをファストフォワードする代わりに、リベースされたすべてのコミットを個別に再生します。これにより、リベースされたブランチの全履歴が新しいコミットで構成されるようになります。

このオプションは、トピックブランチのマージを元に戻した後、役立つ場合があります。このオプションは、新しいコミットでトピックブランチを再作成するため、「revertのrevert」を必要とせずに正常に再マージできます(詳細はrevert-a-faulty-merge How-Toを参照)。

--fork-point
--no-fork-point

<branch>によって導入されたコミットを計算する際に、<upstream><branch>の間でより良い共通の祖先を見つけるためにreflogを使用します。

--fork-pointがアクティブな場合、リベースするコミットの集合を計算するために、<upstream>の代わりにfork_pointが使用されます。ここでfork_pointgit merge-base --fork-point <upstream> <branch>コマンドの結果です(git-merge-base[1]を参照)。もしfork_pointが空になった場合、<upstream>がフォールバックとして使用されます。

コマンドラインで<upstream>または--keep-baseが与えられた場合、デフォルトは--no-fork-pointとなり、それ以外の場合は--fork-pointがデフォルトとなります。また、git-config[1]rebase.forkpointも参照してください。

もしあなたのブランチが<upstream>に基づいていて、<upstream>が巻き戻され、あなたのブランチに破棄されたコミットが含まれている場合、このオプションは--keep-baseと共に使用することで、それらのコミットをあなたのブランチから破棄できます。

以下の「非互換オプション」も参照してください。

--ignore-whitespace

差異を調整しようとするときに、ホワイトスペースの違いを無視します。現在、各バックエンドはこの動作の近似を実装しています。

apply バックエンド

パッチを適用する際、コンテキスト行のホワイトスペースの変更を無視します。残念ながら、これはパッチによって置き換えられる「古い」行が既存のファイルとホワイトスペースのみで異なる場合、パッチの適用が成功する代わりにマージコンフリクトが発生することを意味します。

merge バックエンド

マージ時、ホワイトスペースのみの変更を含む行を未変更として扱います。残念ながら、これは、ホワイトスペースのみを変更する意図があったパッチチャンクが、たとえ相手側に競合する変更がなかったとしても、破棄されることを意味します。

--whitespace=<option>

このフラグは、パッチを適用するgit applyプログラム(git-apply[1]を参照)に渡されます。--applyを暗黙的に指定します。

以下の「非互換オプション」も参照してください。

--committer-date-is-author-date

コミッター日付として現在の時刻を使用する代わりに、リベース中のコミットの作者日付をコミッター日付として使用します。このオプションは--force-rebaseを暗黙的に指定します。

--ignore-date
--reset-author-date

元のコミットの作者日付を使用する代わりに、現在の時刻をリベースされたコミットの作者日付として使用します。このオプションは--force-rebaseを暗黙的に指定します。

以下の「非互換オプション」も参照してください。

--signoff

リベースされたすべてのコミットにSigned-off-byトレーラーを追加します。--interactiveが指定されている場合、pick、edit、またはrewordとマークされたコミットのみにトレーラーが追加されることに注意してください。

以下の「非互換オプション」も参照してください。

-i
--interactive

リベースされる予定のコミットのリストを作成します。リベースの前にユーザーがそのリストを編集できるようにします。このモードはコミットを分割するためにも使用できます(以下の「コミットの分割」を参照)。

コミットリストの形式は、設定オプションrebase.instructionFormatを設定することで変更できます。カスタマイズされた指示形式には、自動的にコミットハッシュが形式の先頭に追加されます。

以下の「非互換オプション」も参照してください。

-r
--rebase-merges[=(rebase-cousins|no-rebase-cousins)]
--no-rebase-merges

デフォルトでは、リベースは単にTODOリストからマージコミットを削除し、リベースされたコミットを単一のリニアなブランチに配置します。--rebase-mergesを使用すると、リベースは代わりにマージコミットを再作成することで、リベースされるコミット内のブランチ構造を保持しようとします。これらのマージコミットで解決されたマージコンフリクトや手動での修正は、手動で解決/再適用する必要があります。--no-rebase-mergesは、rebase.rebaseMerges設定オプションと以前の--rebase-mergesの両方を無効にするために使用できます。

マージをリベースする場合、rebase-cousinsno-rebase-cousinsの2つのモードがあります。モードが指定されていない場合、デフォルトはno-rebase-cousinsです。no-rebase-cousinsモードでは、<upstream>を直接の祖先に持たないコミットは元の分岐点を保持します。つまり、git-log[1]--ancestry-pathオプションによって除外されるコミットは、デフォルトで元の祖先を保持します。rebase-cousinsモードでは、そのようなコミットは代わりに<upstream>(または指定されていれば<onto>)にリベースされます。

現在、マージコミットを再作成できるのはortマージ戦略を使用する場合のみです。異なるマージ戦略は、明示的なexec git merge -s <strategy> [...]コマンドを介してのみ使用できます。

以下の「マージのリベース」および「非互換オプション」も参照してください。

-x <cmd>
--exec <cmd>

最終履歴でコミットを作成する各行の後に「exec <cmd>」を追加します。<cmd>は1つ以上のシェルコマンドとして解釈されます。失敗したコマンドはすべて、終了コード1でリベースを中断します。

複数のコマンドで--execのインスタンスを1つ使用するか、

git rebase -i --exec "cmd1 && cmd2 && ..."

あるいは複数の--execを指定することで、複数のコマンドを実行できます。

git rebase -i --exec "cmd1" --exec "cmd2" --exec ...

--autosquashが使用された場合、中間コミットにはexec行が追加されず、各squash/fixupシリーズの最後にのみ表示されます。

これは内部的に--interactiveの仕組みを使用しますが、明示的な--interactiveなしで実行できます。

以下の「非互換オプション」も参照してください。

--root

<upstream>で制限する代わりに、<branch>から到達可能なすべてのコミットをリベースします。これにより、ブランチ上のルートコミットをリベースできます。

以下の「非互換オプション」も参照してください。

--autosquash
--no-autosquash

特別にフォーマットされたメッセージを持つコミットを、リベース中の前のコミットに自動的にスカッシュします。コミットメッセージが「squash! 」、「fixup! 」または「amend! 」で始まる場合、タイトルの残りがコミット指定子として解釈され、前のコミットのタイトルまたはハッシュと一致すれば、そのコミットと一致します。完全に一致するコミットがない場合、コミットタイトルの開始部分と指定子の一致が考慮されます。

リベースのTODOリストでは、squash、fixup、amendコミットのアクションがそれぞれpickからsquashfixup、またはfixup -Cに変更され、それらが変更するコミットの直後に移動されます。--interactiveオプションを使用して、続行する前にTODOリストを確認および編集できます。

squashマーカー付きコミットを作成する推奨される方法は、git-commit[1]--squash--fixup--fixup=amend:、または--fixup=reword:オプションを使用することです。これらはターゲットコミットを引数として受け取り、それから新しいコミットのタイトルを自動的に入力します。

設定変数rebase.autoSquashをtrueに設定すると、対話型リベースで自動スカッシュがデフォルトで有効になります。--no-autosquashオプションを使用してこの設定を上書きできます。

以下の「非互換オプション」も参照してください。

--autostash
--no-autostash

操作開始前に一時的なスタッシュエントリを自動的に作成し、操作終了後にそれを適用します。これにより、ダーティな作業ツリーでリベースを実行できます。ただし、注意して使用してください。リベース成功後の最終的なスタッシュ適用は、軽視できない競合を引き起こす可能性があります。

--reschedule-failed-exec
--no-reschedule-failed-exec

失敗したexecコマンドを自動的に再スケジュールします。これは対話型モード(または--execオプションが指定された場合)でのみ意味があります。

このオプションはリベースが開始されると一度適用されます。そして、最初にgit rebaseに提供されたコマンドラインオプション、rebase.rescheduleFailedExec設定(git-config[1]または以下の「設定」を参照)、またはデフォルトのfalseの順序に基づいて、リベース全体を通して保持されます。

リベース全体でこのオプションを記録するのは便利な機能です。そうしないと、git rebase --continueが呼び出されたときにrebase.rescheduleFailedExec=true設定が存在すると、開始時の明示的な--no-reschedule-failed-execが上書きされてしまいます。現在、git rebase --continue--[no-]reschedule-failed-execを渡すことはできません。

--update-refs
--no-update-refs

リベース中のコミットを指すブランチを自動的に強制更新します。作業ツリーでチェックアウトされているブランチは、この方法では更新されません。

設定変数rebase.updateRefsが設定されている場合、このオプションを使用してこの設定を上書きし、無効にできます。

以下の「非互換オプション」も参照してください。

非互換オプション

以下のオプション

  • --apply

  • --whitespace

  • -C

は以下のオプションと非互換です。

  • --merge

  • --strategy

  • --strategy-option

  • --autosquash

  • --rebase-merges

  • --interactive

  • --exec

  • --no-keep-empty

  • --empty=

  • --keep-baseなしで使用される場合の--[no-]reapply-cherry-picks

  • --update-refs

  • --ontoなしで使用される場合の--root

さらに、以下のオプションの組み合わせは非互換です。

  • --keep-base と --onto

  • --keep-base と --root

  • --fork-point と --root

動作の相違点

git rebaseには、applymergeの2つの主要なバックエンドがあります。(applyバックエンドは以前はamバックエンドとして知られていましたが、動詞のように見えて名詞ではないため混乱を招きました。また、mergeバックエンドは以前はインタラクティブバックエンドとして知られていましたが、現在では非インタラクティブなケースでも使用されます。どちらもそれぞれの基盤となる低レベル機能に基づいて改名されました。)これら2つのバックエンドの動作にはいくつかの微妙な違いがあります。

空のコミット

applyバックエンドは残念ながら、意図的に空のコミット(つまり、元々空で始まったコミット)を破棄します。これらは実際には稀です。また、空になったコミットも破棄し、この動作を制御するオプションはありません。

mergeバックエンドは、デフォルトで意図的に空のコミットを保持します(ただし、-iを指定するとTODOリストエディタで空としてマークされるか、--no-keep-emptyで自動的に破棄できます)。

applyバックエンドと同様に、mergeバックエンドはデフォルトで空になったコミットを破棄しますが、-i/--interactiveが指定されている場合(この場合、停止してユーザーに何をすべきか尋ねます)は例外です。mergeバックエンドには、空になったコミットの処理動作を変更するための--empty=(drop|keep|stop)オプションもあります。

ディレクトリ名の変更検出

正確なツリー情報(パッチに含まれる限られた情報から偽の祖先を構築することに起因)の不足のため、applyバックエンドではディレクトリ名の変更検出が無効になっています。ディレクトリ名の変更検出が無効であるということは、履歴の一方がディレクトリ名を変更し、もう一方が古いディレクトリに新しいファイルを追加した場合、リベース時にこれらのファイルを新しいディレクトリに移動したい可能性があるという警告なしに、新しいファイルが古いディレクトリに残されることを意味します。

mergeバックエンドではディレクトリ名の変更検出が機能し、そのような場合に警告を提供します。

コンテキスト

applyバックエンドは、一連のパッチを作成し(内部でformat-patchを呼び出す)、その後、そのパッチを順番に適用する(内部でamを呼び出す)ことで機能します。パッチは複数のハンクで構成されており、それぞれに行番号、コンテキスト領域、および実際の変更が含まれています。行番号は、相手側がファイルのより早い段階で行を挿入または削除している可能性が高いため、何らかのオフセットを考慮する必要があります。コンテキスト領域は、変更を正しい行に適用するために行番号を調整する方法を見つけるのに役立つことを意図しています。しかし、コードの複数の領域が同じ周囲のコンテキスト行を持っている場合、間違った行が選択される可能性があります。これにより、衝突が報告されることなくコミットが誤って再適用されるという実世界のケースがあります。diff.contextをより大きな値に設定することで、そのような種類の問題を防止できる可能性がありますが、偽の衝突の可能性は高まります(適用するためにより多くのコンテキスト行の一致が必要となるため)。

mergeバックエンドは、関連する各ファイルの完全なコピーを扱うため、これらの種類の問題から切り離されます。

コンフリクトマーカーのラベリング

コンテンツの競合がある場合、マージ機構は各側の競合マーカーにコンテンツの出所となったコミットを注釈付けしようとします。applyバックエンドは、リベースされたコミットとその親に関する元の情報(そして代わりに生成されたパッチの限られた情報に基づいて新しい偽のコミットを生成する)を破棄するため、それらのコミットを識別できません。代わりに、コミットサマリーにフォールバックする必要があります。また、merge.conflictStylediff3またはzdiff3に設定されている場合、applyバックエンドは「構築されたマージベース」を使用してマージベースからのコンテンツをラベル付けするため、マージベースコミットに関する情報は全く提供されません。

mergeバックエンドは、履歴の両側の完全なコミットを扱うため、そのような制限はありません。

フック

applyバックエンドは伝統的にpost-commitフックを呼び出しませんでしたが、mergeバックエンドは呼び出しました。両者ともpost-checkoutフックを呼び出しましたが、mergeバックエンドはその出力を抑制しました。さらに、両バックエンドはリベースの開始点コミットでのみpost-checkoutフックを呼び出し、中間コミットや最終コミットでは呼び出しません。いずれの場合も、これらのフックの呼び出しは設計によるものではなく、実装上の偶然(両バックエンドは元々シェルスクリプトとして実装され、たまたまフックを呼び出すgit checkoutgit commitのような他のコマンドを起動した)によるものでした。どちらのバックエンドも同じ動作をするべきですが、どちらが正しいのか、あるいは正しいものがあるのかは完全には明らかではありません。将来的には、リベースがこれらのフックのいずれかを呼び出すのを停止する可能性が高いです。

中断可能性

applyバックエンドは、タイミングの悪い中断で安全性に問題があります。ユーザーがリベースを中止しようとして誤ったタイミングでCtrl-Cを押した場合、リベースはその後のgit rebase --abortで中断できない状態になる可能性があります。mergeバックエンドは同じ欠点には苦しんでいないようです。(詳細はhttps://lore.kernel.org/git/20200207132152.GC2868@szeder.dev/を参照してください。)

コミットの再編集

リベース中にコンフリクトが発生すると、リベースは停止し、ユーザーに解決を求めます。ユーザーはコンフリクトの解決中に注目すべき変更を行う必要がある場合があるため、コンフリクトが解決され、ユーザーがgit rebase --continueを実行した後、リベースはエディタを開き、コミットメッセージの更新をユーザーに求めるべきです。mergeバックエンドはこれを実行しますが、applyバックエンドは元のコミットメッセージを盲目的に適用します。

その他の相違点

ほとんどの人が重要ではないと考えるであろう、いくつかのさらなる動作上の相違点がありますが、完全性のために言及します。

  • 参照ログ: 両方のバックエンドは参照ログでの変更記述に異なる表現を使用しますが、どちらも「rebase」という単語を使用します。

  • 進捗、情報、およびエラーメッセージ: 両方のバックエンドは、わずかに異なる進捗メッセージと情報メッセージを提供します。また、applyバックエンドはエラーメッセージ(「あなたのファイルは上書きされます…​」など)を標準出力に書き込みますが、mergeバックエンドは標準エラー出力に書き込みます。

  • 状態ディレクトリ: 両方のバックエンドは、.git/以下の異なるディレクトリにその状態を保持します。

マージ戦略

マージ機構(git mergeおよびgit pullコマンド)は、バックエンドのマージ戦略-sオプションで選択できます。一部の戦略は独自のオプションも持つことができ、これらはgit mergegit pull-X<option>引数を与えることで渡すことができます。

ort

これは、1つのブランチをプルまたはマージする際のデフォルトのマージ戦略です。この戦略は、3方向マージアルゴリズムを使用して2つのヘッドのみを解決できます。3方向マージに使用できる共通の祖先が複数ある場合、共通の祖先のマージ済みツリーを作成し、それを3方向マージの参照ツリーとして使用します。Linux 2.6カーネル開発履歴から取得された実際のマージコミットに対するテストにより、誤ったマージを引き起こすことなくマージコンフリクトを減らすことが報告されています。さらに、この戦略は名前変更を伴うマージを検出および処理できます。検出されたコピーは使用しません。このアルゴリズムの名前は頭字語(「Ostensibly Recursive's Twin」)であり、以前のデフォルトアルゴリズムであるrecursiveの代替として書かれたという事実から来ています。

パスがサブモジュールである場合、マージの一方の側で使用されたサブモジュールコミットがマージのもう一方の側で使用されたサブモジュールコミットの子孫である場合、Gitは子孫へのファストフォワードを試みます。それ以外の場合、Gitはこのケースをコンフリクトとして扱い、もし存在すれば、競合するサブモジュールの子孫であるサブモジュールコミットを解決策として提案します。

ort戦略は以下のオプションを取ることができます。

ours

このオプションは、競合するハンクをourバージョンを優先して自動的にクリーンに解決するよう強制します。私たちの側と競合しない他のツリーからの変更は、マージ結果に反映されます。バイナリファイルの場合、内容はすべて私たちの側から取られます。

これは、相手のツリーの内容を全く見ないoursマージ戦略と混同してはなりません。それは相手のツリーが行ったすべてを破棄し、私たちの履歴に起こったすべてのものが含まれていると宣言します。

theirs

これはoursの反対です。oursとは異なり、このマージオプションと混同されるようなtheirsマージ戦略は存在しないことに注意してください。

ignore-space-change
ignore-all-space
ignore-space-at-eol
ignore-cr-at-eol

指定された種類の空白文字の変更を含む行を、3方向マージの目的で未変更として扱います。行への他の変更と混ざった空白文字の変更は無視されません。git-diff[1]-b-w--ignore-space-at-eol、および--ignore-cr-at-eolも参照してください。

  • もし相手のバージョンが行に空白文字の変更のみを導入する場合、私たちのバージョンが使用されます。

  • もし私たちのバージョンが空白文字の変更を導入し、相手のバージョンが実質的な変更を含む場合、相手のバージョンが使用されます。

  • それ以外の場合、マージは通常通り進行します。

renormalize

これは、3方向マージが必要なファイルのすべての3つのステージの仮想チェックアウトとチェックインを実行します。このオプションは、異なるクリーンフィルタまたは行末正規化ルールを持つブランチをマージする際に使用することを意図しています。詳細はgitattributes[5]の「異なるチェックイン/チェックアウト属性を持つブランチのマージ」を参照してください。

no-renormalize

renormalizeオプションを無効にします。これはmerge.renormalize設定変数を上書きします。

find-renames[=<n>]

名前変更検出を有効にし、オプションで類似度しきい値を設定します。これがデフォルトです。これはmerge.renames設定変数を上書きします。git-diff[1]--find-renamesも参照してください。

rename-threshold=<n>

find-renames=<n>の非推奨の同義語。

subtree[=<path>]

このオプションはsubtree戦略のより高度な形式で、マージ時に2つのツリーが互いに一致するようにどのようにシフトすべきかを戦略が推測します。代わりに、指定されたパスが接頭辞として追加(または先頭から削除)され、2つのツリーの形状が一致するようにします。

recursive

これは、3方向マージアルゴリズムを使用して2つのヘッドのみを解決できます。3方向マージに使用できる共通の祖先が複数ある場合、共通の祖先のマージ済みツリーを作成し、それを3方向マージの参照ツリーとして使用します。Linux 2.6カーネル開発履歴から取得された実際のマージコミットに対するテストにより、誤ったマージを引き起こすことなくマージコンフリクトを減らすことが報告されています。さらに、これは名前変更を伴うマージを検出および処理できます。検出されたコピーは使用しません。これはGit v0.99.9kからv2.33.0までの間、2つのヘッドを解決するためのデフォルト戦略でした。

サブモジュールであるパスの場合、ortと同様の注意がこの戦略にも適用されます。

recursive戦略はortと同じオプションを取ります。ただし、ortが無視する(上記に記載されていない)3つの追加オプションがあり、これらはrecursive戦略で潜在的に役立ちます。

patience

diff-algorithm=patienceの非推奨の同義語。

diff-algorithm=[patience|minimal|histogram|myers]

マージ中に異なるdiffアルゴリズムを使用します。これにより、重要でない一致行(異なる関数からのブレースなど)による誤ったマージを回避するのに役立ちます。git-diff[1]--diff-algorithmも参照してください。ortは具体的にdiff-algorithm=histogramを使用しますが、recursiveはデフォルトでdiff.algorithm設定を使用することに注意してください。

no-renames

名前変更検出をオフにします。これはmerge.renames設定変数を上書きします。git-diff[1]--no-renamesも参照してください。

resolve

これは、3方向マージアルゴリズムを使用して、2つのヘッド(つまり、現在のブランチとプル元の別のブランチ)のみを解決できます。クロスオーバーマージの曖昧さを慎重に検出しようとします。名前変更は処理しません。

octopus

これは、2つ以上のヘッドがあるケースを解決しますが、手動解決が必要な複雑なマージを行うことは拒否します。主にトピックブランチのヘッドをまとめるために使用されます。これは、複数のブランチをプルまたはマージする際のデフォルトのマージ戦略です。

ours

これは任意の数のヘッドを解決しますが、マージの結果となるツリーは常に現在のブランチヘッドのものであり、他のすべてのブランチからの変更は事実上無視されます。これはサイドブランチの古い開発履歴を上書きするために使用することを意図しています。これはrecursiveマージ戦略の-Xoursオプションとは異なることに注意してください。

subtree

これは修正されたort戦略です。ツリーAとBをマージする際、BがAのサブツリーに対応する場合、同じレベルでツリーを読み取るのではなく、まずBをAのツリー構造に一致するように調整します。この調整は共通の祖先ツリーにも行われます。

3方向マージを使用する戦略(デフォルトのortを含む)では、両方のブランチで変更が行われた後、片方のブランチでその変更が元に戻された場合、その変更はマージ結果に存在します。一部の人はこの動作を混乱させると感じます。これは、マージを実行する際に個々のコミットではなく、ヘッドとマージベースのみが考慮されるため発生します。したがって、マージアルゴリズムは元に戻された変更を全く変更なしとみなし、代わりに変更されたバージョンを置き換えます。

注釈

共有しているリポジトリでgit rebaseを使用することの意味を理解しておく必要があります。以下の「アップストリームのリベースからの復旧」も参照してください。

リベースが実行される際、存在すれば最初にpre-rebaseフックが実行されます。このフックを使用して健全性チェックを行い、適切でない場合はリベースを拒否できます。例については、テンプレートのpre-rebaseフックスクリプトを参照してください。

完了すると、<branch>が現在のブランチになります。

対話モード

対話的にリベースするとは、リベースされるコミットを編集する機会があることを意味します。コミットの順序を変更したり、それらを削除したり(不正なパッチや不要なパッチを取り除く)、することができます。

対話モードは、次のようなワークフローを意図しています。

  1. 素晴らしいアイデアを思いつく

  2. コードをハックする

  3. 提出用のシリーズを準備する

  4. 提出する

ここで、2.はいくつかのインスタンスで構成されます。

a) 通常の使用

  1. コミットに値する何かを完了する

  2. commit

b) 独立したフィックスアップ

  1. 何かが機能しないことに気づく

  2. それを修正する

  3. コミットする

b.2.で修正されたものが、それが修正する完璧ではないコミットに修正(amend)できないことがあります。なぜなら、そのコミットがパッチシリーズの深く埋もれているからです。対話型リベースはまさにそのためにあります。「a」や「b」をたくさん行った後、コミットを並べ替えたり編集したり、複数のコミットを1つにスカッシュしたりするために使用します。

そのまま保持したい最後のコミットから開始します。

git rebase -i <after-this-commit>

指定されたコミット以降の現在のブランチのすべてのコミット(マージコミットは無視されます)がエディタで開かれます。このリストのコミットは自由に並べ替えたり、削除したりできます。リストはほぼ次のようになります。

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

一行の説明は純粋にあなたの便宜のためのものです。git rebaseはこれらを見ずにコミット名(この例では「deadbee」と「fa1afe1」)を見るので、名前を削除したり編集したりしないでください。

コマンド「pick」を「edit」に置き換えることで、そのコミットを適用した後にgit rebaseを停止させることができます。これにより、ファイルを編集したり、コミットメッセージを編集したり、コミットを修正したり、リベースを続行したりすることができます。

リベースを中断するには(「edit」コマンドと同様ですが、最初にコミットをチェリーピックしない)、コマンド「break」を使用します。

コミットのコミットメッセージだけを編集したい場合は、コマンド「pick」を「reword」に置き換えます。

コミットを削除するには、コマンド「pick」を「drop」に置き換えるか、対応する行を削除するだけです。

2つ以上のコミットを1つにまとめたい場合、2番目以降のコミットのコマンド「pick」を「squash」または「fixup」に置き換えます。コミットの作者が異なる場合、まとめられたコミットは最初のコミットの作者に帰属します。まとめられたコミットの提案されるコミットメッセージは、最初のコミットのメッセージと「squash」コマンドで指定されたコミットのメッセージを連結したもので、ただし「fixup -c」が使用されていない限り、「fixup」コマンドで指定されたコミットのメッセージは省略されます。その場合、提案されるコミットメッセージは「fixup -c」コミットのメッセージのみとなり、メッセージを編集できるようにエディタが開かれます。「fixup -c」コミットの内容(パッチ)は、まとめられたコミットに組み込まれたままになります。「fixup -c」コミットが複数ある場合、最後のものからのメッセージが使用されます。エディタを開かずに「fixup -c」と同じ動作を得るには、「fixup -C」を使用することもできます。

「pick」が「edit」に置き換えられた場合、またはマージエラーによりコマンドが失敗した場合、git rebaseは停止します。編集および/またはコンフリクトの解決が完了したら、git rebase --continueで続行できます。

例えば、最後の5つのコミットを並べ替えて、HEAD~4だったものを新しいHEADにしたい場合。それを実現するには、git rebaseを次のように呼び出します。

$ git rebase -i HEAD~5

そして、最初のパッチをリストの最後に移動させます。

マージコミットを再作成したい場合があります。例えば、次のような履歴がある場合です。

           X
            \
         A---M---B
        /
---o---O---P---Q

"A"から始まるサイドブランチを"Q"にリベースしたいとします。現在のHEADが"B"であることを確認し、次を呼び出します。

$ git rebase -i -r --onto Q O

コミットの並べ替えや編集は、通常、テストされていない中間ステップを作成します。履歴の編集が何も壊していないか、テストを実行するか、または少なくとも履歴の中間点で「exec」コマンド(ショートカット「x」)を使用して再コンパイルすることで確認したい場合があります。これは、次のようなTODOリストを作成することで実行できます。

pick deadbee Implement feature XXX
fixup f1a5c00 Fix to feature XXX
exec make
pick c0ffeee The oneline of the next commit
edit deadbab The oneline of the commit after
exec cd subdir; make test
...

対話型リベースは、コマンドが失敗した場合(つまり、0以外のステータスで終了した場合)に停止し、問題を修正する機会を提供します。git rebase --continueで続行できます。

「exec」コマンドはシェル(デフォルトは通常/bin/sh)でコマンドを起動するため、シェル機能(「cd」、「>」、「;」など)を使用できます。コマンドは作業ツリーのルートから実行されます。

$ git rebase -i --exec "make test"

このコマンドを使用すると、中間コミットがコンパイル可能であることを確認できます。TODOリストは次のようになります。

pick 5928aea one
exec make test
pick 04d0fda two
exec make test
pick ba46169 three
exec make test
pick f4593f9 four
exec make test

コミットの分割

対話モードでは、コミットに「edit」アクションをマークできます。ただし、これはgit rebaseがこの編集の結果が厳密に1つのコミットであることを期待しているという意味ではありません。実際、コミットを元に戻したり、他のコミットを追加したりできます。これはコミットを2つに分割するために使用できます。

  • 分割したいコミットが<commit>である場合、git rebase -i <commit>^で対話型リベースを開始します。実際、そのコミットが含まれていれば、どのようなコミット範囲でも構いません。

  • 分割したいコミットを「edit」アクションでマークします。

  • そのコミットを編集する段階になったら、git reset HEAD^を実行します。これによりHEADが1つ巻き戻され、インデックスもそれに追従します。ただし、作業ツリーは同じままです。

  • 次に、最初のコミットに含めたい変更をインデックスに追加します。これにはgit add(場合によっては対話的に)またはgit gui(あるいはその両方)を使用できます。

  • 現在のインデックスを、現時点で適切なコミットメッセージでコミットします。

  • 作業ツリーがクリーンになるまで、最後の2つのステップを繰り返します。

  • git rebase --continueでリベースを続行します。

中間リビジョンが一貫していること(コンパイルできるか、テストスイートに合格するかなど)を完全に確信できない場合は、各コミット後にgit stashを使用して未コミットの変更をスタッシュし、テストを行い、修正が必要な場合はコミットをamendするべきです。

アップストリームのリベースからの復旧

他の人が作業のベースにしているブランチをリベースする(またはその他の書き換え形式)のは悪いアイデアです。そのブランチの下流にいる人は全員、手動で履歴を修正せざるを得なくなります。このセクションでは、下流側の視点から修正を行う方法を説明します。しかし、本当の解決策は、そもそもアップストリームをリベースしないことです。

例として、誰かがsubsystemブランチを開発し、あなたがこのsubsystemに依存するtopicで作業している状況を仮定します。あなたは次のような履歴になるかもしれません。

    o---o---o---o---o---o---o---o  master
	 \
	  o---o---o---o---o  subsystem
			   \
			    *---*---*  topic

もしsubsystemmasterに対してリベースされた場合、次のようになります。

    o---o---o---o---o---o---o---o  master
	 \			 \
	  o---o---o---o---o	  o'--o'--o'--o'--o'  subsystem
			   \
			    *---*---*  topic

もしあなたが通常通り開発を続け、最終的にtopicsubsystemにマージした場合、subsystemからのコミットは永遠に重複したままになります。

    o---o---o---o---o---o---o---o  master
	 \			 \
	  o---o---o---o---o	  o'--o'--o'--o'--o'--M	 subsystem
			   \			     /
			    *---*---*-..........-*--*  topic

そのような重複は、履歴を乱し、追跡を困難にするため、一般的に好ましくありません。整理するには、topic上のコミットを新しいsubsystemの先端に移植する必要があります。つまり、topicをリベースします。これは波及効果を生み、topicの下流にいる誰もがリベースを余儀なくされ、以下同様になります!

修正には2種類あり、以下のサブセクションで説明します。

簡単なケース: 変更が文字通り同じである場合。

これは、subsystemのリベースが単純なもので、コンフリクトがなかった場合に発生します。

難しいケース: 変更が同じでない場合。

これは、subsystemのリベースにコンフリクトがあった場合、または--interactiveを使用してコミットを省略、編集、スカッシュ、またはフィックスアップした場合に発生します。あるいは、アップストリームがcommit --amendreset、またはfilter-repoのような履歴を完全に書き換えるコマンドを使用した場合があります。

簡単なケース

subsystemで行われたリベースの前と後で、subsystem上の変更(diffの内容に基づくパッチID)が文字通り同じである場合にのみ機能します。

その場合、新しいアップストリームに既に存在する変更をgit rebaseがスキップすることを知っているため(--reapply-cherry-picksが指定されていない限り)、修正は簡単です。したがって、(topicにいると仮定して)次のように入力すると、

    $ git rebase subsystem

修正された履歴が得られます。

    o---o---o---o---o---o---o---o  master
				 \
				  o'--o'--o'--o'--o'  subsystem
						   \
						    *---*---*  topic

難しいケース

subsystemの変更がリベース前のものと正確に対応しない場合、事態はより複雑になります。

注記
「簡単なケースでの復旧」は、難しいケースでも成功したように見えることがありますが、意図しない結果を招く可能性があります。例えば、git rebase --interactiveで削除されたコミットが復活してしまいます!

考え方は、git rebaseに「古いsubsystemがどこで終わり、あなたのtopicがどこから始まったか」、つまり、それらの間の古いマージベースが何であったかを手動で伝えることです。古いsubsystemの最後のコミットを名前で指定する方法を見つける必要があります。例えば、

  • subsystemの参照ログを使用する場合: git fetchの後、subsystemの古い先端はsubsystem@{1}にあります。その後のfetchではこの数値が増加します。(git-reflog[1]を参照。)

  • topicの先端を基準にする場合: あなたのtopicに3つのコミットがあることを知っていれば、古いsubsystemの先端はtopic~3であるはずです。

その後、(reflogのケースで、既にtopicにいると仮定して)次のようにして、古いsubsystem..topicを新しい先端に移植できます。

    $ git rebase --onto subsystem subsystem@{1}

「難しいケース」での復旧の波及効果は特に悪く、topicの下流にいる全員が今度は「難しいケース」での復旧を行わなければならなくなります!

マージのリベース

対話型リベースコマンドは元々、個々のパッチシリーズを処理するために設計されました。そのため、開発者がブランチ作業中にその時点のmasterをマージし、最終的にすべてのコミットをmasterにリベースする(マージコミットをスキップする)場合、TODOリストからマージコミットを除外するのは理にかなっています。

しかし、開発者がマージコミットを再作成したい正当な理由もあります。それは、複数の相互に関連するブランチで作業する際に、ブランチ構造(または「コミットトポロジー」)を維持するためです。

以下の例では、開発者がボタンの定義方法をリファクタリングするトピックブランチと、そのリファクタリングを使用して「バグを報告」ボタンを実装する別のトピックブランチで作業しています。git log --graph --format=%s -5の出力は次のようになるかもしれません。

*   Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one

開発者は、ブランチトポロジーを維持しながら、これらのコミットを新しいmasterにリベースしたいと考えるかもしれません。例えば、最初のトピックブランチが2番目のものよりもはるかに早くmasterに統合されることが予想される場合、あるいはmasterに取り込まれたDownloadButtonクラスの変更とのマージコンフリクトを解決するためなどです。

このリベースは、--rebase-mergesオプションを使用して実行できます。次のようなTODOリストが生成されます。

label onto

# Branch: refactor-button
reset onto
pick 123456 Extract a generic Button class from the DownloadButton one
pick 654321 Use the Button class for all buttons
label refactor-button

# Branch: report-a-bug
reset refactor-button # Use the Button class for all buttons
pick abcdef Add the feedback button
label report-a-bug

reset onto
merge -C a1b2c3 refactor-button # Merge 'refactor-button'
merge -C 6f5e4d report-a-bug # Merge 'report-a-bug'

通常のリベースとは異なり、pickコマンドに加えて、labelresetmergeコマンドがあります。

labelコマンドは、そのコマンドが実行されたときに現在のHEADにラベルを関連付けます。これらのラベルは、リベースが終了すると削除される作業ツリーローカルな参照(refs/rewritten/<label>)として作成されます。これにより、同じリポジトリにリンクされた複数の作業ツリーでのリベース操作が互いに干渉しません。labelコマンドが失敗した場合、直ちに再スケジュールされ、続行方法に関する役立つメッセージが表示されます。

resetコマンドは、HEAD、インデックス、および作業ツリーを指定されたリビジョンにリセットします。これはexec git reset --hard <label>に似ていますが、未追跡ファイルを上書きすることを拒否します。resetコマンドが失敗した場合、直ちに再スケジュールされ、TODOリストを編集する方法に関する役立つメッセージが表示されます(これは通常、resetコマンドが手動でTODOリストに挿入され、タイプミスが含まれている場合に発生します)。

mergeコマンドは、その時点のHEADに指定されたリビジョンをマージします。-C <original-commit>を使用すると、指定されたマージコミットのコミットメッセージが使用されます。-Cが小文字の-cに変更された場合、マージが成功した後にメッセージがエディタで開かれ、ユーザーがメッセージを編集できるようになります。

mergeコマンドがマージ競合以外の理由で(つまり、マージ操作が開始されなかった場合でも)失敗した場合、すぐに再スケジュールされます。

デフォルトでは、mergeコマンドは通常の merges にはortマージ戦略を、octopus merges にはoctopusを使用します。リベースを呼び出す際に--strategy引数を使用してすべての merges のデフォルト戦略を指定することも、execコマンドを使用してgit merge--strategy引数付きで明示的に呼び出すことで、対話型コマンドリスト内の特定の merges を上書きすることもできます。このようにgit mergeを明示的に呼び出す際、ラベルが作業ツリーローカルな参照であるという事実(例えば、参照refs/rewritten/ontoはラベルontoに対応します)を利用して、マージしたいブランチを参照できることに注意してください。

注記: 最初のコマンド(label onto)は、コミットがリベースされるリビジョンにラベルを付けます。名前ontoは、--ontoオプションへの言及として、単なる慣例です。

また、merge <merge-head>の形式のコマンドを追加することで、完全に新しいマージコミットをゼロから導入することも可能です。この形式は仮のコミットメッセージを生成し、常にエディタを開いてユーザーが編集できるようにします。これは、例えばトピックブランチが単一の関心事だけでなく複数の関心事を扱うことになり、2つ以上のトピックブランチに分割したい場合などに役立ちます。このTODOリストを検討してください。

pick 192837 Switch from GNU Makefiles to CMake
pick 5a6c7e Document the switch to CMake
pick 918273 Fix detection of OpenSSL in CMake
pick afbecd http: add support for TLS v1.3
pick fdbaec Fix detection of cURL in CMake on Windows

このリストにあるCMakeに関連しない1つのコミットは、CMakeへの切り替えによって導入されたすべてのバグを修正する作業によって動機付けられたのかもしれませんが、それは別の懸念事項に対処しています。このブランチを2つのトピックブランチに分割するには、TODOリストを次のように編集できます。

label onto

pick afbecd http: add support for TLS v1.3
label tlsv1.3

reset onto
pick 192837 Switch from GNU Makefiles to CMake
pick 918273 Fix detection of OpenSSL in CMake
pick fdbaec Fix detection of cURL in CMake on Windows
pick 5a6c7e Document the switch to CMake
label cmake

reset onto
merge tlsv1.3
merge cmake

設定

このセクションのこの行より下のすべての内容は、git-config[1]のドキュメントから選択的に含まれています。内容はそちらで見られるものと同じです。

rebase.backend

リベースに使用するデフォルトのバックエンド。選択肢はapplyまたはmergeです。将来、mergeバックエンドがapplyバックエンドの残りのすべての機能を取得した場合、この設定は使用されなくなる可能性があります。

rebase.stat

前回のリベース以降、アップストリームで何が変更されたかのdiffstatを表示するかどうか。デフォルトはfalseです。

rebase.autoSquash

trueに設定すると、対話モードでgit-rebase[1]--autosquashオプションがデフォルトで有効になります。これは--no-autosquashオプションで上書きできます。

rebase.autoStash

trueに設定すると、操作開始前に一時的なスタッシュエントリを自動的に作成し、操作終了後にそれを適用します。これにより、ダーティな作業ツリーでリベースを実行できます。ただし、注意して使用してください。リベース成功後の最終的なスタッシュ適用は、軽視できない競合を引き起こす可能性があります。このオプションは、git-rebase[1]--no-autostashおよび--autostashオプションで上書きできます。デフォルトはfalseです。

rebase.updateRefs

trueに設定すると、--update-refsオプションがデフォルトで有効になります。

rebase.missingCommitsCheck

「warn」に設定すると、一部のコミットが削除された場合(例:行が削除された場合)、git rebase -iは警告を出力しますが、リベースは続行されます。「error」に設定すると、以前の警告を出力し、リベースを停止します。その後、git rebase --edit-todoを使用してエラーを修正できます。「ignore」に設定すると、チェックは行われません。警告やエラーなしでコミットを削除するには、TODOリストでdropコマンドを使用します。デフォルトは「ignore」です。

rebase.instructionFormat

対話型リベース中のTODOリストに使用される、git-log[1]で指定された形式文字列。この形式には、自動的にコミットハッシュが先頭に追加されます。

rebase.abbreviateCommands

trueに設定すると、git rebaseはTODOリストで短縮されたコマンド名を使用し、次のような結果になります。

	p deadbee The oneline of the commit
	p fa1afe1 The oneline of the next commit
	...

代わりに

	pick deadbee The oneline of the commit
	pick fa1afe1 The oneline of the next commit
	...

デフォルトはfalseです。

rebase.rescheduleFailedExec

失敗したexecコマンドを自動的に再スケジュールします。これは対話モード(または--execオプションが指定された場合)でのみ意味があります。これは--reschedule-failed-execオプションを指定するのと同じです。

rebase.forkPoint

falseに設定すると、--no-fork-pointオプションがデフォルトで設定されます。

rebase.rebaseMerges

--rebase-mergesオプションをデフォルトで設定するかどうか、またどのように設定するか。rebase-cousinsno-rebase-cousins、またはブーリアン値をとることができます。trueまたはno-rebase-cousinsに設定することは--rebase-merges=no-rebase-cousinsと同等であり、rebase-cousinsに設定することは--rebase-merges=rebase-cousinsと同等であり、falseに設定することは--no-rebase-mergesと同等です。コマンドラインで--rebase-mergesを引数ありまたはなしで渡すと、rebase.rebaseMergesのすべての設定が上書きされます。

rebase.maxLabelLength

コミットサブジェクトからラベル名を生成する際、この長さに名前を切り詰めます。デフォルトでは、名前はNAME_MAXよりわずかに短く切り詰められます(例えば、対応するルーズリファレンス用の.lockファイルが書き込めるようにするため)。

sequence.editor

git rebase -iがリベース指示ファイルを編集するために使用するテキストエディタ。この値は使用時にシェルによって解釈されることを意図しています。GIT_SEQUENCE_EDITOR環境変数によって上書きできます。設定されていない場合、デフォルトのコミットメッセージエディタが代わりに使用されます。

Git

git[1] スイートの一部

scroll-to-top