Как применить патч git от одного репозитория к другому?
У меня есть два репозитория, один из них является основным репо для библиотеки, а другой - проектом с использованием этой библиотеки.
Если я исправлю проект subervient, мне бы хотелось, чтобы этот патч был обращен вверх по течению.
В каждом репозитории расположение файлов различно.
- Главное репо:
www.playdar.org/static/playdar.js
- Проект:
playlick.com/lib/playdar.js
Я попытался использовать git format-patch -- lib/playdar.js
в проекте playlick, а затем git am
в основном репортаже playdar, но разные расположения файлов в файле патча вызвали ошибку.
Есть ли простой способ применить патч от данной фиксации в заданном файле к другому произвольному файлу в другом месте?
Что касается бонусных очков, что делать, если файл, к которому вы хотите применить патч, не находится в репозитории git?
Ответы
Ответ 1
Если ручное редактирование файла исправления не может быть и речи, это может быть сделано со стандартными опциями (доступно в git apply
, git format-patch
и GNU patch
).
-
-p<n>
удаляет n
ведущие каталоги из путей в патче.
-
После обработки -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/'
Ответ 2
Патч, созданный 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 patch для людей, у которых нет git
---, но не запускайте format-patch
с параметрами -M
, -C
и т.д. для создания переименования патчи в этом случае, потому что поддержка для них не универсальна.
Ответ 3
Предполагая, что оба проекта представляют собой проекты git, это похоже на то, что подмодули будут идеально подходят вам. Это позволяет проекту git динамически связываться с другим проектом git, в основном выпекая репо git прямо внутри другого репозитория git, оба имеют свои собственные жизни.
Другими словами, добавьте "основное репо" в качестве подмодуля в "проекте". Всякий раз, когда вы совершаете/нажимаете новые вещи в "основном репо", вы просто git pull
возвращаете их обратно в "проект".
Ответ 4
Чтобы завершить ответ Хенрика, и перейти к бонусной точке
что, если файл, к которому вы хотите применить патч, находится не в репозитории git?
Если у вас есть доступ к каталогам кандидата файлов для патча из репозитория git, вы можете сначала преобразовать это дерево каталогов/файлов в репозиторий git! ('git init
': репозиторий git - это всего лишь .git в корневом каталоге).
Затем вы установите этот репо как подмодуль для своего основного проекта.
Ответ 5
Вы можете добавить новый пульт и вытащить его. Статья с подробностями.
$ cd <path-to-repoB>
$ git remote add repoA <git-URL-for-repoA>
$ git pull repoA
Ответ 6
Я думаю, что поддерево - лучшее решение для вашей проблемы
Учебное пособие 1
Tuorial 2
Ответ 7
Вы можете просто временно удалить (переименовать) основной репозиторий.
cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git
Ответ 8
Использование опции --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).