web-dev-qa-db-ja.com

複数のブランチのGitタコマージ順序

私はgitを使用して興味深いことが起こりました。誰かがそれを私に説明して私がよりよく理解できるかどうか疑問に思いました。

複数のブランチ(A、B)をマージする場合、

git merge A B

非早送りとして失敗しますが、

git merge B A

うまくいきました。なぜでしょうか?

38
James Maroney

Aが現在のブランチの厳密な 直接の子 であると仮定しましょう。次に、Bが厳密な直接の子of Aであると想定します。

引数として与えられたヘッドを左から右に処理するツリーに関して増分的に/、しかし独立してタコのマージインデックスへのは、Bを適用してからAを適用しようとすると競合なしに成功しますが、変換を行うと競合が発生します。

git-mergeマニュアルのセクション MERGE STRATEGIES に従います。

octopus
   This resolves cases with more than two heads, but refuses to do a
   complex merge that needs manual resolution.

例えば:

 ~                 $ git init testdir && cd testdir && echo "This is C" > myfile
 Initialized empty Git repository in /home/huitseeker/testdir/.git/

 ~/testdir         $ git add myfile && git commit -m "C" 
 [master (root-commit) f0c8c82] C
  1 files changed, 1 insertions(+), 0 deletions(-)
  create mode 100644 myfile

 ~/testdir(master) $ git checkout -b "A" && echo "This is A1" > myfile
 Switched to a new branch 'A'
 ~/testdir(A)      $ git commit -m "A1" myfile
 [A ac5b51c] A1
  1 files changed, 1 insertions(+), 1 deletions(-)

 ~/testdir(A)      $ git checkout -b "B" && echo "This is B1" >> myfile
 Switched to a new branch 'B'
 ~/testdir(B)      $ git commit -m "B1" myfile
 [B 5bc838c] B1
  1 files changed, 1 insertions(+), 0 deletions(-)

 ~/testdir(B)      $ git checkout master
 Switched to branch 'master'
 ~/testdir(master) $ git merge B A
 Fast-forwarding to: B
 Already up-to-date with A
 Merge made by octopus.
  myfile |    3 ++-
  1 files changed, 2 insertions(+), 1 deletions(-)

 ~/testdir(master) $ git reset --hard HEAD^^^
 HEAD is now at f0c8c82 C
 ~/testdir(master) $ git merge A B
 Fast-forwarding to: A
 Fast-forwarding to: B
 error: Entry 'myfile' would be overwritten by merge. Cannot merge.
 Merge with strategy octopus failed.

 ~/testdir(master) $ cat myfile
 This is A1

確かに、Aに早送りすると、ツリーのように、masterのラベルが押し出されていません。

 ~/testdir(master) $ git status
 # On branch master
 # Changes to be committed:
 #   (use "git reset HEAD <file>..." to unstage)
 #
 #  modified:   myfile
 #

タコのマージが何をするかのコードを見て、私はこれを手動で実行する場合(上記のハッシュを見てください):

 ~/testdir(master) $ git reset --hard f0c8c82
 HEAD is now at f0c8c82 C     
 ~/testdir(master) $ git read-tree -u -m f0c8c82 ac5b51c
 ~/testdir(master) $ git read-tree -u -m f0c8c82 5bc838c
 error: Entry 'myfile' would be overwritten by merge. Cannot merge.

反対方向(merge B A)で、merge-octopusのコードをもう一度見ると、追加しようとしているブランチがすでにツリーにあることを検出しようとします(2番目のcaseforループの)。実際、Aのマージでは、ac5b51c(別名Aの頭)がAとBの共通の祖先であることがわかり、2番目のread-treeを実行せずに異常終了します。

この動作はgitの新しいバージョンと一致しています。v.1.3.1をポイントしましたが、これは私のバージョンでも発生しています。

 ~/testdir(master) $ git --version
 git version 1.7.5.4

tl; dr:タコのマージブランチで個別のファイルにアクセスする

48
Francois G