У меня два репозитория. В одном я вношу изменения в файл ./hello.test
. Я фиксирую изменения и создаю патч из этого коммита с помощью git format-patch -1 HEAD
. Теперь у меня есть второй репозиторий , который содержит файл , который имеет то же содержание , как hello.test но помещается в другом каталоге под другим именем: ./blue/red/hi.test
. Как мне применить к hi.test
файлу вышеупомянутый патч ? Я пробовал, git am --directory='blue/red' < patch_file
но он, конечно, жалуется, что файлы имеют разные имена (я думал, что Git не заботится?). Я знаю, что, вероятно, мог бы отредактировать разницу для применения к этому конкретному файлу, но я ищу командное решение.
101
Ответы:
Вы можете создать патч с помощью,
git diff
а затем применить его с помощьюpatch
утилиты, которая позволяет указать файл, к которому вы хотите применить разницу.Например:
источник
am
илиapply
, но я не могу этого найти. Если вы обнаружите, что часто дублируете изменения, может быть лучшее решение с использованием подмодулей или того, что ваш язык по выбору предоставляет для совместного использования кода (например, в Ruby вы можете извлечь повторяющийся код как драгоценный камень).Существует простое решение, которое не требует ручного редактирования патчей или внешнего скрипта.
В первом репозитории (это также может экспортировать диапазон фиксации, используйте,
-1
если вы хотите выбрать только одну фиксацию):Во втором репозитории:
Вместо использования
--relative
ingit format-patch
другим решением является использование-p<n>
опции ingit am
для удаленияn
каталогов из пути патчей, как упоминалось в ответе на аналогичный вопрос .Также можно запустить
git format-patch --relative <committish>
без--stdout
, и он будет генерировать набор.patch
файлов. Эти файлы затем могут быть загружены напрямую сgit am
помощьюgit am --directory blue/red/ path/to/*.patch
.источник
--directory
опция требует указать полный путь к каталогу относительно корня репо; что-то вроде--directory=./
while chdir'd в подкаталог в репо не сработает.--3way
помогает сdoes not exist in index
:git am --3way --directory (relative-path) (patch)
-k
ключ в обеих командах, чтобы не удалять первую строку сообщения фиксации.--3way
не только помогает с ошибками «не существует в индексе» (как указано в @nobar), но также позволяет вам аккуратно обрабатывать конфликты слияния. Вместо того, чтобы оставлять конфликтующие файлы нетронутыми, добавляется блок конфликта, который затем может быть разрешен.Отвечая на свой вопрос с помощью скрипта, который делает именно это: https://github.com/mprpic/apply-patch-to-file
Вместо того, чтобы изменять файл патча вручную, он запрашивает у пользователя целевой файл, изменяет патч и применяет его к репо, в котором вы сейчас находитесь.
источник
Основываясь на ответе @georgebrock, вот решение, которое я использовал:
Сначала создайте файлы патчей как обычно (например
git format-patch commitA..commitB
).Затем убедитесь, что ваш целевой репозиторий чист (в нем не должно быть измененных или неотслеживаемых файлов), и примените такие патчи:
Для каждого файла патча вы получите сообщение об ошибке типа «ошибка: XYZ не существует в индексе». Теперь вы можете применить этот файл патча вручную:
Вы должны выполнить эти три шага для каждого файла исправления.
Это сохранит исходное сообщение фиксации и т. Д. Без необходимости использования какой-либо специальной
git format-patch
команды или редактирования файлов патча.источник
git format-patch -1 commitA --stdout > thing.diff
; (2) Отредактируйте файл патча, пока он не сделает то, что мне нужно; (3) Текст для фиксации,git am --3way thing.diff
который имеет то преимущество, что вы можете принять части исправления, которые применяются чисто, и использоватьgit
стандартный процесс разрешения конфликтов для частей, которые не применяются .Я понимаю, что в вашей ситуации эти два файла совершенно одинаковы, поэтому исправление, скорее всего, будет успешным.
Однако, если вы хотите применить патч к подобному, но не точно тому же файлу, или вы хотите выполнить интерактивное исправление, вы будете использовать трехстороннее слияние.
Допустим, вы изменили файл
A
, обозначим егоA~1
как предыдущую версию, и вы хотите применить разницу междуA~1
кA
к файлуB
.Откройте инструмент трехстороннего слияния, например Beyond Compare, путь левой панели равен
A
, средняя панель является общим предком, так что путь естьA~1
, путь правой панелиB
. Затем нижняя панель показывает результат применения различий междуA~1
кA
в файлB
.Следующий рисунок иллюстрирует эту идею.
источник
К вашему сведению: недавно у меня были проблемы с попыткой загрузить патч из Github и применить его к локальному файлу (что было «переопределением» в новом месте).
git am
не применил бы исправление, потому что файл был «не в индексе» или «грязный». Но я обнаружил, что простаяpatch
команда может применить патч. Мне было предложено указать имя файла, который нужно исправить.В любом случае, работа сделана ...
источник