web-dev-qa-db-ja.com

gitにおける "ours"と "theirs"の正確な意味は何ですか?

これはあまりにも基本的な質問のように思えるかもしれませんが、私は答えを探しました、そして今私は以前より混乱しています。

私のブランチを他のブランチにマージするとき、 "ours"と "theirs"はgitで何を意味しますか?両方の枝は "私たちのもの"です。

マージコンフリクトでは、 "ours"が常に表示されている2つのバージョンのうちの上位になっていますか?

"ours"は、マージが始まったときにHEADが指していたブランチを常に指していますか?もしそうなら、(両ブランチとも技術的には私たちのものなので) "ours"のような所有代名詞を使うのではなく、 "current branch's"のような明確な所有参照を使わないでください。

または単に支店名を使用する(「私たちの」と言うのではなく「ローカルマスターの」などと言うのではなく)?

私にとって最も分かりにくいのは、特定のブランチの.gitattributesファイルで指定した場合です。で言うことができますテストブランチ私は次の.gitattributesファイルがあります:

config.xml merge=ours

チェックアウトしてHEADをmasterにポイントしてからtestにマージします。 masterは私たちのもので、testの.gitattributesはチェックアウトされていないので、それは効果さえありますか?もしそれが効果があるのなら、masterは "our's"になっているので、どうなるでしょう?

249
CommaToast

基本的に混乱しているので、ここで混乱していると思います。さらに悪いことに、リベースを行っているときに、私たち/スタッフ全員が役割を切り替えます(逆になります)。

最終的に、git mergeの間、「ours」ブランチは、マージするブランチを指しますinto

git checkout merge-into-ours

「theirs」ブランチは、マージする(単一の)ブランチを指します。

git merge from-theirs

とにかく「彼ら」がおそらくあなたのものであるとしても、「彼ら」はあなたがいたものではないので、ここで「私たち」と「彼ら」はいくらか理にかなっていますongit mergeを実行したとき。

実際のブランチ名を使用するのはかなりクールかもしれませんが、より複雑な場合にはバラバラになります。たとえば、上記の代わりに、次のことを実行できます。

git checkout ours
git merge 1234567

生のcommit-IDでマージする場所。さらに悪いことに、これを行うことさえできます:

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

その場合、noブランチ名が含まれます!

ここではほとんど役に立たないと思いますが、実際には gitrevisions構文 では、競合するマージ中にインデックス内の個々のパスを番号で参照できます

git show :1:README
git show :2:README
git show :3:README

ステージ#1はファイルの共通の祖先、ステージ#2はターゲットブランチバージョン、ステージ#3はマージ元のバージョンです。


「私たち」と「彼ら」の概念がrebaseの間に入れ替わる理由は、リベースが一連のチェリーピッキングを行うことにより、匿名ブランチ(分離されたHEADモード)で動作するためです。ターゲットブランチは匿名ブランチであり、merge-fromブランチは元の(リベース前)ブランチです。したがって、「-ours」はリベースする匿名の1つを意味し、「-theirs」は「リベースされるブランチ」を意味します。 。


Gitattributesエントリに関して:itcouldは効果があります: "ours"は実際には "use stage#2"を内部的に意味します。しかし、あなたが注意しているように、それは実際にはその時点では適切ではありませんので、は、ここでは効果がありません...まあ、あなたがそれをコピーしない限り開始する前に作業ツリーに移動します。

また、これはourとtheirsのすべての使用に適用されますが、一部はファイルレベル全体(マージ戦略の場合は-s ours;マージ競合中のgit checkout --ours)であり、一部はピースごと(-X oursまたは-X theirsマージ中の-s recursive)。おそらくこれは混乱の助けにはなりません。

しかし、私はこれらのより良い名前を思いつきませんでした。そして: VonCの答え を参照してください。別の質問では、git mergetoolがこれらの名前をさらに紹介し、「ローカル」および「リモート」と呼んでいます。

310
torek

Gitの「ours」は、git履歴の信頼できる/正規の部分を持つ元の作業ブランチを指します。

theirs」は、 rebased (現在に再生される変更のために、作業を保持するバージョンを指しますブランチ)。

これは、リベース(例えばgit rebase)が実際にあなたの作業を保留していることに気付いていない人(つまりtheirs)に交換されて、正規にリプレイするように見えるかもしれません/ main履歴はoursです。これは、変更をサードパーティの作業としてリベースしているためです。

git-checkoutのドキュメントは、Git> = 2.5.1で f303016 commit に従ってさらに明確になりました。

--ours--theirs

インデックスからパスをチェックアウトするとき、マージされていないパスのステージ#2(「私たち」)または#3(「彼ら」)をチェックアウトします。

git rebaseおよびgit pull --rebase中に、「ours」と「theirs」が入れ替わっているように見えることに注意してください。 --oursは、変更がリベースされるブランチのバージョンを提供し、--theirsは、リベースされる作業を保持するブランチのバージョンを提供します。

