回答:
OPの答えよりもさらに簡単です。
git rebase -i <any earlier commit>
。設定したテキストエディターにコミットのリストが表示されます。a1b2c3d
)。エディターで、その行をに変更pick
しedit
ます。a1b2c3d
)がコミットされたかのように、コマンドプロンプトが表示されます。git commit
(ほとんどのとは異なり、修正しないでくださいedit
)。これにより、選択したコミットの後に新しいコミットが作成されます。git rebase --continue
。これにより、連続したコミットが再生され、新しいコミットが正しい場所に挿入されたままになります。これにより履歴が書き直され、プルしようとする他のユーザーが破壊されることに注意してください。
A -- B -- C -- D
は望みの代わりになりましたA -- D -- B -- C
。
D
どこでもコミットできます。私たちがいて、このブランチにさえないA - B - C
コミットがD
あるとします。私たちはそのSHAを知っていgit rebase -i HEAD~3
ますが、できます。次にA
、B
pick
行と行の間に、と言う新しい pick
行を挿入しpick SHA
、希望するのハッシュを与えますD
。完全なハッシュである必要はなく、短縮されたものである必要があります。 git rebase -i
チェリーpick
は、バッファ内の行ごとにリストされているコミットをすべて選択します。それらはあなたのためにリストしたオリジナルのものである必要はありません。
break
2つのコミットの間にある専用の行でエディターのキーワードを使用できます(または最初の行で、指定したコミットの前にコミットを挿入します)。
非常に単純であることがわかります。答えはここにあります。ブランチにいるとしますbranch
。次の手順を実行します。
新しいコミット(この場合はcommit A
)を挿入した後、コミットから一時的なブランチを作成します。
git checkout -b temp A
変更を実行してコミットし、コミットを作成して、それを呼び出しましょうN
:
git commit -a -m "Message"
(またはgit add
その後にgit commit
)
新しいコミット(この場合はコミットB
とC
)の後に必要なコミットを新しいコミットにリベースします。
git rebase temp branch
(-p
もしあれば、おそらくマージを保存するために使用する必要があります-ciekawyによるもう存在しないコメントのおかげで)
一時的なブランチを削除します。
git branch -d temp
この後、履歴は次のようになります。
A -- N -- B -- C
もちろん、リベース中にいくつかの競合が発生する可能性があります。
ブランチがローカルのみではない場合、これは書き換え履歴を導入するため、深刻な問題を引き起こす可能性があります。
git push --force
、リモートリポジトリを変更する必要がありました。
git rebase temp branch -Xtheirs
。スクリプトを挿入するのに役立つ回答です。
git rebase temp branch
ますが、前にgit branch -d temp
、あなたがしなければならないすべては、紛争や問題をマージ修正し、ステージであるgit rebase --continue
、つまり何かをコミットする必要はありません、など
さらに簡単な解決策:
最後にDで新しいコミットを作成します。これで、次のことができました。
A -- B -- C -- D
次に実行します:
$ git rebase -i hash-of-A
Gitがエディターを開き、次のようになります。
pick 8668d21 B
pick 650f1fc C
pick 74096b9 D
このようにDを一番上に移動し、保存して終了するだけです
pick 74096b9 D
pick 8668d21 B
pick 650f1fc C
今あなたは持っているでしょう:
A -- D -- B -- C
コミット履歴がpreA -- A -- B -- C
であるとするA
とB
、との間にコミットを挿入する場合の手順は次のとおりです。
git rebase -i hash-of-preA
Gitがエディターを開きます。コンテンツは次のようになります。
pick 8668d21 A
pick 650f1fc B
pick 74096b9 C
最初のものpick
を次のように変更しedit
ます。
edit 8668d21 A
pick 650f1fc B
pick 74096b9 C
保存して終了。
コードを変更してから git add . && git commit -m "I"
git rebase --continue
今あなたのGitコミット履歴は preA -- A -- I -- B -- C
競合が発生した場合、Gitはこのコミットで停止します。を使用git diff
して、競合マーカーを見つけて解決できます。すべての競合を解決した後、を使用git add <filename>
してGitに競合が解決されたことを通知し、を再実行する必要がありますgit rebase --continue
。
リベースを元に戻す場合は、を使用しますgit rebase --abort
。
これは、私が読んだ他の回答で見られるリベース中に「編集ハック」を行わないようにする戦略です。
を使用git rebase -i
すると、そのコミット以降のコミットのリストを取得できます。ファイルの先頭に「ブレーク」を追加するだけで、その時点でリベースがブレークします。
break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>
起動git rebase
すると、「中断」の時点で停止します。これでファイルを編集して、通常どおりコミットを作成できます。その後、でリベースを続行できgit rebase --continue
ます。これにより、修正が必要な競合が発生する可能性があります。道に迷った場合は、を使用していつでも中断できることを忘れないでくださいgit rebase --abort
。
この戦略は、コミットをどこにでも挿入できるように一般化できます。コミットを挿入したい場所に「ブレーク」を置くだけです。
履歴を書き換えた後は、忘れずにgit push -f
。あなたのブランチをフェッチしている他の人に関する通常の警告が適用されます。
rebase
ここを走っています。コミットをリベース中に作成するか、事前に作成するかは、それほど大きな違いはありません。
すでに多くの良い答えがここにあります。「リベースなし」のソリューションを4つの簡単なステップで追加したかっただけです。
概要
git checkout A
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD
説明
(注:このソリューションの利点の1つは、最終ステップまでブランチに触れないことです。最終結果に問題がないことを100%確信しているため、非常に便利な「事前確認」ステップがあります。 ABテストが可能です。
初期状態(私はmaster
あなたのブランチ名を想定しています)
A -- B -- C <<< master <<< HEAD
1)適切な場所にHEADを向けることから始めます
git checkout A
B -- C <<< master
/
A <<< detached HEAD
(オプションとして、ここでは、HEADをデタッチするのではなく、で一時的なブランチを作成しgit checkout -b temp A
、プロセスの最後に削除する必要があります。他のすべてが同じままであるため、どちらのバリアントも動作します。)
2)挿入する新しいコミットDを作成する
# at this point, make the changes you wanted to insert between A and B, then
git commit -am "Message for commit D"
B -- C <<< master
/
A -- D <<< detached HEAD (or <<< temp <<< HEAD)
3)次に、最後に失われたコミットBとCのコピーを用意します(さらにコミットがあった場合は同じ行になります)
git cherry-pick A..C
# (if any, resolve any potential conflicts between D and these last commits)
B -- C <<< master
/
A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)
(必要に応じてここで快適なABテスト)
今、あなたのコードを検査する瞬間は、ニーズをテストすることをテスト何でもあります。また、差分/検査/比較することができ、何を持っていたし、何を得るでしょう操作の後。
4)C
との間のテストに応じて、C'
問題がないか、問題がない。
(どちらでも)4-OK)最後に、の参照を移動しますmaster
git branch -f master HEAD
B -- C <<< (B and C are candidates for garbage collection)
/
A -- D -- B' -- C' <<< master
(OR)4-KO)だけのままmaster
変わらず
一時的なブランチを作成した場合は、それをgit branch -d <name>
で削除するだけですが、切り離されたHEADルートに移動した場合、この時点では何もする必要はありません。新しいコミットはHEAD
、git checkout master
どちらの場合も(OKまたはKO)、この時点でmaster
もう一度チェックアウトして再接続しHEAD
ます。