Почему `git checkout -m` успешно выполняется без слияния? - PullRequest
0 голосов
/ 15 января 2019

Git Pocket Guide говорит

Git игнорирует неотслеживаемые файлы при переключении веток, , если только файл существует в целевой ветви ; тогда он прерывается, даже если версии в рабочем дереве и ветви назначения совпадают. Вы можете используйте параметр --merge, чтобы обойти это без необходимости удалять неотслеживаемый файл , только чтобы Git восстановил его через мгновение. В этом случае операция объединения приводит к одному и тому же файлу.

На ветке master, у меня есть отслеживаемый файл hellofile

$ git branch 
  feature2
* master
$ cat hellofile 
hello
$ git status
On branch master
nothing to commit, working tree clean

На ветке feature2, у него нет файла hellofile, и я создаю его, но оставляю его без отслеживания

$ git checkout feature2
$ ls
common  reader  README  writer
$ echo "world" > hellofile

Затем я пытаюсь оформить заказ master. Понятно, что git checkout не удастся, но с -m получится. Но почему git checkout -m удается без слияния? (Я ожидаю файл hellofile с отмеченным конфликтом)

$ git checkout master
error: The following untracked working tree files would be overwritten by checkout:
    hellofile
Please move or remove them before you switch branches.
Aborting
$ git branch
* feature2
  master

$ git checkout -m master
error: Dirty index: cannot merge (dirty: f2f hellofile)
Switched to branch 'master'
$ cat hellofile 
hello

1 Ответ

0 голосов
/ 16 января 2019

Проблема в том, что hellofile не отслеживается в feature2, но существует в master. -m предназначен для обеих веток, имеющих некоторые изменения в отслеживаемом файле. Теперь это изменение может или не может быть организовано, но отслеживается в нашем рабочем дереве. Наоборот, я надеюсь, что имеет смысл, что если бы обе ветви добавили и зафиксировали какую-то версию файла, у нас был бы стандартный конфликт.

Если файл не по крайней мере отслеживается в обеих ветвях, то трехстороннее объединение, похоже, разрешит конфликт как git checkout --ours ... подробнее об этом в разделе для обсуждения.

То есть, делая это в вашем примере,

$ echo "world" > hellofile
$ git checkout -m master

Вы фактически (не на самом деле) говорите игнорировать изменения в неотслеживаемом файле текущих рабочих каталогов. Однако если вы отслеживали hellofile в обеих ветках и внесли изменения,

$ `echo "world" > hellofile"
$ `git add hellofile`

вы бы получили конфликт, который выглядел бы примерно так:

<<<<<<< master
hello
=======
world
>>>>>>> local

Я собираюсь предположить, что это то, для чего вы шли; он был правильно помечен как конфликт слияния. Тем не менее, ваши изменения были перенесены в обе ветви без каких-либо обязательств.


Обсуждение

В документации не говорится, что это предназначено, но ваша проблема явно в поведении. Я думаю, что это, вероятно, упущение / ошибка с их стороны. То, что они, кажется, значат, это

"Однако, с помощью этой опции, трехстороннее слияние между текущей веткой, вашими проиндексированными файлами и новой ветвью завершено, и вы будете в новой ветке."

После прочтения этого поста: Можно ли использовать git diff для неотслеживаемых файлов? , я собираюсь предположить, что на самом деле происходит в схеме слияния то, что файл рабочего каталога на самом деле не имеет Действительный блоб в индексе считается чем-то, что нужно слить, и поэтому для всех намерений и целей «игнорируется».

Редактировать: Вот вопрос, который только что задан, с похожей загадкой: Почему git checkout <<file>> не работает, когда тот же файл находится в индексе?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...