Разрешение конфликта Git с бинарными файлами

464

Я использую Git на Windows (msysgit), чтобы отслеживать изменения для некоторых дизайнерских работ, которые я делал.

Сегодня я работал на другом ПК (с удаленным репо brian) и сейчас пытаюсь объединить сделанные сегодня правки с моей обычной локальной версией на моем ноутбуке.

На моем ноутбуке я использовал git pull brian masterизменения в моей локальной версии. Все было хорошо, кроме основного документа InDesign - это выглядит как конфликт.

Версия на ПК ( brian) - последняя, ​​которую я хочу сохранить, но я не знаю, какие команды говорят репо использовать эту.

Я попытался напрямую скопировать файл на свой ноутбук, но это, кажется, нарушает весь процесс слияния.

Может кто-то указать мне верное направление?

Кевин Уилсон
источник

Ответы:

854

git checkoutпринимает --oursили --theirsвариант для таких случаев, как это. Поэтому, если у вас конфликт слияния, и вы знаете, что просто хотите получить файл из ветви, в которую вы сливаете, вы можете сделать следующее:

$ git checkout --theirs -- path/to/conflicted-file.txt

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

$ git checkout --ours -- path/to/conflicted-file.txt
mipadi
источник
47
Мне пришлось запустить файл 'git reset HEAD path / to / конфликтаted-file.txt' перед использованием --ours, иначе это, похоже, не дало результата.
Цитракс
6
@Zitrax Разбирали ли вы файл после запуска git checkout --ours? Страница руководства предлагает (ИМХО), что checkout --ours / - их удалит изменение из списка «оба измененных, нужно объединить» и добавит его в индекс, и я думаю, что это не правильно. Я считаю, что вам нужно будет бежать git addпосле проверки.
Тим Китинг
15
Примечание: вы все еще хотите сделать «git add конфликтаted-file.txt » и «git commit». Когда я пытался это сделать, сообщение о коммите было предварительно заполнено запиской о конфликте.
Эдвард Фальк
2
Фраза «ветвь, в которую вы объединяетесь» опасно близка к «ветке, в которую вы объединяете», я думаю, что было бы лучше просто отбросить предлог: «ветвь, которую вы объединяете», что также отражало бы команду git (то есть git merge branch_name).
Андрыбак
13
Пара важных моментов, которые всегда отсутствуют в пояснениях к этой теме. При выполнении rebase вместо слияния значения --theirи --oursменяются местами, т. Е. --Their == текущая извлеченная ветвь, а --ours - это ветвь, обычно удаленная ветвь, или спецификация пути, которую вы пытаетесь объединить с текущей филиал. В [space]--[space]опции устраняет неоднозначность на пути спецификацию между именем ветви и путем спецификацией , что и случаются, существует с тем же именем (например , имя существующей ветви «а» и каталог существует под название «ABC»).
BoiseBaked
147

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

git commit -a -m "Fix merge conflict in test.foo"

Обычно Git автоматически выполняет коммитирование после слияния, но когда он обнаруживает конфликты, которые он не может решить самостоятельно, он применяет все обнаруженные патчи и оставляет остальное для разрешения и фиксации вручную. Страница Git Merge Man Page , Git-SVN Crash Course или эта запись в блоге могут пролить свет на то, как она должна работать.

Изменить: см. Пост ниже, вы на самом деле не должны копировать файлы самостоятельно, но можете использовать

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

выбрать версию файла, который вы хотите. Копирование / редактирование файла будет необходимо, только если вы хотите смешать обе версии.

Пожалуйста, отметьте ответ mipadis как правильный.

Волька
источник
1
Спасибо за это. Я не был уверен, есть ли какой-то встроенный способ пометить файл как «правильный». Объясняет, почему я не смог найти несуществующую команду, хотя!
Кевин Уилсон
Да, это немного не интуитивно понятно - что-то вроде git resolution было бы неплохо, но также было бы дополнительным шагом ...
VolkA
120

Вы также можете преодолеть эту проблему с

git mergetool

что заставляет gitсоздавать локальные копии конфликтующего двоичного файла и порождать им редактор по умолчанию:

  • {conflicted}.HEAD
  • {conflicted}
  • {conflicted}.REMOTE

