Como gerar um patch git para um commit específico?


1233

Preciso escrever um script que crie patches para uma lista de números de confirmação SHA1.

Eu tentei usar git format-patch <the SHA1>, mas isso gerou um patch para cada confirmação desde o SHA1. Depois que algumas centenas de patches foram geradas, tive que interromper o processo.

Existe uma maneira de gerar um patch apenas para o SHA1 específico?

Respostas:


1990

Tentar:

git format-patch -1 <sha>

ou

git format-patch -1 HEAD

De acordo com o link da documentação acima, o -1sinalizador informa ao git quantos commits devem ser incluídos no patch;

- <n>

     Prepare patches a partir das confirmações mais altas.


Aplique o patch com o comando:

git am < file.patch

211
Aplicando o patch: git apply --stat file.patch# show stats. git apply --check file.patch# verifique se há erros antes de aplicar. git am < file.patch# aplique o patch finalmente.
— Adrian

3
Parece não funcionar se o último commit for uma mesclagem de outro branch.
— Lex Li

2
Para aplicar o patch em arquivos usando terminações de linha CRLF:git am --keep-cr < mypatch.patch
— Michael Schmeißer

40
Use git am -3 < file.patchpara aplicar usando uma mesclagem de três vias que permitirá resolver conflitos usando git mergetoolposteriormente (ou editando manualmente) encontrados aqui .
— Matt

6
Este comando também funciona para apenas um arquivo específico (s) do commit: git format-patch -1 <sha> path/to/file.jsIsto irá criar um patch contendo apenas os diffs para os file.js
— Kristóf Dombi

281

Para gerar os patches a partir dos commits superiores, a partir de um hash sha1 específico:

git format-patch -<n> <SHA1>

Os últimos 10 patches da cabeça em um único arquivo de patches:

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

2
você pode por favor seja gentil o suficiente para fornecer um exemplo para o primeiro comando
— Kasun Siyambalapitiya

1
git format-patch -1 HEADirá gerar patch para o mais recente comprometer
— Sriram Murali

1
perdoem-me por perguntar isso, então quando é -2que geram manchas para a maioria dos últimos 2 commits é, e mais uma coisa para esclarecimentos é o comando got format-patch -2 HEADé o mesmo que a linhagit format-patch HEAD~2
— Kasun Siyambalapitiya

85

Digamos que você tenha cometido o id 2 após o commit 1, você seria capaz de executar:

git diff 2 1 > mypatch.diff

onde 2 e 1 são hashes SHA.


Obrigado dookehster pela resposta. Isso significa que eu preciso do script para encontrar os commits que antecederam aqueles em que estou interessado. Eu esperava poder evitar isso.
— elle

11
@elle, não, você não - git diff hash^ hash . o "hash ^" fornece o commit precedido. (mas, é claro, a resposta de manojlds é melhor)
— J-16 SDiZ

2
git show HEAD > mypatch.diff enquanto você estiver no commit, deve fazer o mesmo.
— andho

1
@dookehester está correto ou é o contrário,git diff 1 2
— Kasun Siyambalapitiya

1
Isso não incluirá nenhum arquivo binário no diff.
— stuckj

55

Este comando (como já sugerido por @ Naftuli Tzvi Kay ):

git format-patch -1 HEAD

Substitua HEADpor hash ou intervalo específico.

irá gerar o arquivo de correção para a confirmação mais recente formatada para se parecer com o formato da caixa de correio UNIX.

-<n> - Prepare os patches a partir dos commits mais altos.

Em seguida, você pode reaplicar o arquivo de patch em um formato de caixa de correio:

git am -3k 001*.patch

Veja: man git-format-patch.


Obrigado! Eu acho que vale a pena notar que a aplicação do patch criará uma confirmação com uma mensagem de confirmação prefixada por [PATCH]. Isso é fácil de corrigir, embora
— Mike S

2
Fenomenal. OP, você não aceitou isso, porque ...? @MikeS Não, não funciona mais do que qualquer outro gitpatch formatado, pelo menos se o usuário o aplicar da maneira correta.
— Underscore_d

2
@ MikeS Eu realmente não investiguei o porquê, mas deixar de fora a -kflag ( git am -3) me corrigiu esse formulário (sem PATCH[0/10]enviar mensagens). Git versão 2.20.1.windows.1
— jannis

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

Solução rápida e simples.


5
Também não se esqueça de ligar git apply --check patch-file-nameantes de aplicar um patch. Isso ajudará a evitar problemas.
— precisa saber é

16

