次の場合を考えてみましょう。
私はトピックブランチでいくつかの仕事をしていて、今マスターにマージする準備ができています:
* eb3b733 3 [master] [Origin/master]
| * b62cae6 2 [topic]
|/
* 38abeae 1
マスターからマージを実行し、競合を解決すると、次のようになります。
* 8101fe3 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
* | eb3b733 3 [Origin/master]
|/
* 38abeae 1
さて、マージに時間がかかったので、別のフェッチを行うと、リモートマスターブランチに新しい変更があることがわかります。
* 8101fe3 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
| | * e7affba 4 [Origin/master]
| |/
|/|
* | eb3b733 3
|/
* 38abeae 1
Masterから「git rebase Origin/master」を試みると、すべての競合を再度解決せざるを得なくなり、マージコミットも失われます。
* d4de423 2 [master]
* e7affba 4 [Origin/master]
* eb3b733 3
| * b62cae6 2 [topic]
|/
* 38abeae 1
マージコミットをリベースするクリーンな方法はありますか。そのため、以下に示すような履歴になりますか?
* 51984c7 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
* | e7affba 4 [Origin/master]
* | eb3b733 3
|/
* 38abeae 1
ここには2つのオプションがあります。
1つは、インタラクティブなリベースを実行してマージコミットを編集し、マージを手動でやり直してリベースを続行することです。
もう1つの方法は、-p
でgit rebase
オプションを使用することです。これは、マニュアルから次のように説明されています。この質問はさらに説明します: gitの "rebase --preserve-merges"は正確に何をする(そしてなぜ?)
わかりました、それは古い質問であり、すでに @siride
による回答を受け入れていますが、私の場合は--preserve-merges
がすべての競合を2度目に解決するように強制するため、その回答は十分ではありませんでした。 @Tobi B
によるアイデアに基づいた私のソリューションですが、正確なステップバイステップコマンド
そのため、質問の例に基づいてこのような状態から開始します。
* 8101fe3 Merge branch 'topic' [HEAD -> master]
|\
| * b62cae6 2 [topic]
| |
| | * f5a7ca8 5 [Origin/master]
| | * e7affba 4
| |/
|/|
* | eb3b733 3
|/
* 38abeae 1
マスターには2つのコミットがあるため、チェリーピックは機能しません。
まず、必要な正しい履歴を作成しましょう。
git checkout -b correct-history # create new branch to save master for future
git rebase -s ours -p Origin/master
-p
は--preserve-merges
を意味し、それを使用してマージコミットを履歴に保存します-s ours
は--strategy=ours
を意味します。そのマージコミットに含まれる内容を気にしないため、すべてのマージ競合を無視します。
履歴は次のようになります(マスターを無視):
* 51984c7 Merge branch 'topic' [HEAD -> correct-history]
|\
| * b62cae6 2 [topic]
* | f5a7ca8 5 [Origin/master]
* | e7affba 4
* | eb3b733 3
|/
* 38abeae 1
正しいインデックスを取得しましょう。
git checkout master # return to our master branch
git merge Origin/master # merge Origin/master on top of our master
ここで追加のマージ競合が発生する可能性がありますが、それは8101fe3
とf5a7ca8
の間で変更されたファイルからの競合のみであり、topic
からの既に解決された競合は含まれません。
履歴は次のようになります(修正履歴を無視):
* 94f1484 Merge branch 'Origin/master' [HEAD -> master]
|\
* | f5a7ca8 5 [Origin/master]
* | e7affba 4
| * 8101fe3 Merge branch 'topic'
| |\
| | * b62cae6 2 [topic]
|/ /
* / eb3b733 3
|/
* 38abeae 1
最後の段階は、正しい履歴を持つブランチと正しいインデックスを持つブランチを結合することです
git reset --soft correct-history
git commit --amend
reset --soft
を使用してブランチ(および履歴)を修正履歴にリセットしますが、インデックスと作業ツリーはそのままにします。次に、commit --amend
を使用して、誤ったインデックスを使用していたマージコミットを、マスターからの適切なインデックスで書き換えます。
最終的に、このような状態になります(トップコミットの別のIDに注意してください)。
* 13e6d03 Merge branch 'topic' [HEAD -> master]
|\
| * b62cae6 2 [topic]
* | f5a7ca8 5 [Origin/master]
* | e7affba 4
* | eb3b733 3
|/
* 38abeae 1
これを理解しようとして一日を失い、同僚の助けを借りて実際に解決策を見つけたので、私は中に入れるべきだと思いました。
大規模なコードベースがあり、同時に大幅に変更されている2つのブランチを処理する必要があります。メインブランチとセカンダリブランチがあります。
セカンダリブランチをメインブランチにマージしている間、メインブランチで作業が続行されますが、完了するまでに、互換性がないため変更をプッシュできません。
したがって、「マージ」を「リベース」する必要があります。
これが最終的な方法です。
1)SHAを書き留めます。例:c4a924d458ea0629c0d694f1b9e9576a3ecf506b
git log -1
2)適切な履歴を作成しますが、これによりマージが中断されます。
git rebase -s ours --preserve-merges Origin/master
3)SHAをメモします。例:29dd8101d78
git log -1
4)以前の場所にリセットします
git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard
5)現在のマスターを作業ブランチにマージします
git merge Origin/master
git mergetool
git commit -m"correct files
6)正しいファイルはあるが、間違った履歴があるので、変更を加えて正しい履歴を取得します:
git reset 29dd8101d78 --soft
7)そして-オリジナルのマージコミットの結果を修正します
git commit --amend
出来上がり!
あなたがしたいことは、最初のマージを削除することです。次の手順に従うことができます。
git checkout master # Let's make sure we are on master branch
git reset --hard master~ # Let's get back to master before the merge
git pull # or git merge remote/master
git merge topic
それはあなたが望むものを与えるでしょう。