2016-08-10 8 views
16

Я знаю, что git cherry-pick - это команда, использующая для применения изменений указанной фиксации, но я думаю, что просто не понимаю, как она работает.Почему у этой вишни есть конфликт?

Давайте предположим, что акт репо так:

git init 

echo a>a 
git add .; git commit -am 'master add line a' 

git checkout -b dev 
echo b>>a 
git commit -am 'dev add line b' 
echo c>>a 
git commit -am 'dev add line c' 

git checkout master 

git cherry-pick dev 

Я думал cherry-pick команда будет хорошо работать и изменить файл a в:

a 

c 

, но на самом деле я получил следующее сообщение:

error: could not apply 08e8d3e... dev add line c 
hint: after resolving the conflicts, mark the corrected paths 
hint: with 'git add <paths>' or 'git rm <paths>' 
hint: and commit the result with 'git commit' 

И затем я запускаю:

git diff 

выход:

diff --cc a 
index 7898192,de98044..0000000 
--- a/a 
+++ b/a 
@@@ -1,1 -1,3 +1,6 @@@ 
    a 
++<<<<<<< HEAD 
++======= 
+ b 
+ c 
++>>>>>>> 11fff29... abc 

Так что мой вопрос: Почему существует конфликт, как Git-Diff шоу? Каковы детали работы вишневого затвора в этом случае?

+0

Git cherry pick - это способ выбора и применения отдельных коммитов из другой ветви на текущую ветку. По существу, происходит слияние одного коммита, поэтому вы можете получить конфликты. Нет ничего плохого в том, что вы видите. –

+0

@TimBiegeleisen Но если я запускаю 'git merge dev', нет конфликта и показывает, что я успешно слиял ... – huachengzan

+0

' git cherry-pick dev' даже не имеет смысла для меня, потому что вы указываете название ветви довольно чем фиксация. –

ответ

21

Попробуйте снова вишневый-забрать после:

git config merge.conflictstyle diff3 

Вы получите более подробную диф:

<<<<<<< HEAD 
||||||| parent of 5b2a14c... dev add line c 
b 
======= 
b 
c 
>>>>>>> 5b2a14c... dev add line c 

Это показывает, что, при применении исправления патча Представлено руководством dev (b и c), Гит не знает об общем предке; это сдвинуто:

  • непосредственный родитель из вишневого взял обязательство (показывая, что он добавляет строку «c„после строки“b»)
  • назначения фиксации (который не показывает никакой линии b вообще поверх которого он мог применить добавленное изменение «c»)

Следовательно, конфликт.

Cherry-picking не похож на merge (который ищет merge-base).

Cherry-picking принимает фиксацию, а применяет изменение, которое вводит.

Здесь внесенное изменение: добавить c сверху b.
И адресат совершить не b вообще, так что для Git:

  • вверх по течению (назначения) коммит «удалены b» (или никогда не имели его в первую очередь, что в данном случае, но Git этого не знает)
  • Исходный коммит имеет b, поверх которого добавляется c.

Насколько Git знает, когда пытаемся применить этот патч (и это все git cherry-pick делает:. Применить патч Он не ищет историю вишни совершить на всех), то есть конфликт: одновременная модификация.

Если вы уверены в том, как разрешение должно идти, вы можете сделать:

> git cherry-pick -Xtheirs dev 
[master 7849e0c] dev add line c 
Date: Wed Aug 17 08:25:48 2016 +0200 
1 file changed, 2 insertions(+) 

Тогда вы увидите b и c прибавляются к оригиналу фиксации, без какого-либо конфликта (так как вы указали, как разрешить его с помощью опции «-Xtheirs», переданной в default merge strategy recursive)

+0

Кстати, сообщение об ошибке конфликта переписывается и обсуждается по мере того, как мы говорим: http://marc.info/?t=146956231900001&r=1&w=2 – VonC

+0

вы про, ура –

+0

* «непосредственный родитель из вишневого commit (показывая, что он добавляет строку 'c'after строка' b ') "* - это подозрение, которое у меня было для способа его работы, но я также подумал, что git будет достаточно умным, чтобы признать, что это было на последней строке файл, чтобы он не конфликтует. Git всегда откладывает до ** линии выше ** для размещения? –

-1

Технически, поскольку вы редактируете одну и ту же строку одного и того же файла в разных ветвях, Git видит это как конфликт. Cherrypicking, хотя технически не «операция слияния», все еще ищет те же типы конфликтов и просит их разрешить их.

Для противоречивых путей индексный файл записывает до трех версий, как описано в разделе «ИСТИНА MERGE» git-merge [1]. Файлы рабочих деревьев будут содержать описание конфликта, заключенного в скобки с помощью обычных маркеров конфликта. < < < < < < < и >>>>>>>.

От git-scm documentation

+2

Хм ... Я не думаю, что у меня есть одна и та же строка того же файла, просто добавьте несколько строк в конец файла. – huachengzan

+3

Не знаю, почему этот ответ поднял два оборота за последние несколько минут: это не объясняет, как получается вишневый выбор, учитывая, что происходит параллельное изменение. В нем указывается только очевидное (т. Е. «Одновременное изменение означает конфликт», а если конфликты Git требуют, чтобы вы его разрешили »). Весь вопрос: «Как Гит приходит к выводу, что происходит параллельное изменение?». – VonC