Как создать Git-патч для определенного коммита?


1233

Мне нужно написать скрипт, который создает патчи для списка номеров коммитов SHA1.

Я пытался использовать git format-patch <the SHA1>, но это создало патч для каждого коммита, начиная с этого SHA1. После того, как было сгенерировано несколько сотен патчей, мне пришлось убить процесс.

Есть ли способ сгенерировать патч только для конкретного SHA1?

Ответы:


1991

Пытаться:

git format-patch -1 <sha>

или

git format-patch -1 HEAD

Согласно приведенной выше ссылке на документацию, -1флаг сообщает git, сколько коммитов должно быть включено в патч;

- <п>

     Подготовьте патчи из верхних коммитов.


Примените патч с помощью команды:

git am < file.patch

211
Применение патча: git apply --stat file.patch# показать статистику. git apply --check file.patch# проверить на наличие ошибок перед применением. git am < file.patch# наконец примените патч.
— Адриан

3
Кажется, он не работает, если последний коммит является слиянием из другой ветви.
— Лекс Ли

2
Чтобы применить патч к файлам, используя окончания строк CRLF:git am --keep-cr < mypatch.patch
— Michael Schmeißer

40
Используйте git am -3 < file.patchдля применения трехстороннего слияния, которое позволит вам разрешать конфликты, используя git mergetoolвпоследствии (или редактирование вручную), найденные здесь .
— Мэтт

6
Эта команда также работает только для определенного файла (-ов) из коммита: git format-patch -1 <sha> path/to/file.jsЭто создаст патч, содержащий только различия в файле .js
— Dombi

282

Для генерации патчей из верхних коммитов из определенного хэша sha1:

git format-patch -<n> <SHA1>

Последние 10 патчей из головы в одном файле патчей:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch

2
пожалуйста, будьте любезны, приведите пример для первой команды
— Касун Сиямбалапития,

1
git format-patch -1 HEADсгенерирует патч для самого последнего коммита
— Шрирам Мурали

1
простите меня за то, что я спросил об этом, поэтому, когда он -2генерирует патчи для двух последних коммитов, это так, и еще одна вещь для пояснения: команда got format-patch -2 HEADтакая же, как строкаgit format-patch HEAD~2
— Kasun Siyambalapitiya

85

Скажем, у вас есть коммит 2 после коммита 1, который вы сможете запустить:

git diff 2 1 > mypatch.diff

где 2 и 1 - хэши SHA.


Спасибо dookehster за ответ. Это означает, что мне нужен сценарий, чтобы найти коммиты, которые предшествовали тем, кто мне интересен. Я надеялся, что смогу избежать этого.
— elle

11
@elle, нет, ты не git diff hash^ hash... "хэш ^" дает предыдущий коммит. (но, конечно, ответ Манойлдса лучше)
— J-16 SDiZ

2
git show HEAD > mypatch.diffв то время как вы на коммите должны сделать то же самое.
— andho

1
@dookehester это правильно или наоборот,git diff 1 2
— Касун Сиямбалапития

1
Это не будет включать любые двоичные файлы в diff.
— stuckj

55

Эта команда (как уже предложено @ Naftuli Tzvi Kay ):

git format-patch -1 HEAD

Заменить HEADна определенный хэш или диапазон.

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

-<n> - Подготовьте патчи из верхних коммитов.

Затем вы можете повторно применить файл исправления в формате почтового ящика:

git am -3k 001*.patch

См: man git-format-patch.


Спасибо! Я думаю, что стоит отметить, что применение патча создаст коммит с сообщением коммита с префиксом [PATCH]. Это легко исправить
— Майк С

2
Феноменальная. OP, вы не приняли это, потому что ...? @MikeS Нет, не больше, чем любой другой gitформатированный патч, по крайней мере, если пользователь применяет его правильно.
— underscore_d

2
@MikeS Я на самом деле не выяснил, почему, но опущенный -kфлаг ( git am -3) исправил эту форму меня (без PATCH[0/10]сообщений коммита). Git версия 2.20.1.windows.1
— Яннис

31
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

Быстрое и простое решение.


5
Также не забудьте позвонить git apply --check patch-file-nameперед применением патча. Это поможет избежать проблем.
— Ямантоние

16

Если вы хотите быть уверенным, что исправление (одиночная фиксация) будет применено поверх определенной фиксации, вы можете использовать новую опцию git 2.9 (июнь 2016 г.) git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