これは、rebaseが、リモートでの履歴を共有標準ワークフローとして扱い、リベースするブランチで行われた作業をサードパーティの作業として統合するワークフローで使用されるためです。リベース中に一時的に標準履歴のキーパーの役割を引き受けます。正規の履歴のキーパーとして、リモートからの履歴をours(つまり、「共有された正規の履歴」)として表示する必要がありますが、サイドブランチで行ったことはtheirsとして(つまり、その上での貢献者の仕事」)。

git-merge の場合、次のように説明されます。

ours

このオプションは、バージョンを優先することで、競合するハンクを強制的にきれいに自動解決します。私たちの側と競合しない他のツリーからの変更は、マージ結果に反映されます。バイナリファイルの場合、コンテンツ全体が当社側から取得されます。

これは、他のツリーに含まれる内容をまったく考慮しないマージ戦略と混同しないでください。それは他のツリーが行ったすべてを破棄し、その中に起こったすべてが私たちの歴史に含まれていると宣言します。

彼ら

これは私たちの反対です。

さらに、ここでそれらの使用方法を説明します。

マージメカニズム(git mergeおよびgit pullコマンド)を使用すると、-sオプションでバックエンドマージ戦略を選択できます。一部の戦略は独自のオプションを取ることもできます。これは、-X<option>および/またはgit mergegit pull引数を与えることで渡すことができます。


そのため、時には混乱を招く場合があります。例えば:

  • git pull Origin masterここで-Xoursはローカル、-Xtheirsは彼らの(リモート)ブランチです
  • git pull Origin master -rここで-Xoursは自分のもの(リモート)、-Xtheirsは私たちのものです

したがって、2番目の例は1番目の例とは逆になります。これは、ブランチをリモートベースにリベースするため、開始点がリモートブランチであり、変更が外部として扱われるためです。

git merge戦略(-X oursおよび-X theirs)でも同様です。

41
kenorb

私はこれが答えられたことを知っています、しかしこの問題は私が覚えておくのを助けるために私が小さい参照ウェブサイトを立ち上げたことを何度も私を混乱させました: https://nitaym.github.io/ourstheirs/

これが基本です。

マージ:

$ git checkout master 
$ git merge feature

masterでバージョンを選択したい場合:

$ git checkout --ours codefile.js

featureでバージョンを選択したい場合:

$ git checkout --theirs codefile.js

リベース:

$ git checkout feature 
$ git rebase master 

masterでバージョンを選択したい場合:

$ git checkout --ours codefile.js

featureでバージョンを選択したい場合:

$ git checkout --theirs codefile.js

(もちろんこれは完全なファイル用です)

23
Nitay

git checkoutの使い方から:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

マージの競合を解決するときは、git checkout --theirs some_filegit checkout --ours some_fileを実行して、それぞれファイルを現在のバージョンと着信バージョンにリセットします。

git checkout --ours some_fileまたはgit checkout --theirs some_fileを実行し、ファイルを3-wayマージバージョンのファイルにリセットしたい場合は、git checkout --merge some_fileを実行できます。

2
Joshua Ryan
  • Ours :これはあなたが現在行っている枝です。
  • Theirs :これはあなたの行動に使われるもう一つの枝です。

あなたがbranch release/2.5 にいて、branch feature/new-buttons をマージしている場合、 release/2.5 にある内容がwhat ours を参照します。 /に含まれている内容と 機能/新しいボタン は何の 彼らのもの を指します。マージアクションの間、これはかなり簡単です。

ほとんどの人が陥る唯一の問題はリベースの場合です。通常のマージではなく再ベースを実行すると、役割が入れ替わります。どのようだ?まあ、それはもっぱらリベースが機能する方法によって引き起こされます。そのように動作するようにリベースを考える:

  1. 前回のプル以降に行ったすべてのコミットは、独自のブランチに移動されます。それを BranchX と名付けましょう。
  2. 現在のブランチの先頭をチェックアウトし、ローカルの変更をすべて破棄しますが、その方法では他の人がそのブランチに対してプッシュしたすべての変更を取得します。
  3. BranchX へのコミットはすべて、現在のブランチから順に行われます。
  4. BranchX は再び削除されるため、どの履歴にも表示されなくなります。

もちろん、それは実際に起こっていることではありませんが、それは私にとっては素晴らしいマインドモデルです。そして2と3を見れば、役割が今交換される理由がわかります。 2の時点で、あなたの現在のブランチは変更されていないサーバからのブランチになったので、これは ours (あなたがいるブランチ)になります。行った変更は現在のものではない別のブランチ( BranchX )になります。したがって、これらの変更は(あなたが行った変更であるにもかかわらず) theirs (あなたのアクションで使用される他のブランチ)です。 。

つまり、マージして変更を常に優先させる場合は、gitに常に "ours"を選択するように指示しますが、リベースしてすべての変更を常に優先させたい場合はgitに常に "theirs"を選択するように指示します。

2
Mecki