Introdução
O git patch é uma ferramenta poderosa para compartilhar mudanças em seu código-fonte sem a necessidade de um repositório remoto. Ele permite que você “empacote” commits ou alterações não versionadas em um arquivo de texto simples (.patch) que pode ser enviado por e-mail, transferido via USB, ou compartilhado de qualquer outra forma, e então aplicado por outra pessoa em seu próprio repositório Git.
É extremamente útil em cenários como:
- Compartilhamento de alterações com colaboradores que não têm acesso direto ao seu repositório.
- Revisão de código offline.
- Aplicação de “hotfixes” rapidamente.
- Migração de commits entre branches ou repositórios independentes.
Neste guia, exploraremos como criar e aplicar patches, tanto de commits já existentes quanto de alterações que ainda não foram “staged” ou commitadas.
Criando Patches de Commits (git format-patch)
Quando você precisa compartilhar um ou mais commits que já estão no seu histórico, git format-patch é a ferramenta ideal. Ele gera arquivos .patch formatados como e-mails, o que é útil para sistemas de revisão de código baseados em e-mail, mas também funciona perfeitamente para aplicação manual.
Um único commit
Para criar um patch de um único commit, você pode usar o SHA do commit ou a referência de HEAD com um tilde ~.
git format-patch -1 <SHA_DO_COMMIT>
# Ou para o último commit
git format-patch -1 HEAD
Exemplo:
Se você tem o commit abcde123 que deseja compartilhar:
git format-patch -1 abcde123
Isso criará um arquivo como 0001-Minha-nova-funcionalidade.patch.
Uma sequência de commits
Para criar patches de uma série de commits, você precisa especificar o ponto de partida (o commit anterior ao primeiro que você quer no patch) e o ponto final.
git format-patch <SHA_DO_COMMIT_ANTERIOR_AO_PRIMEIRO>..<SHA_DO_ULTIMO_COMMIT>
# Ou do último N commits
git format-patch -N
Exemplo: Suponha que seu histórico de commits seja:
A -- B -- C -- D -- E (HEAD)
Você quer criar patches para os commits C, D e E. O commit anterior ao primeiro que você quer é B.
git format-patch B..E
# Ou, se B for o terceiro commit antes de HEAD:
git format-patch -3
Isso gerará três arquivos: 0001-Commit-C.patch, 0002-Commit-D.patch, 0003-Commit-E.patch.
Visualização do Histórico e Patches:
Seu histórico:
commit F (novo)
commit E (alteração Z) <-- Último commit a ser "format-patch"
commit D (alteração Y) <-- Segundo commit
commit C (alteração X) <-- Primeiro commit
commit B (base)
commit A (inicial)
Comando: git format-patch B..E
Resulta em arquivos .patch contendo C, D, E.
Aplicando Patches de Commits (git am)
Para aplicar patches criados com git format-patch, a ferramenta mais robusta é git am (apply mail-box). Ela é projetada para aplicar patches com metadados de commit (autor, data, mensagem) e tentar reproduzir o commit original.
Aplicando um único patch
git am <CAMINHO_DO_ARQUIVO_PATCH>
Exemplo:
git am 0001-Minha-nova-funcionalidade.patch
Aplicando múltiplos patches
Você pode aplicar múltiplos patches de uma vez, especificando os arquivos ou um diretório contendo-os:
git am 0001-Commit-C.patch 0002-Commit-D.patch 0003-Commit-E.patch
# Ou de um diretório
git am /caminho/para/patches/*.patch
Lidando com Conflitos
Se houver conflitos durante a aplicação do patch, git am pausará e informará sobre os arquivos conflitantes.
- Resolva os conflitos: Edite os arquivos indicados para resolver as diferenças.
- Adicione os arquivos resolvidos:
git add <ARQUIVO_CONFLITANTE> - Continue a aplicação:
git am --continue
Se você decidir abortar a aplicação do patch (e desfazer quaisquer alterações que ele já tenha aplicado), use:
git am --abort
Criando Patches de Alterações Não Versionadas (git diff)
Às vezes, você tem alterações no seu diretório de trabalho (staged ou unstaged) que ainda não foram commitadas e deseja compartilhá-las. git diff é a ferramenta para isso, mas o patch gerado não contém os metadados de um commit.
Alterações no diretório de trabalho (unstaged)
Para criar um patch das alterações que você fez mas ainda não adicionou ao staging area (não usou git add):
git diff > meu_patch_nao_staged.patch
Alterações “staged” (prontas para commit)
Para criar um patch das alterações que você adicionou ao staging area (git add), mas ainda não commitou:
git diff --staged > meu_patch_staged.patch
# Ou
git diff --cached > meu_patch_staged.patch
Alterações entre dois branches ou commits
Você também pode gerar um diff entre quaisquer dois pontos no histórico do Git.
git diff <BRANCH_OU_COMMIT_1> <BRANCH_OU_COMMIT_2> > diff_entre_branches.patch
Exemplo:
git diff main feature-branch > diff_feature_vs_main.patch
Aplicando Patches de git diff (git apply)
Patches gerados por git diff são mais simples e não contêm os metadados de commit. Para aplicá-los, você usa git apply. Esta ferramenta tenta aplicar as mudanças no seu diretório de trabalho, mas não cria um commit automaticamente.
git apply <CAMINHO_DO_ARQUIVO_PATCH>
Exemplo:
git apply meu_patch_nao_staged.patch
Opções úteis com git apply
--check: Verifica se o patch pode ser aplicado sem erros, sem realmente aplicá-lo.git apply --check meu_patch.patch--reject: Se o patch não puder ser aplicado limpo, as partes que falharem serão salvas em arquivos.rej(reject) para inspeção manual.git apply --reject meu_patch.patch--3way: Tenta uma fusão de três vias se houver conflitos, similar agit merge.git apply --3way meu_patch.patch
Lidando com Conflitos (git apply)
Ao contrário de git am, git apply não pausa para resolução de conflitos. Se houver conflitos, ele falhará e, dependendo das opções (--reject), pode criar arquivos .rej. Você precisará resolver os conflitos manualmente e então aplicar as mudanças manualmente ou tentar novamente após a resolução.
Conclusão
git patch oferece uma flexibilidade incrível para compartilhar e integrar mudanças no seu fluxo de trabalho Git, especialmente em ambientes onde o acesso a repositórios remotos é limitado ou inconveniente. Seja para commits formalizados via git format-patch e git am, ou para alterações rápidas com git diff e git apply, dominar estas ferramentas enriquecerá sua capacidade de colaboração e gerenciamento de código. Lembre-se sempre de verificar o estado do seu repositório antes e depois de aplicar patches para garantir que as alterações foram integradas conforme o esperado.
