2010-07-29 11 views
11

Sto lavorando a un repository Git che è stato estratto da un repository SVN utilizzando git svn. Molte lune fa, il repository SVN è stato creato da un archivio sorgente del progetto originale (a monte). Il progetto originale aveva una struttura di file come il seguente:Come posso modificare il percorso del file in una serie di patch Git?

/ 
    COPYING 
    README 
    src/ 
     ...many source files... 

Tuttavia, quando il repo SVN è stato creato, i file README, ecc, sono stati spogliati, e l'applicazione è stato creato con src/ come la radice, in modo il repository ora sembra proprio:

/ 
    ...many source files 

Ho recentemente convertito questo repository SVN in un repository Git. Il progetto originale è anche in un repository Git e vorrei iniziare a monitorare i cambiamenti upstream in modo da poter vedere facilmente quali modifiche personalizzate sono state apportate (e inviare patch al progetto originale, se applicabile). Ho trovato il commit nel repository upstream da cui è stato creato il repository SVN, quindi ora mi piacerebbe applicare le nostre modifiche a quel commit (in un ramo). Posso creare facilmente un set di patch usando git format-patch e applicarli al repository upstream clonato ... tranne che le strutture dei file sono diverse, quindi le patch non puntano più ai file corretti. C'è un modo per applicare le patch da git format-patch alla directory src/ nel repository clonato? (Si noti che le patch Git hanno anche le informazioni necessarie come il nome dell'autore originale, l'e-mail e la data, che mi piacerebbe anche applicare e non dover fare a mano, cioè, scherzando con GIT_AUTHOR_EMAIL, ecc.)

+2

Domanda simile: http://stackoverflow.com/questions/931882/how-to-apply-a-git-patch-from-one-repository-to-another – koppor

risposta

5

Mi sembra che sia possibile utilizzare git filter-branch per modificare i percorsi nel repository SVN precedentemente clonato da. Quindi, dopo che tutti i percorsi dei file sono stati aggiornati, è ora possibile utilizzare semplicemente git format-patch per creare patch che si applicheranno al repository appena clonato da upstream.

Prova:

git filter-branch --tree-filter 'mkdir src; git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files src'

+0

Quasi funziona, ma i file sotto 'src/'sono organizzati in sottodirectory - questa soluzione li sposta tutti direttamente in' src/'. Un modo per spostare l'intero albero della sottodirectory? – mipadi

+0

@mipadi: Giusto. Il mio errore per non effettivamente * testare * quello che scrivo: O. Ho corretto quell'errore nella mia risposta. Grazie per aver segnalato il problema :) –

+0

No biggie - la tua risposta originale funziona bene se 'src /' non contiene sottodirectory (e ho dimenticato di menzionarlo nella mia domanda). – mipadi

2

Ho dovuto fare qualcosa di molto simile una volta, non era bello ma era gestibile. Quello che ho finito per fare era:

git format-patch <commitish> --stdout > patches-for-upstream.mbox 
$EDITOR patches-for-upstream.mbox 

All'interno l'editor, ho guardato che i bit erano comuni e aveva bisogno di cambiare per rendere "git am" fare quello che volevo. Che si è rivelato essere tre linee, per file commesso in ogni commit:

  • la riga che inizia con diff --git a/path/to/file b/path/to/file
  • la riga che inizia con --- a/path/to/file
  • la riga che inizia con +++ b/path/to/file

Che l'editor deve fare a questo punto è passare attraverso questo tipo di linee e apportare le modifiche che si sa sono necessarie per applicare tutte le patch all'altro repository Git.

L'ho fatto in Vim, utilizzando tre macro digitate rapidamente, YMMV.Qualcosa sulla falsariga di:

  • andare alla prossima riga che inizia con diff --git a/
  • andare avanti a quella barra dopo la a
  • cambiamento il percorso come avete bisogno di essere
  • andare avanti per la barra dopo la b/ (al prossimo spazio dal file a, quindi /)
  • cambiamento il percorso nello stesso modo come un
  • nex linea di t (la ---)
  • andare avanti per a/
  • cambiamento il percorso
  • riga successiva (la +++)
  • andare avanti per b/
  • cambiamento il percorso

Ripetere fino a quando il il file è fatto. In Vim si trattava di recuperarlo in una macro (qq<long string of commands>q), provarlo una volta (@q) e poi farlo per l'intero file ([email protected]).

Salva il file, vai nell'altro repository Git e prova a git am it.

3

Recentemente ho avuto un problema simile. La mia soluzione era quella di creare un nuovo repository di destinazione con un src sottodirectory, quindi ho creato un insieme di patch nel repository di origine:

/data/source-repository$ git format-patch -k --root 

poi quelle macchie sono state applicate alla directory src nel repository di destinazione:

/data/target-repository$ git am -k --committer-date-is-author-date --directory src ../source-repository/*.patch 

Tutte le patch dal repository di origine sono terminate in src nel repository di destinazione, ovvero tutti i percorsi sono stati modificati di conseguenza.

Da lì è possibile creare nuovamente le patch e importarle nel repository upstream all'interno di un ramo.

+1

Questo combinato con 'git filter-branch --subdirectory-filter ' mi ha permesso di spostare interamente i miei commit in una directory diversa. –

Problemi correlati