Se você quiser ter certeza de que o patch (confirmação única) será aplicado sobre uma confirmação específica, use a nova opção git 2.9 (junho de 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

Consulte commit bb52995 , commit 3de6651 , commit fa2ab86 , commit ded2c09 (26 de abril de 2016) por Xiaolong Ye (``) .
(Mesclado por Junio ​​C Hamano - gitster- na commit 72ce3ff , 23 de maio de 2016)

format-patch: adicionar '--base ' opção para registrar informações da árvore base

Mantenedores ou testadores de terceiros podem querer saber a árvore base exata à qual a série de patches se aplica. Ensinar git format-patch a '--base opção ' para registrar as informações da árvore base e anexá-las no final da primeira mensagem (a carta de apresentação ou o primeiro patch da série).

As informações da árvore base consistem no "commit de base", que é um commit conhecido que faz parte da parte estável do histórico do projeto em que todos os outros trabalham, e zero ou mais "patches de pré-requisito", conhecidos correções em andamento que ainda não fazem parte do "commit básico" que precisam ser aplicadas sobre o "commit básico" em ordem topológica antes que os patches possam ser aplicados.

O "commit base" é mostrado como " base-commit:" seguido pelo hexadecimal 40 do nome do objeto commit.
Um "patch de pré-requisito" é mostrado como " prerequisite-patch-id:" seguido pelo "id do patch" de 40 hexadecimais, que pode ser obtido passando o patch pelo git patch-id --stablecomando " ".


O Git 2.23 (terceiro trimestre de 2019) melhorará isso, porque a --baseopção " " de " format-patch" calculou os patch-idspatches de pré-requisito de maneira instável, que foi atualizada para calcular de forma compatível com " git patch-id --stable".

Veja commit a8f6855 , commit 6f93d26 (26 abr 2019) por Stephen Boyd ( akshayka) .
(Incorporado por Junio ​​C Hamano - gitster- in commit 8202d12 , 13 jun 2019)

format-patch: tornar a --base patch-idsaída estável

Não estávamos liberando o contexto toda vez que processamos um pedaço no patch-idcódigo de geração diff.c, mas estávamos fazendo isso quando geramos IDs de patch "estáveis" com a patch-idferramenta ' '.

Vamos portar essa lógica semelhante do patch-id.cpara, diff.cpara que possamos obter o mesmo hash quando estivermos gerando IDs de patch para format-patch --base=tipos de chamadas de comando.


Antes do Git 2.24 (quarto trimestre de 2019), " git format-patch -o <outdir>" fazia o equivalente a " mkdir <outdir>" não " mkdir -p <outdir>", que estava sendo corrigido.

Veja commit edefc31 (11 de out de 2019) de Bert Wesarg ( bertwesarg) .
(Incorporado por Junio ​​C Hamano - gitster- in commit f1afbb0 , 18 out 2019)

format-patch: criar componentes principais do diretório de saída

Assinado por: Bert Wesarg

'git format-patch -o' fez o equivalente a 'mkdir' e não 'mkdir -p', que está sendo corrigido.

Evite o uso de ' adjust_shared_perm' nos diretórios principais, que podem ter implicações de segurança. Conseguido desativando temporariamente o ' config.sharedRepository' like ' git init' faz.


Com o Git 2.25 (primeiro trimestre de 2020), " git rebase" não funcionou bem quandoformat.useAutoBase variável de configuração foi definida, o que foi corrigido.

Consulte commit cae0bc0 , commit 945dc55 , commit 700e006 , commit a749d01 , commit 0c47e06 (04 dez 2019) por Denton Liu ( Denton-L) .
(Incorporado por Junio ​​C Hamano - gitster- no commit 71a7de7 , 16 de dezembro de 2019)

rebase: corrigir format.useAutoBasequebra

Reportado por: Christian Biesinger
Assinado por: Denton Liu

Com format.useAutoBase = true, executar a rebase resultou em um erro:

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.

Corrija isso sempre passando --no-basepara o patch de formato a partir da rebase, para que o efeito de format.useAutoBaseseja negado.


8

Para gerar o caminho de uma confirmação específica (não a última confirmação):

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

5

se você quiser apenas diferenciar o arquivo especificado, você pode:

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


0

Com minha formação mercurial, eu usaria:

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

Mas estou pensando em usar git format-patch -1 $IDagora.


-5

Qual é a maneira de gerar um patch apenas para o SHA1 específico?

É bem simples:

Opção 1. git show commitID > myFile.patch

Opção 2. git commitID~1..commitID > myFile.patch

Nota: Substitua commitIDpelo ID de confirmação real (código de confirmação SHA1).


3
A opção 1 é totalmente errada e não está relacionada à questão.
— Anshuman Manral

3
A opção 2 também é um comando inválido. Você receberá um erro como: git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 ~ 1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git: 'a5f4bcaeb7fa7de27ae79d95223328287a7a7a7aaaaaaaaaaaa' Veja 'git --help'. Por favor, verifique antes de postar respostas
— Anshuman Manral
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.