O patch de formato Git deve ser compatível com o svn?

96

Existe alguma maneira de obter um patch criado com git format-patch para ser compatível com svn para que eu possa enviá-lo para um repo svn?

Estou trabalhando em um repo svn no github e desejo enviar minhas alterações de volta ao repo principal. Eu preciso criar um patch para fazer isso, no entanto, o patch não pode ser aplicado, pois o git formata esse patch de forma diferente do svn. Existe algum segredo que ainda não descobri?

ATUALIZAÇÃO: Embora atualmente não exista nenhum script ou maneira nativa do git de fazer isso, consegui encontrar um post do início deste ano sobre como fazer isso manualmente. Eu segui as instruções e tive sucesso em fazer meus patches git funcionarem com o svn.

Se alguém pudesse tentar escrever um script para fazer isso e contribuir com o projeto git, todos ficariam muito agradecidos.

http://kerneltrap.org/mailarchive/git/2008/1/15/570308/thread#mid-570308

rip747
fonte
Não consigo fazer funcionar ... você poderia postar todas as etapas necessárias? obrigado!
Mauricio Scheffer
1
Oi, Anthony. Você consideraria mudar a resposta aceita para a de Nicholas?
Simon East
Eu concordo com a sugestão de Simon, tendo a resposta de Nicholas Smith como a aceita beneficiaria a todos, pois é muito mais prática.
Albireo

Respostas:

90

Sempre preciso pesquisar isso no Google, mas descobri que funciona perfeitamente (para mim):

  • Crie o patch com git diff --no-prefix master..branch > somefile.diff, a parte master e branch são opcionais, depende de como você deseja obter seus diffs.
  • Envie para qualquer lugar e aplique com patch -p0 < somefile.diff.

Sempre parece funcionar bem para mim e parece ser o método mais simples que encontrei.

Nicholas Smith
fonte
1
Esta é a maneira canônica de gerar patch compatível com SVN com Git. Deve ser marcado como a resposta.
mloskot
--no-pagernão é mais uma opção para git diff.
naught101 01 de
Foi postado originalmente sem --no-pager, não tenho certeza por que foi adicionado na edição. Sempre funcionou bem para mim sem nada --no-pager.
Nicholas Smith
2
Apenas para um commit específico: git diff --no-prefix 056a1ba5140 7d939289b80 >my.patchfuncionou para mim (onde 056a1ba5140e 7d939289b80são os sha-1 do commit anterior e específico no git).
Ed Randall
@Lilás esse é um problema do SVN. Diffs / patches no SVN nunca foram capazes de lidar com arquivos removidos
Toofy
17

Aqui está um script auxiliar para fazer uma comparação com o último conjunto de alterações svn e o commit fornecido: http://www.mail-archive.com/[email protected]/msg00864.html

#!/bin/sh
#
# git-svn-diff
# Generate an SVN-compatible diff against the tip of the tracking branch
TRACKING_BRANCH=`git config --get svn-remote.svn.fetch | sed -e 's/.*:refs\/remotes\///'`
REV=`git svn find-rev $(git rev-list --date-order --max-count=1 $TRACKING_BRANCH)`
git diff --no-prefix $(git rev-list --date-order --max-count=1 $TRACKING_BRANCH) $* |
sed -e "s/^+++ .*/&    (working copy)/" -e "s/^--- .*/&    (revision $REV)/" \
-e "s/^diff --git [^[:space:]]*/Index:/" \
-e "s/^index.*/===================================================================/"
Christoph
fonte
1
Descobri que o valor REV está incorreto se você não está trabalhando com a última revisão svn. Eu corrigi para usar git svn infoassim: REV=`git svn info | grep 'Last Changed Rev:' | sed -E 's/^.*: ([[:digit:]]*)/\1/'`
Sebastien Martin
1
Isso é incrível! Muito obrigado. Tive de fazer uma alteração para que funcionasse na importação de meus patches para o cadinho da Fisheye, que era substituir os espaços antes de "(revisão" por uma guia.
Zugwalt
10

SVN provavelmente não consegue entender a saída de git diff -p, mas você pode recorrer à força bruta:

  1. Faça dois clones do seu repo
  2. Em um clone, verifique suas novidades
  3. No outro checkout do clone, tudo o que for equivalente ao svn upstream. Se você planejou com antecedência, você tem uma cópia do svn upstream em seu próprio ramo, ou marcou a última versão do svn. Se você não planejou com antecedência, use a data ou gitk para encontrar o hash SHA1 do git que mais se aproxima do estado svn.
  4. Agora calcule um patch real executando diff -ros dois clones.
Norman Ramsey
fonte
12
Ou apenas siga o conselho de @Nicholas-smith e execute git diff --no-prefix > somefile.diffem seu repositório git e envie para qualquer usuário svn para que ele aplique o patch patch -p0 < somefile.diffna raiz do projeto.
DavidG
10

O Subversion <1.6 não tem suporte a patch. Parece que o Subversion 1.7 permitirá a aplicação de patches e as extensões git / hg para o diff unificado estão em nossa lista TODO.

Bert Huijben
fonte
4

Na verdade, é uma solicitação de recurso do início de 2008

Linus Torvalds disse na época:

Então, eu diria que você precisa de algo mais forte para dizer "não faça um git diff", e isso também deve impedir a detecção de renomeação no mínimo.
Francamente, qualquer programa que seja tão estúpido a ponto de não aceitar os patches atuais do git (ou seja, TortoiseSVN), então nós muito bem não deveríamos apenas desativar a parte mais trivial dele. Devemos ter certeza de que não habilitamos nenhuma das extensões bastante importantes:
mesmo se ToirtoiseSVN as ignorasse, se ignorá-las significa que ele não entendeu o diff, não deveria ser permitido.

Pode ser por isso

 git-format-patch: add --no-binary to omit binary changes in the patch.

foi introduzido no Git1.5.6 em maio / julho de 2008 (ainda não o testei)

VonC
fonte
0

Certifique-se de que suas alterações sejam confirmadas e realocadas em seu branch local do git, a partir do git bash run:

git show --pretty >> myChangesFile.patch

Ismail Hawayel
fonte
0

A resposta aceita fornecida por Nicholas funciona bem, exceto quando a) arquivos binários existem no diff ou b) você está trabalhando no Windows Git e tem diretórios com espaços. Para resolver isso, tive que adicionar um comando git diff aninhado para ignorar os binários e o comando sed para escapar dos espaços. É um pouco complicado de escrever, então criei um alias:

[alias]
svnpatch = "!f() { git diff --name-only --no-prefix master...$1 | grep -Ev \"\\.sdf|\\.Doc|\\.dll|\\.zip|\\.exe\" | sed 's_\\s_\\\\\\\\ _g'  | xargs git diff --no-prefix master...$1 > $1.patch; echo "Created $1.patch"; }; f"

Se você digitar:

git svnpatch Feature123

... um arquivo de patch Feature123.patch será criado com as diferenças entre a base de mesclagem do branch master e o branch Feature123.

Leandro Gomez
fonte