Невозможно выбрать фиксацию с изменением несуществующего файла

Мне интересно, почему git не позволяет выбирать фиксацию, которая вносит изменения в файл, который не существует. Насколько я понимаю, фиксация представляет собой полный снимок рабочего каталога. Таким образом, выбор вишневого коммита, содержащего файл, которого в настоящее время не существует, должен просто создать этот файл, но я вижу, что это не так.

Ниже приведены несколько команд для воспроизведения ситуации, о которой я говорю.

$ git init
Initialized empty Git repository in /home/mzakrze/workspace/tmp/.git/
$ echo "Hello world!" > first_file; git add first_file; git commit -m "Init commit"
[master (root-commit) 7f9478a] Init commit
 1 file changed, 1 insertion(+)
 create mode 100644 first_file
$ echo "Fox jumps over the layz dog" > test; git add test; git commit -m "Commit with a typo"
[master 776387b] Commit with a typo
 1 file changed, 1 insertion(+)
 create mode 100644 test
$ echo "Fox jumps over the lazy dog" > test; git add test; git commit -m "Fix typo"
[master 9ea19df] Fix typo
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git log 
commit 9ea19dfe2597b28eb576e2682e745de3da74733f
Author: mzakrze <[email protected]>
Date:   Sun Apr 11 17:01:13 2021 +0200

    Fix typo

commit 776387b563edba9df2a12c5d1a2fd5bffb10c643
Author: mzakrze <[email protected]>
Date:   Sun Apr 11 17:00:53 2021 +0200

    Commit with a typo

commit 7f9478a83e3938bf57552c1b90ddc7322b1bf315
Author: mzakrze <[email protected]>
Date:   Sun Apr 11 16:59:04 2021 +0200

    Init commit
$ git reset --hard 7f9478a83e3938bf57552c1b90ddc7322b1bf315
HEAD is now at 7f9478a Init commit
$ git cherry-pick 9ea19 # cherry-pick "Fix typo"
error: could not apply 9ea19df... Fix typo
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'

INB4: я не ищу решения, я просто хочу понять, почему git считает, что это конфликт.


person mzakrze    schedule 11.04.2021    source источник
comment
В значительной степени дубликат, например, stackoverflow.com/questions/60847892/   -  person matt    schedule 12.04.2021


Ответы (2)


Помните, что выбор вишни технически представляет собой трехстороннее слияние. Вы запускаете git cherry-pick C для некоторой фиксации C - часто указываемой идентификатором хэша - и Git находит родителя P фиксации C:

  • commit P теперь является базой слияния;
  • ours фиксация - это текущая (HEAD) фиксация; а также
  • theirs фиксация - это фиксация C.

Разница между P и HEAD заключается в том, что рассматриваемый файл был полностью удален. Разница между P и C заключается в том, что содержимое файла было изменено.

Для стандартного алгоритма слияния (git-merge-recursive) это конфликт высокого уровня или уровня дерева: конфликт изменения / удаления. Это конфликт слияния, который нельзя разрешить с помощью -X ours или -X theirs. Таким образом, слияние останавливается на середине, оставляя вас с конфликтом слияния, который вы должны разрешить.

Разрешите конфликт слияния и запустите git cherry-pick --continue, чтобы завершить выбор. Способ разрешения этого конфликта слияния зависит от вас; команда git checkout в ответе larsks в порядке, или вы можете использовать git checkout --theirs test и git add test. Обратите внимание, что при использовании git checkout --ours (неприменимо в данном случае) и git checkout --theirs, Git не отмечает конфликт разрешенным, но при использовании git checkout CHERRY_PICK_HEAD (или необработанного хеш-идентификатора) Git делает пометку конфликта разрешенным. Это связано с особенностями реализации git checkout.

person torek    schedule 11.04.2021

Если вы посмотрите документацию по команде cherry-pick (см., Например, git cherry-pick --help), вы увидите описание: Применить изменения, внесенные некоторыми существующими коммитами. Другими словами, это смотрит на выбранную фиксацию и ее родительский элемент, вычисляет разницу между ними и пытается применить это изменение к вашей текущей ветке.

Изменение, внесенное фиксацией, которую вы пытаетесь cherry-pick, влияет на несуществующий файл, поэтому его нельзя применить.

Если вам просто нужен файл в том виде, в котором он существует в исходной фиксации, вы можете:

git checkout 9ea19 test
person larsks    schedule 11.04.2021