Как создать 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.