Git ребаз и проблемы слияния с символическими ссылками - PullRequest
0 голосов
/ 05 февраля 2019

Во время git rebase или git merge символические ссылки, кажется, преобразуются в простые файлы.

Я столкнулся со следующей проблемой с символическими ссылками при запуске git rebase master в ветви.

Во-первых, немного предыстории:

  • master не содержал рассматриваемых символических ссылок, но содержал все цели символических ссылок.
  • Рассматриваемые символические ссылки быливсе добавляются в ветку за один коммит.

Во время ребазинга я получил «CONFLICT (add/add): Merge conflict in ...» для каждой символической ссылки.Когда я делал git ls-files --stage для каждой предполагаемой символической ссылки, он показывал режим как 100644 (т.е. простой файл, а не символическая ссылка).Я написал простой сценарий оболочки, чтобы заменить каждый из этих текстовых файлов необходимой символической ссылкой, добавил их в индекс и продолжил перебазирование.

Некоторое время назад я заметил набор символических ссылок, которые я хотел быдобавленный в предыдущей предыдущей ветви преобразовался в простые текстовые файлы на master, каждый из которых содержал только путь к тому, что ранее было целью ссылки;В то время я подозревал, что изменение произошло во время слияния ветки с мастером, и теперь я более уверен.

Итак, мои вопросы:

  1. Есть лиспособ заставить Git лучше обрабатывать символические ссылки во время слияния?
  2. Если git rebase или git merge выдает конфликты и заменяет символические ссылки на простые файлы, есть ли лучший способ решить проблему, чем удаление каждогофайл и воссоздание символической ссылки?

1 Ответ

0 голосов
/ 05 февраля 2019

Есть ли способ заставить Git лучше обрабатывать символические ссылки во время слияния?

Не совсем, нет.Если два добавленных файла имеют одинаковое содержимое, Git вообще не называет это конфликтом (я только что это проверил), и слияние завершается успешно.

В конечном счете, проблема заключается в том, чтосимволическая ссылка - это файл данных, целью которого является ссылка, которая представляет собой всего одну строку (без завершающей строки!).Однако операционная система с достаточной связью хранит эти данные специально и может только обращаться к ним специально.(Windows обычно не достаточно link-y и вместо этого сохраняет его в виде простого текстового файла.) Итак, предположим, что две символические ссылки в двух файлах для объединения, которые находятся в двух коммитах, отличаются от исходной символической ссылки.в исходном коммите:

merge base: file foo should be a symlink to bar/baz
--ours:     file foo should be a symlink to our/name
--theirs:   file foo should be a symlink to different/path

Поскольку все это одна строка, Git не может объединить эти два изменения, которые оба изменяют одну и ту же исходную строку - строка 1 является строкой only - изфайл базы слияния.Вы должны объединить их вручную.

(В вашем случае вообще нет записи на этапе 1, только этапы 2 и 3, следовательно, «конфликт добавления / добавления», который я называю максимумом конфликт уровня , который никогда не входит в низкоуровневый код слияния файлов. Приведенное ниже описание предназначено в большей степени для случаев конфликтов низкого уровня, которые также могут возникать, и где -X ours или -X theirs могут работать.конфликты высокого уровня, Git никогда не попадает в код обработки -X.)

Когда я сделал git ls-files --stage для каждой предполагаемой символической ссылки, он показывал режим как 100644 (т.е. простой файл, а не символическая ссылка).

Возможно, это ошибка.Замечу, что когда я попробовал это в качестве эксперимента, я не получил:

$ git ls-files --stage
100644 79f977c119cd6951428b04565177cb4e53dd4bc3 0       README
100644 fa49b077972391ad58037050f2a75f74e3671e92 0       newfile
120000 1b407f24bddc88f87d93302f462251bf881acbc9 2       newlink
120000 1de565933b05f74c75ff9a6520af5f9f8a5a2f1d 3       newlink

Обратите внимание на строки mode 120000 здесь.Символическая ссылка остается символической ссылкой и в моем рабочем дереве:

$ ls -l newlink
lrwxr-xr-x  1 torek  torek   9 Feb  5 00:55 newlink -> newtarget

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

(я ожидаю, что git mergetool приведет к извлечению этих двух файлов в виде простых файлов:

$ git checkout-index --temp --stage 2 newlink
.merge_link_OzyiFR      newlink

, поэтому, если вы используете git mergetool, это ошибка git mergetool здесьДействительно, но это не должно быть в состоянии установить режим ввода индекса на 100644.)

Если git rebase или git merge вызывает конфликты и изменяет символические ссылки на простые файлы,Есть ли лучший способ решить проблему, чем удаление каждого файла и воссоздание символической ссылки?

Не совсем, нет.Вы должны выбрать , какую ссылку (нашу или их), чтобы отдать предпочтение, если либо одно, либо даже третье значение (возможно, возвращаясь к базовой версии слияния или к еще одному пути).

Обратите внимание, что не получит конфликт слияния, если только одна «сторона» (наша или их) изменит цель ссылки.В этом случае либо база слияния с нашей совпадает, поэтому Git принимает их изменение, либо база слияния с их совпадает, поэтому Git принимает наши изменения - точно так же, как и для любого обычного файла.(См. раздел трехстороннего слияния git read-tree документации .)

Логически -X ours или -X theirs должны разрешать конфликт автоматически, но только в случаенастоящее трехстороннее слияние.Когда возникает конфликт добавления / добавления (поскольку цели двух символических ссылок в двух коммитах с подсказками различаются, а символическая ссылка вообще отсутствует в базе), мы никогда не доберемся до этой точки, и -X не сможет помочь.

...