Смотрите коммит bb52995 , коммит 3de6651 , коммит fa2ab86 , коммит ded2c09 (26 апреля 2016 г.) от Xiaolong Ye (``) .
(Слиты Junio C Hamano - gitster- в фиксации 72ce3ff , 23 мая 2016)

format-patch: добавить --baseопцию ' ' для записи информации о базовом дереве

Сопровождающие или сторонние тестировщики могут узнать точное базовое дерево, к которому относится серия исправлений. Научите git format-patch --baseопции ' ' записывать информацию о базовом дереве и добавлять ее в конце первого сообщения (либо сопроводительное письмо, либо первое исправление в серии).

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

«Базовый коммит» отображается как « base-commit:», за которым следует шестнадцатеричный код имени объекта коммита.
«Предварительно установленное исправление» отображается как « prerequisite-patch-id:», за которым следует 40-шестнадцатеричный «идентификатор исправления», который можно получить, пропустив исправление с помощью команды « git patch-id --stable».


Git 2.23 (Q3 2019) улучшит это, потому что « --baseопция» « format-patch» patch-idsнестабильно вычисляла для обязательных патчей, которая была обновлена ​​для вычисления способом, совместимым с « git patch-id --stable».

Смотрите коммит a8f6855 , коммит 6f93d26 (26 апреля 2019 г.) Стивена Бойда ( akshayka) .
(Слиты Junio C Hamano - gitster- в фиксации 8202d12 , 13 июн 2019)

format-patch: сделать --base patch-idвывод стабильным

Мы не очищали контекст каждый раз, когда обрабатывали ханк в patch-idкоде генерации diff.c, но мы делали это, когда генерировали «стабильные» идентификаторы патчей с помощью patch-idинструмента «».

Давайте перенесем эту похожую логику из patch-id.cв, diff.cчтобы мы могли получить тот же хеш, когда мы генерируем идентификаторы исправлений для ' format-patch --base=' типов вызовов команд.


До Git 2.24 (Q4 2019) " git format-patch -o <outdir>" сделал эквивалент " mkdir <outdir>" не " mkdir -p <outdir>", что исправляется.

См. Коммит edefc31 (11 октября 2019 г.) Берта Весарга ( bertwesarg) .
(Слиты Junio C Hamano - gitster- в фиксации f1afbb0 , 18 октября 2019)

format-patch: создать ведущие компоненты выходного каталога

Подписано: Берт Весарг

'git format-patch -o' сделал эквивалент 'mkdir', а не 'mkdir -p', что исправляется.

Избегайте использования ' adjust_shared_perm' в ведущих каталогах, которые могут иметь последствия для безопасности. Достигается путем временного отключения функции config.sharedRepository«лайк» git init.


В Git 2.25 (Q1 2020) " git rebase" не работал должным образом, когда format.useAutoBaseустановлена ​​переменная конфигурации, которая была исправлена.

См. Коммит cae0bc0 , коммит 945dc55 , коммит 700e006 , коммит a749d01 , коммит 0c47e06 (04 декабря 2019 г.) от Denton Liu ( Denton-L) .
(Слиты Junio C Hamano - gitster- в фиксации 71a7de7 , 16 дек 2019)

rebase: исправить format.useAutoBaseполомку

Автор: Кристиан Бизингер.
Подписано: Дентон Лю

При format.useAutoBase = trueзапуске rebase произошла ошибка:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

Исправьте это, всегда передавая --no-baseformat-patch из rebase, чтобы эффект был format.useAutoBaseсведен на нет.


8

Чтобы сгенерировать путь из определенного коммита (не последнего коммита):

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE

5

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

git diff master 766eceb - connections /> 000-mysql-connector.patch


0

С моим ртутным прошлым я собирался использовать:

git log --patch -1 $ID > $file

Но я рассматриваю возможность использования git format-patch -1 $IDсейчас.


-5

Как создать патч только для конкретного SHA1?

Все довольно просто:

Опция 1. git show commitID > myFile.patch

Вариант 2 git commitID~1..commitID > myFile.patch

Примечание. Замените commitIDфактическим идентификатором фиксации (код фиксации SHA1).


3
Вариант 1 совершенно неверен и не связан с вопросом.
— Аншуман Манрал

3
Вариант 2 также является недопустимой командой. Вы получите сообщение об ошибке, например: Смотрите «git --help». Просьба проверить перед публикацией ответов
— Аншуман Манрал
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.