Eu tenho dois repositórios. Em um, faço alterações no arquivo ./hello.test
. Eu confirmo as mudanças e crio um patch a partir desse commit com git format-patch -1 HEAD
. Agora, eu tenho um segundo repositório que contém um arquivo que tem o mesmo conteúdo como hello.test mas é colocado em um diretório diferente com um nome diferente: ./blue/red/hi.test
. Como faço para aplicar o patch mencionado acima ao hi.test
arquivo? Eu tentei, git am --directory='blue/red' < patch_file
mas claro que reclama que os arquivos não têm o mesmo nome (o que achei que o Git não se importava?). Eu sei que provavelmente poderia editar o diff para aplicar a esse arquivo específico, mas estou procurando uma solução de comando.
100
Respostas:
Você pode criar o patch usando
git diff
e aplicá-lo usando opatch
utilitário, que permite especificar o arquivo ao qual deseja aplicar o diff.Por exemplo:
fonte
am
ouapply
, mas não consigo encontrar. Se você estiver duplicando muito as mudanças, pode haver uma solução melhor usando submódulos, ou qualquer outra linguagem de sua escolha para compartilhar código (por exemplo, em Ruby você pode extrair o código duplicado como uma gema).Existe uma solução simples que não envolve edição manual de patch nem script externo.
No primeiro repositório (isso também pode exportar um intervalo de commit, use
-1
se você quiser selecionar apenas um commit):No segundo repositório:
Em vez de usar
--relative
ingit format-patch
, outra solução é usar a-p<n>
opção ingit am
para retirar osn
diretórios do caminho dos patches, conforme mencionado em uma resposta a uma pergunta semelhante .Também é possível executar
git format-patch --relative <committish>
sem o--stdout
, e irá gerar um conjunto de.patch
arquivos. Esses arquivos podem ser alimentados diretamentegit am
comgit am --directory blue/red/ path/to/*.patch
.fonte
--directory
opção parece exigir que você especifique o caminho completo do diretório em relação à raiz do repo; algo como--directory=./
while chdir'd em um subdiretório no repo não funcionará.--3way
ajuda comdoes not exist in index
:git am --3way --directory (relative-path) (patch)
-k
tecla em ambos os comandos para não retirar a primeira linha da mensagem de confirmação.--3way
não apenas ajuda com erros "não existe no índice" (como apontado por @nobar), mas também permite que você trate de forma limpa os conflitos de mesclagem. Em vez de deixar os arquivos em conflito intactos, é adicionado um bloco de conflito que pode ser resolvido.Respondendo minha própria pergunta com um script que faz exatamente isso: https://github.com/mprpic/apply-patch-to-file
Em vez de modificar o arquivo de patch manualmente, ele solicita ao usuário o arquivo de destino, modifica o patch e o aplica ao repositório em que você está.
fonte
Com base na resposta de @georgebrock, aqui está uma solução que usei:
Primeiro, crie os arquivos de patch como de costume (por exemplo
git format-patch commitA..commitB
).Em seguida, certifique-se de que seu repositório de destino está limpo (não deve haver arquivos alterados ou não rastreados) e aplique os patches como este:
Para cada arquivo de patch, você receberá um erro como "erro: XYZ não existe no índice". Agora você pode aplicar este arquivo de patch manualmente:
Você deve seguir estas três etapas para cada arquivo de patch.
Isso preservará a mensagem de confirmação original, etc., sem exigir nenhum
git format-patch
comando especial ou editar os arquivos de patch.fonte
git format-patch -1 commitA --stdout > thing.diff
; (2) Edite o arquivo de patch até que ele faça o que eu preciso; (3) Texto para confirmaçãogit am --3way thing.diff
que tem a vantagem de que você pode aceitar as partes do patch que se aplicam de forma limpa e usargit
o processo de resolução de conflito padrão para as partes que não se aplicam .Eu entendo que os dois arquivos são exatamente os mesmos na sua situação, portanto, o patch provavelmente terá sucesso.
No entanto, caso você queira aplicar um patch a um arquivo semelhante, mas não exatamente o mesmo, ou deseja fazer um patch interativo, você usará a fusão de três vias.
Digamos que você modificou Arquivo
A
, vamos denotarA~1
como a versão anterior, e você deseja aplicar a diferença entreA~1
aA
para ArquivoB
.Abra uma ferramenta de mesclagem de três vias, por exemplo Beyond Compare, o caminho do painel esquerdo é
A
, o painel do meio é o ancestral comum, então o caminho éA~1
, o caminho do painel direito éB
. Em seguida, o painel inferior mostra o resultado da aplicação da diferença entreA~1
aA
para ArquivoB
.A figura a seguir ilustra a ideia.
fonte
Para sua informação: Recentemente, tive problemas ao tentar baixar um patch do Github e aplicá-lo a um arquivo local (o que foi uma "substituição" em um novo local).
git am
não aplicaria o patch porque o arquivo "não estava no índice" ou "sujo". Mas, descobri que opatch
comando simples pode aplicar o patch. Ele solicitou o nome do arquivo a ser corrigido.Terminei o trabalho, de qualquer maneira ...
fonte