Очевидно, что вы не можете с пользой редактировать двоичные файлы в текстовом редакторе. Вместо этого вы копируете новый {conflicted}.REMOTEфайл, {conflicted}не закрывая редактор. Затем, когда вы закроете редактор, gitвы увидите, что неокрашенная рабочая копия была изменена, и ваш конфликт слияния разрешен обычным способом.

RobM
источник
8
Если файлы имеют большой размер или вы вообще не хотите рисковать открытием двоичного файла в текстовом редакторе, вы можете нажать ctrl + c в приглашении mergetool (" Hit return to start merge resolution tool"), и git оставит дополнительные файлы на месте. Затем вы можете изменить их или объединить во внешнем инструменте (полезно для двоичных форматов документов, таких как LibreOffice / OpenOffice / MSWord) и сохранить результат обратно в исходное имя файла. Чтобы сообщить git, что конфликт разрешен, git addукажите исходное имя файла, и вы можете закончить коммит слияния.
Феликс
18

Чтобы решить, сохранив версию в текущей ветке (игнорируйте версию из ветви, в которую вы объединяете), просто добавьте и зафиксируйте файл:

git commit -a

Чтобы решить эту проблему, перезаписав версию в текущей ветке версией из ветви, в которую вы объединяете, вам нужно сначала извлечь эту версию в рабочий каталог, а затем добавить / зафиксировать ее:

git checkout otherbranch theconflictedfile
git commit -a

Объяснено более подробно

Джошуа Фланаган
источник
1
Я предпочитаю этот вариант перед принятым ответом, потому что он более интуитивен, особенно учитывая, что значение этих «--ours» и «--theirs» поменяется местами в случае перебазировки.
Энтони Хэтчкинс
11

Ответ Мипади мне не помог, мне нужно было сделать следующее:

git checkout --ours path / to / file.bin

или, чтобы сохранить версию в:

git checkout - их путь / в / file.bin

тогда

git add path / to / file.bin

И тогда я смог снова выполнить «git mergetool» и перейти к следующему конфликту.

крис
источник
6

Из git checkoutдокументов

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
При проверке путей из индекса проверьте этап № 2 ( ours) или № 3 (theirs ) для неотключенных путей.

Индекс может содержать необъединенные записи из-за предыдущего неудачного слияния. По умолчанию, если вы попытаетесь извлечь такую ​​запись из индекса, операция извлечения не будет выполнена и ничего не будет извлечено. Использование -fбудет игнорировать эти необработанные записи. Содержимое определенной стороны слияния можно извлечь из индекса с помощью --oursили --theirs. С помощью -mизменений, внесенных в файл рабочего дерева, можно отказаться, чтобы заново создать исходный конфликтующий результат слияния.

user456814
источник
4

Я столкнулся с подобной проблемой (желая получить коммит, включающий некоторые двоичные файлы, которые вызывали конфликты при объединении), но натолкнулся на другое решение, которое может быть полностью выполнено с использованием git (то есть не нужно вручную копировать файлы). Я подумал, что включу это сюда, чтобы, по крайней мере, я мог вспомнить это в следующий раз, когда мне это понадобится. :) Шаги выглядят так:

% git fetch

Он выбирает последние коммиты из удаленного репозитория (вам может потребоваться указать имя удаленной ветви, в зависимости от вашей настройки), но не пытается объединить их. Записывает коммит в FETCH_HEAD

% git checkout FETCH_HEAD stuff/to/update

Это берет копию двоичных файлов, которые я хочу, и перезаписывает то, что находится в рабочем дереве с версией, извлеченной из удаленной ветви. git не пытается выполнить слияние, поэтому вы просто получаете точную копию двоичного файла из удаленной ветви. Как только это будет сделано, вы можете добавить / зафиксировать новую копию, как обычно.

Брайан Вебстер
источник
4

Эта процедура предназначена для разрешения конфликтов двоичных файлов после того, как вы отправили запрос на извлечение в Github:

  1. Итак, на Github вы обнаружили, что ваш запрос на удаление конфликтует с двоичным файлом.
  2. Теперь вернитесь в ту же ветку git на вашем локальном компьютере.
  3. Вы (а) заново создаете / перестраиваете этот двоичный файл снова и (б) фиксируете полученный двоичный файл в той же самой ветке git.
  4. Затем вы снова толкаете эту ветку Git в Github.

