Posso obter uma saída compatível com patches do git-diff?


160

Estou fazendo algo muito simples errado. Estou tentando preparar um arquivo de patch comum, para poder aplicar novamente algumas alterações:

$ git diff > before
$ git diff something_here > save.patch
$ git checkout . 
$ patch < save.patch
$ git diff > after
$ diff before after
$

Com o something_here espaço em branco , quase funciona, mas os nomes dos arquivos não estão corretos. Acho que estou perdendo alguma opção.

Na vida real, vou fazer uma mesclagem após o checkout, para que o patch possa falhar por lá, mas você vê no que estou entrando.

Edite Minha falha aqui por fazer a pergunta errada. A questão real é: eu quero salvar minhas alterações, fazer uma mesclagem e reaplicar as alterações, se possível? Perguntei da maneira errada, porque estou acostumado a usar o patch para resolver esse tipo de problema e git diffparecia que era isso que eu queria que eu fizesse.

Comentário de Charles Bailey teve a resposta certa. Para mim, o git-apply é a coisa certa a fazer (o git-stash parece mais pesado do que eu preciso, o rebasing e os pacotes estão definitivamente além do meu nível de habilidade atual.) Vou aceitar a resposta que Charles deu (porque você não pode aceitar um comentário). Obrigado por todas as sugestões.

Editar, 6 anos depois Como qualquer pessoa familiarizada com o assunto sabe, eu superestimei a dificuldade de git stash. Quase todos os dias, usarei a seguinte sequência:

$ git stash
$ git merge
$ git stash pop

8
Existe algum motivo que você deseja usar especificamente, em patchvez degit apply ?
— perfil completo de CB Bailey

3
E mesmo assim, você realmente precisa de patches em vez de algo como git stashou outras ferramentas git?
— CB Bailey

3
Após a edição, acho que git stashé a solução mais fácil para o que você está tentando fazer, mas existem muitas abordagens que funcionam.
— CB Bailey

1
@ Malvolio: Na verdade, você nem precisa pensar em um nome de arquivo temporário para armazenar seu patch.
— CB Bailey

4
@Charlse, às vezes você precisa enviar um patch para alguém sem todo o repositório git. Por exemplo, se estiver usando git-svn.
— Elazar Leibovich 29/03

Respostas:


139

Se você quiser usar o patch, precisará remover os a/ b/prefixos que o git usa por padrão. Você pode fazer isso com a --no-prefixopção (você também pode fazer isso com a -popção do patch ):

git diff --no-prefix [<other git-diff arguments>]

Geralmente, porém, é mais fácil usar o straight git diffe depois usar a saída para alimentar git apply.

Na maioria das vezes, tento evitar o uso de patches de texto. Geralmente, uma ou mais confirmações temporárias combinadas com rebase git stashe pacotes são mais fáceis de gerenciar.

Para o seu caso de uso, acho que stashé o mais apropriado.

# save uncommitted changes
git stash

# do a merge or some other operation
git merge some-branch

# re-apply changes, removing stash if successful
# (you may be asked to resolve conflicts).
git stash pop

7
git diff --no-prefix master > diff.patche depoisgit checkout master patch -p0 < diff.patch
— Natim

1
@ Natim Para segurança máxima, eu recomendaria o uso patch --dry-run < diff.patchantes de emitir o último comando.
— ᴠɪɴᴄᴇɴᴛ

1
@ ᴠɪɴᴄᴇɴᴛ qual seria o benefício de fazer isso? Já que estamos usando o git, é improvável que percam alguma coisa, não é?
— Natim

1
@ Natim Como eu disse, apenas para segurança máxima, não há necessidade de desfazer nada em caso de erro. Eu também estava pensando em pessoas que leem isso e desejam usar patchfora do git (talvez usando um arquivo de correção gerado por diff) em um caso de uso mais geral.
— ᴠɪɴᴄᴇɴᴛ

Para incluir novos arquivos no seu patch, você precisa incluir também "git diff --no-prefix --cached" no patch. Talvez haja uma maneira melhor?
— Jamshid

219

Basta usar -p1: você precisará usar -p0o --no-prefixcaso de qualquer maneira, para que você possa deixar de fora o --no-prefixe usar -p1:

$ git diff > save.patch
$ patch -p1 < save.patch

$ git diff --no-prefix > save.patch
$ patch -p0 < save.patch

1
Se você está se perguntando o porquê, o homem resume tudo bem - fonte .
— TutuDajuju

3
Isso não funcionará com renomeações; git diffgera uma linha que patchignora. git applyé o caminho a percorrer.
— Hraban

17

As diferenças do git têm um segmento de caminho extra anexado aos caminhos do arquivo. Você pode remover esta entrada no caminho especificando -p1 com patch, assim:

patch -p1 < save.patch

10
  1. Eu salvo o diff do diretório atual (incluindo arquivos não confirmados) no HEAD atual.
  2. Em seguida, você pode transportar o save.patcharquivo para qualquer lugar (incluindo arquivos binários).
  3. Na máquina de destino, aplique o patch usando git apply <file>

Nota: também são os arquivos faseados no momento.

$ git diff --binary --staged HEAD > save.patch
$ git reset --hard
$ <transport it>
$ git apply save.patch

Hahaha Isso é engraçado. Fiz essa pergunta há quase quatro anos e a maneira como venho fazendo isso evoluiu, mas se você tivesse me perguntado ontem como fazê-lo, eu teria dado sua resposta e dito que obtive de respostas a essa pergunta. (Na verdade, eu provavelmente usaria um bare git diff > save.patche em git checkout .vez de um reset, mas sim ...
— Malvolio

Oh não percebeu seus 4 anos de idade: P. Aliás, a redefinição é apenas para demonstrar que funciona. Também não vejo ninguém usando git applyou tornando o diff relevante para o seu estado e o ponteiro para o último commit disponível. Fazer simplesmente git diffnão fez nada
— Matej 5/09

Sim, agora eu me pergunto como eu descobri git apply. A coisa com git diffé (eu acho) de usar git reset- as relações entre os repo, o índice, ea área de trabalho são o problema.
— Malvolio

8

Um truque útil para evitar a criação de arquivos de patch temporários:

git diff | patch -p1 -d [dst-dir]

Exatamente o que eu queria. Também funciona perfeitamente com esconderijos! git stash show -p stash@{3} | patch -p1 -d [dst-dir]
— precisa saber é o seguinte
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.