Почему у этой вишни есть конфликт?

Я знаю, что 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? Каковы детали работы вишневого мешка в этом случае?

Ответ 1

Повторите попытку своей вишни после:

git config merge.conflictstyle diff3

Вы получите более подробный diff:

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

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

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

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

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

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

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

  • команда upstream (destination) commit "удалила 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", переданной в стратегия объединения по умолчанию recursive)

Ответ 2

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

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

Из git -scm documentation