На Github, по вашему запросу, конфликт должен исчезнуть.

Дэвид М Ли
источник
Это именно та процедура, которая мне нужна
Huifang Feng
2

Если двоичный файл представляет собой нечто большее, чем DLL или что-то, что можно редактировать напрямую например, как изображение, или смешанный файл (и вам не нужно выбрасывать / выбирать один или другой файл), реальное слияние будет выглядеть примерно так:

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

и сравни их.

Если нет инструмента сравнения для сравнения ваших файлов, тогда, если у вас есть оригинальный генератор файла bin (то есть, существует редактор для него ... как, например, blender 3d, вы можете вручную проверить эти файлы, а также посмотрите журналы и спросите другого человека, что вы должны включить) и выполните вывод файлов с помощью https://git-scm.com/book/es/v2/Git-Tools-Advanced-Merging#_manual_remerge

$ git show :1:hello.blend > hello.common.blend $ git show :2:hello.blend > hello.ours.blend $ git show :3:hello.blend > hello.theirs.blend

tyoc213
источник
1

Я столкнулся с двумя стратегиями управления diff / слиянием бинарных файлов с помощью Git на windows.

  1. Git Tortoise позволяет вам настраивать инструменты сравнения / слияния для разных типов файлов в зависимости от их расширений. См. 2.35.4.3. Дополнительные настройки Diff / Merge http://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html . Эта стратегия, конечно, зависит от наличия подходящих инструментов сравнения / слияния.

  2. Используя атрибуты git, вы можете указать инструмент / команду для преобразования вашего двоичного файла в текст, а затем позволить своему стандартному инструменту diff / merge сделать свое дело. См. Http://git-scm.com/book/it/v2/Customizing-Git-Git-Attributes . В статье даже приведен пример использования метаданных для сравнения изображений.

Я получил обе стратегии для работы с бинарными файлами программных моделей, но мы пошли с черепаховым мерзавцем, так как конфигурация была простой.

BoJohDoh
источник
0

Я использую Git Workflow для Excel - приложение https://www.xltrail.com/blog/git-workflow-for-excel, чтобы решить большинство проблем слияния, связанных с моими двоичными файлами. Это приложение с открытым исходным кодом помогает мне продуктивно решать проблемы, не затрачивая слишком много времени, и позволяет мне без проблем выбрать нужную версию файла.

Сиддхартха Тота
источник
0

мой случай выглядит как ошибка .... с помощью GIT 2.21.0

Я сделал тянуть ... он жаловался на двоичные файлы:

warning: Cannot merge binary files: <path>
Auto-merging <path>
CONFLICT (content): Merge conflict in <path>
Automatic merge failed; fix conflicts and then commit the result.

И тогда ни в одном из ответов здесь не было никакого результата, который имел бы смысл.

Если я посмотрю, какой файл у меня сейчас ... это тот, который я отредактировал. Если я сделаю либо:

git checkout --theirs -- <path>
git checkout --ours -- <path>

Я получаю вывод:

Updated 0 paths from the index

и у меня все еще есть моя версия файла. Если я произвожу, а затем оформлю заказ, вместо него будет 1, но он все равно даст мне мою версию файла.

Git Mergetool говорит

No files need merging

и Git статус говорит

    All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

Один из вариантов - отменить коммит ... но мне не повезло, у меня было много коммитов, и этот плохой был первым. Я не хочу тратить время на это.

так что решить это безумие

Я только что побежал

git commit

который теряет удаленную версию и, вероятно, тратит некоторое пространство на хранение дополнительного двоичного файла ... тогда

git checkout <commit where the remote version exists> <path>

который возвращает мне удаленную версию

затем снова отредактировал файл ... и затем подтвердил и нажал, что, вероятно, снова означает, что тратится место на другую копию двоичного файла.

Питер
источник
В моем случае после попытки git checkout --ours <path>я получил Updated 0 paths from the index . Я исправил это с помощью git add <path>команды, которая делает то же самое.
Андрей