Как применить git patch из одного хранилища в другое? - PullRequest
71 голосов
/ 31 мая 2009

У меня есть два репозитория, один из которых является основным репозиторием для библиотеки, а другой - это проект, использующий эту библиотеку.

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

Местоположение файла отличается в каждом хранилище.

  • Основной репо: www.playdar.org/static/playdar.js
  • Проект: playlick.com/lib/playdar.js

Я пытался использовать git format-patch -- lib/playdar.js в проекте playlick, а затем git am в основном репозитории playdar, но из-за различий в расположении файла патча возникла ошибка.

Есть ли простой способ применить патч из данного коммита к данному файлу к другому произвольному файлу в другом месте?

Что касается бонусных баллов, что если файл, к которому вы хотите применить патч, отсутствует в репозитории git?

Ответы [ 8 ]

96 голосов
/ 29 июня 2012

Если редактирование файла исправления вручную невозможно или невозможно, это можно сделать с помощью стандартных параметров (доступны в git apply, git format-patch и GNU patch).

  1. -p<n> удаляет n ведущих каталогов из путей в патче.

  2. После обработки -p, --directory=<root> добавляет root к каждому из путей в патче перед применением.

Пример * * тысяча двадцать-одна Итак, для вашего примера, чтобы взять патч, который изначально был на static/playdar.js, и применить его к lib/playdar.js, вы должны выполнить: $ cat patch_file | git am \ -p1 \ # remove 1 leading directory ('static/') --directory='lib/' # prepend 'lib/'

35 голосов
/ 31 мая 2009

Патч, создаваемый git format-patch, представляет собой просто текстовый файл - вы можете редактировать заголовки diff, чтобы он изменял другой путь.

Так, например, он мог бы создать что-то вроде этого:

diff --git a/lib/playdar.js b/lib/playdar.js
index 1234567..89abcde
-- a/lib/playdar.js
++ b/lib/playdar.js

Все, что вам нужно сделать, это изменить lib/playdar.js на static/playdar.js и затем запустить патч через git am"

Исправление должно быть доступно для чтения стандартной утилитой исправления GNU для людей, которые не имеют git ---, но не запускают format-patch с опциями -M, -C и т. Д. Для переименования в этом случае исправления, потому что их поддержка не универсальна.

4 голосов
/ 31 мая 2009

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

Другими словами, добавьте «основное репо» как подмодуль в «проекте». Всякий раз, когда вы фиксируете / толкаете новые вещи в «основном репо», вы просто git pull возвращаете их в «проект».

2 голосов
/ 31 мая 2009

Чтобы завершить ответ Хенрика и получить бонусный балл

что если файл, к которому вы хотите применить исправление, отсутствует в репозитории git?

Если у вас есть доступ к каталогам файла-кандидата для патча, поступающего из git-репозитория, вы можете сначала преобразовать это дерево каталогов / файлов в сам git-репозиторий! ('git init': в конце концов, git-репозиторий - это просто .git в корневом каталоге).
Затем вы установите это репо как подмодуль для вашего основного проекта.

1 голос
/ 29 декабря 2014

Вы можете добавить новый пульт и вытащить из него. Артикул с деталями.

$ cd <path-to-repoB>
$ git remote add repoA <git-URL-for-repoA>
$ git pull repoA
0 голосов
/ 11 декабря 2017

Использование опции --relative для format-patch может улучшить абстракцию (скрыть ненужные сведения о хранилище, из которого был сгенерирован патч).

[repository-with-changes]
git format-patch --relative=(path-to-library) (base-commit-for-patch) ## 'HEAD~1'

Я обнаружил, что опция --3way требуется при применении патча (чтобы избежать ошибки does not exist in index) - ваш пробег может отличаться. Использование --directory=(...), вероятно, необходимо только в том случае, если целевой путь не является корнем хранилища.

[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)

  • format-patch создаст один файл патча для каждого коммита с текущей веткой, начиная с 'base'.

  • Документация для опции --relative, кажется, отсутствует , в некоторых случаях отсутствует , но, похоже, все равно работает (с версии 2.7.4).

0 голосов
/ 03 марта 2015

Вы можете просто временно удалить (переименовать) основной репозиторий.

cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git
0 голосов
/ 12 февраля 2015

Я думаю, что поддерево - лучшее решение для вашей проблемы

Учебник 1

Туориал 2

...