Git で別のブランチのブランチを「マージ」するのではなく「上書き」するにはどうすればよいですか? 質問する

Git で別のブランチのブランチを「マージ」するのではなく「上書き」するにはどうすればよいですか? 質問する

ブランチが 2 つあり、はemail最新のもので、ブランチ内の古い変更は不要になりましたが、削除したくありません。stagingstagingemail

そこで、 のすべての内容をダンプして、両方が同じコミットを指すようにしたいのですがstagingemailそれは可能ですか?

ベストアンサー1

あなたは「私たちの」合併戦略:

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our (=staging) branch head
$ git checkout email
$ git merge staging

質問では、ブランチのコミットが保持されることが求められます。コミットはアクセス不能にしてはならないため、ベースのアプローチやブランチの削除と再作成はemail不可能になります。reset

電子メール ブランチの古い変更はもう必要ありませんが、削除したくありません。

両方のブランチのコミットをアクセス可能に保つには、それらのコミットを指す 1 つ以上の参照が存在する必要があります。 常に 2 つの参照 (stagingと) を保持できますが、質問では参照の 1 つを削除するように求められています。 したがって、何らかの方法でブランチをマージするemail必要があります。


編集 2020-07-30:

この質問と解決策についてもう少し考えてみました。マージの親を正しい順序で絶対に必要とし、このアクションを 1 回のコマンド ライン呼び出しで実行する必要があり、配管コマンドを実行しても構わない場合は、次の操作を実行できます。

$ git checkout A
$ git merge --ff-only $(git commit-tree -m "Throw away branch 'A'" -p A -p B B^{tree})

これは基本的に(存在しない)merge -s theirs戦略のように機能します。結果の履歴はplumbingデモリポジトリのブランチ

switchに比べると読みにくく、覚えにくいです-s oursが、目的は果たせます。結果のツリーは、ブランチ B と同じです。

$ git rev-parse A^{tree} B^{tree} HEAD^{tree}
3859ea064e85b2291d189e798bfa1bff87f51f3e
0389f8f2a3e560b639d82597a7bc5489a4c96d44
0389f8f2a3e560b639d82597a7bc5489a4c96d44

編集 2020-07-29:

-s ours-X ours(後者は と同等)の違いについて多くの混乱があるようです-s recursive --strategy-option ours。ここでは、これら2つの方法を使用した2つの結果を示す小さな例を示します。また、の質問と回答を読むことをお勧めします。(Git マージ) 「ours」戦略、「ours」オプション、「theirs」オプションはいつ使用すればよいですか?

まず、2つのブランチと3つのコミット(ベースコミット1つとブランチごとに1つのコミット)を持つリポジトリを設定します。サンプルリポジトリはGitHubで

$ git init
$ echo 'original' | tee file1 file2 file3
$ git commit -m 'initial commit'
$ git branch A
$ git branch B
$ git checkout A
$ echo 'A' > file1
$ git commit -m 'change on branch A' file1
$ git checkout B
$ echo 'B' > file2
$ git commit -m 'change on branch B' file2

さて、戦略オプションを試してみましょう(この説明に彼らの戦略を使用するか私たちの戦略を使用するかは、あまり重要ではありません)。

$ git merge -X ours A
$ cat file*
A
B
original

最終的には、両方のブランチの内容がマージされます(サンプル リポジトリのブランチ「strategy-option」)。これを、マージ戦略を使用した場合と比較します(次の手順を実行する前に、リポジトリを再初期化するか、ブランチをリセットします)。

$ git merge -s ours A
$ cat file*
original
B
original

結果はまったく異なります (サンプル リポジトリのブランチ「merge-strategy」)。strategy オプションを使用すると、両方のブランチのマージ結果が得られますが、strategy を使用すると、他のブランチで発生した変更はすべて破棄されます。

また、マージ戦略によって作成されたコミットは、実際には「our」ブランチの最新のコミットとまったく同じツリーを指しているのに対し、戦略オプションは、これまでに見たことのない新しいツリーを作成していることにも気づくでしょう。

$ git rev-parse A^{tree} B^{tree} merge-strategy^{tree} strategy-option^{tree}
3859ea064e85b2291d189e798bfa1bff87f51f3e
0389f8f2a3e560b639d82597a7bc5489a4c96d44
0389f8f2a3e560b639d82597a7bc5489a4c96d44
5b09d34a37a183723b409d25268c8cb4d073206e

OP は確かに「[…] ブランチの古い変更はもう必要ありません」と「[A] のすべての内容を [B] にダンプしたいだけです」と求めていますが、これは戦略オプション では実行できませんwrite-tree 「ours」マージ戦略を使用するのは、多くの可能性の 1 つですが、おそらく最も簡単です (他の可能性としては、やなどの Git の低レベル コマンドを使用することが挙げられますcommit-tree)。

おすすめ記事