“ theirs”はありますか“ git merge -s ours&#8221 ;?
質問
トピックブランチ" B"をマージする場合「A」に git merge
を使用すると、競合が発生します。すべての競合は" B"のバージョンを使用して解決できることを知っています。
git merge -s ours
を知っています。しかし、私が欲しいのは git merge -s theirs
のようなものです。
なぜ存在しないのですか?既存の git
コマンドとの競合のマージ後に同じ結果を得るにはどうすればよいですか? ( git checkout
Bのすべてのマージされていないファイル)
UPDATE:" solution"ブランチA(ツリーのBバージョンへのマージコミットポイント)から何かを単に破棄することは、私が探しているものではありません。
解決
-X
オプションを theirs
に追加します。例:
git checkout branchA
git merge -X theirs branchB
すべてが目的の方法でマージされます。
問題が発生するのは、ファイルがbranchBから削除された場合のみです。 git以外の何かが削除を行うと、競合として表示されます。
修正は簡単です。削除されたファイルの名前で git rm
を実行するだけです:
git rm {DELETED-FILE-NAME}
その後、 -X theirs
は期待どおりに動作するはずです。
もちろん、 git rm
コマンドを使用して実際の削除を行うことにより、そもそも競合が発生しなくなります。
注:より長い形式のオプションもあります。使用するには、次を置き換えます。
-X theirs
with:
--strategy-option=theirs
他のヒント
ブランチBをチェックアウトされたブランチAにマージするための可能なテスト済みソリューション:
# in case branchA is not our current branch
git checkout branchA
# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB
# make temporary branch to merged commit
git branch branchTEMP
# get contents of working tree and index to the one of branchB
git reset --hard branchB
# reset to our merged commit but
# keep contents of working tree and index
git reset --soft branchTEMP
# change the contents of the merged commit
# with the contents of branchB
git commit --amend
# get rid off our temporary branch
git branch -D branchTEMP
# verify that the merge commit contains only contents of branchB
git diff HEAD branchB
自動化するには、branchAとbranchBを引数として使用してスクリプトにラップします。
このソリューションは、 git merge -s theirs branchB
で予想されるように、マージコミットの最初と2番目の親を保持します。
gitの古いバージョンでは、「theirs」を使用できました。マージ戦略:
git pull --strategy=theirs remote_branch
ただし、このメッセージで浜野潤夫によって説明されているように、これはその後削除されました。 (Gitメンテナー)。リンクに記載されているように、代わりにこれを行います:
git fetch origin
git reset --hard origin
ただし、これは実際のマージとは異なることに注意してください。あなたのソリューションはおそらくあなたが本当に探しているオプションです。
私は今からPaul Pladijsの回答を使用しました。私は、「通常」を実行できることを知りました。マージ、競合が発生するため、あなたは
git checkout --theirs <file>
他のブランチのリビジョンを使用して競合を解決します。ファイルごとにこれを行うと、予想される動作と同じ
git merge <branch> -s theirs
とにかく、努力はマージ戦略の場合よりも多くなります! (これはgitバージョン1.8.0でテストされました)
希望する結果が何であるかは完全には明らかではないため、「正しい」ことについて混乱が生じています。回答とコメントでそれを行う方法。概要を説明しようとすると、次の3つのオプションが表示されます。
マージにBを使用して競合を解決します
これは、 git merge -X ours
&quot;のバージョン」 (これは git merge -s recursive -X ours
の略です):
git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB
これは、たとえばアランW.スミスの答えはそうです。
Bのコンテンツのみを使用する
これにより、両方のブランチに対してマージコミットが作成されますが、 branchA
からのすべての変更が破棄され、 branchB
からの内容のみが保持されます。
# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB
# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA
# Set branchA to current commit and check it out.
git checkout -B branchA
マージのコミットの最初の親は branchB
からのものであり、2番目の親は branchA
からのものです。これは、例えば Gandalf458の答えはそうです。
Bのコンテンツのみを使用し、正しい親の順序を維持する
これは、 git merge -s ours
&quot;の実際の&quot;バージョンです。前のオプションと同じ内容(つまり、 branchB
からのみ)がありますが、親の順序は正しいです。つまり、最初の親は branchA
から、2番目は親から branchB
。
git checkout branchA
# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB
# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB
# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA
# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA
# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD
これは、ポールプラディスの答えの機能です(一時的なブランチは不要です)。
使用して問題を解決しました
git checkout -m old
git checkout -b new B
git merge -s ours old
ブランチAにいる場合:
git merge -s recursive -X theirs B
gitバージョン1.7.8でテスト済み
トピックブランチ&quot; B&quot;をマージする場合&quot; A&quot; git mergeを使用すると、競合が発生します。 &gt; Bのバージョンを使用すると、すべての競合を解決できることがわかっています。
git merge -s oursを知っています。しかし、私が欲しいのはgit merge&gt; -s theirのようなものです。
masterからブランチを作成し、masterにマージして、master内の古いものを上書きしたいと仮定しています。それがまさにこの投稿に出会ったときにやりたかったことです。
最初に1つのブランチを他のブランチにマージすることを除いて、やりたいことを正確に実行します。私はちょうどこれをやった、そしてそれはうまくいった。
git checkout Branch
git merge master -s ours
次に、マスターをチェックアウトし、ブランチをマージします(今はスムーズに進みます):
git checkout master
git merge Branch
マージするブランチからのみの入力を受け取るマージを本当に適切に行うには、次のようにします
git merge --strategy = ours ref-to-be-be-merged
git diff --binary ref-to-be-merged | git apply --reverse --index
git commit --amend
私が知っているどのシナリオでも競合はありません。追加のブランチを作成する必要はなく、通常のマージコミットのように動作します。
ただし、これはサブモジュールではうまくいきません。
浜野順夫の広く引用されている回答を参照:コミットを破棄する場合コンテンツ、単にコミットを破棄する、またはとにかくそれをメイン履歴から除外します。なぜ提供するものがないコミットからのコミットメッセージを読んで、将来誰もが気にするのですか?
ただし、管理上の要件がある場合や、その他の理由がある場合があります。何も貢献しないコミットを本当に記録しなければならない状況では、以下が必要です:
(編集:うわー、前にこれを間違えたことがありましたか。これは動作します。)
git update-ref HEAD $(
git commit-tree -m 'completely superseding with branchB content' \
-p HEAD -p branchB branchB:
)
git reset --hard
なぜ存在しないのですか
&quot; あるブランチを別のブランチのように作成するgitコマンド&quot; git merge -s theirs
をシミュレートする方法、Git 2.15(2017年第4四半期)がより明確になったことに注意してください:
マージの「
-X&lt; option&gt;
」のドキュメントは誤解を招くようなものでした &quot;-s theirs
&quot;を示唆するために書かれた存在しますが、そうではありません。
gitster
)。
( C浜野邦夫- gitster
- commit 4da3e23 、2017年9月28日)
merge-strategies:&quot;
-s theirs
&quot;存在する
-Xours
マージオプションの説明には括弧付きの注記があります それは読者に-s ours
とは非常に異なることを伝えます。 正しいですが、それに続く-Xtheirs
の説明 &quot;これはours
&quot;の反対であり、誤って 読者もそれが非常に重要であると警告される必要があるという印象 実際には存在しない-s theirs
とは異なります。
-Xtheirs
は、再帰戦略に適用される戦略オプションです。これは、再帰戦略が可能な限りすべてをマージし、&quot; theirs
&quot;のみにフォールバックすることを意味します。競合の場合のロジック。
theirs
マージ戦略の適切性に関する議論が最近持ち帰られましたこの2017年9月のスレッドで。
古い(2008)スレッド
要するに、前の議論は、「
-s theirs
」は間違ったワークフローを助長するため、「-s theirs
」にはなりません。
エイリアスについて言及しています:
mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -
ヤロスラフ・ハルチェンコはその戦略のためにもう一度擁護しようとしている、ジュニオC.浜野:
私たちのものと彼らのものが対称ではない理由は、あなたがあなたであり彼らではないからです。私たちの歴史と彼らの歴史の制御と所有権は対称ではありません。
履歴がメインラインであると判断したら、開発ラインをサイドブランチとして扱い、その方向にマージすることをお勧めします。つまり、結果のマージの最初の親は履歴のコミットです。そして、2番目の親はあなたの歴史の最後の悪い親です。そのため、&quot;
彼らの履歴をチェックアウト&amp;&amp; merge -s your-history
&quot;に 最初の親権を賢明に保ちます。そして、その時点で&quot;
>-s ours
&quot;を使用します&quot;-s theirs
&quot;の不足の回避策ではなくなりました。
これは望ましいセマンティクスの適切な部分です。つまり、存続する標準的な履歴行の観点からは、それが行った内容を保存し、他の履歴行が行ったことを無効にします。
これはgit plumbingコマンドread-treeを使用しますが、全体的なワークフローが短くなります。
git checkout <base-branch>
git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit
# Check your work!
git diff <their-branch>
これにより、newBranchが既存のbaseBranchにマージされます
git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch
あなたが実際に欲しいのは:
git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch
これは不器用なようですが、動作するはずです。私がこのソリューションについて本当に嫌いだと思うのは、gitの履歴が紛らわしいということだけです...しかし、少なくとも履歴は完全に保存され、削除されたファイルに対して特別なことをする必要はありません。
「git merge -s theirs branchB」と同等の(親の順序を保持する)
!!!クリーンな状態であることを確認してください!!!
マージを実行:
git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
git reset --hard 36daf519952 # is the output of the prev command
私たちがしたこと 2人の親が自分と自分の親であり、コミットのコントロールがbranchB-彼らのものである新しいコミットを作成しました
より正確には:
git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'
この回答はPaul Pladijsによって与えられました。便宜上、彼のコマンドを使用してgitエイリアスを作成しました。
.gitconfigを編集して、次を追加します。
[alias]
mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"
その後、「git merge -s theirs A」を使用できます実行:
git checkout B (optional, just making sure we're on branch B)
git mergetheirs A
最近、共通の履歴を共有する2つの別個のリポジトリに対してこれを行う必要がありました。始めたのは:
-
Org / repository1マスター
-
Org / repository2マスター
これを解決したのは、 次に 最後に、 repository2 master
からのすべての変更を repository1 master
に適用し、repository2が行うすべての変更を受け入れるようにしました。 gitの用語では、これは と呼ばれる戦略である必要がありますが、存在しません。 -X theirs
はあなたが望むものと同じように命名されているので注意してください。 >
repository2
に移動して、新しいブランチ repo1-merge
を作成することでした。そのブランチでは、 git pull git@gitlab.com:Org / repository1 -s ours
を実行しましたが、問題なくマージされます。それをリモートにプッシュします。 repository1
に戻り、新しいブランチ repo2-merge
を作成します。そのブランチでは、 git pull git@gitlab.com:Org / repository2 repo1-merge
を実行しますが、これは問題を抱えて完了します。 repository1
でマージリクエストを発行して新しいマスターにするか、ブランチとして保持する必要があります。
シンプルで直感的な(私の意見では)2段階の方法があります
git checkout branchB .
git commit -m "Picked up the content from branchB"
続いて
git merge -s ours branchB
(2つのブランチをマージ済みとしてマークします)
唯一の欠点は、branchBで削除されたファイルを現在のブランチから削除しないことです。その後、2つのブランチ間の単純なdiffは、そのようなファイルがあるかどうかを示します。
このアプローチは、何が行われたのか、そして何が意図されたのかを、その後の改訂ログからも明確にします。