git: applica le modifiche introdotte da commit in un repository a un altro repository


115

Ho un repo1e repo2sulla macchina locale. Sono molto simili, ma quest'ultimo è una sorta di altro ramo ( repo1non viene più mantenuto).

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

Come applicare le modifiche apportate da impegnarsi <some_sha>in repo1a repo2?

Devo preparare qualche patch o è possibile farne un po ' cherry-picktra i repository?

Che ne dici di fare lo stesso ma per la gamma di commit?


2
Non puoi semplicemente tirare da repo1 a repo2?
Zwol

per il caso leggermente più specifico in cui stai cercando di applicare modifiche a uno o più file spostati in uno dei repository, guarda qui: stackoverflow.com/questions/3491270/…
Braham Snyder

Risposte:


31

Come hack, puoi provare a modificare la ricetta per confrontare i commit in due diversi repository sulla pagina GitTips , ovvero:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

dove ../repoè il percorso dell'altro repository.

Con il moderno Git puoi utilizzare più revisioni e intervalli di revisione con cherry-pick .

Il $(git --git-dir=../repo/.git rev-parse --verify <commit>) è qui per tradurre <commit>(per esempio HEAD, o v0.2, o master~2, che sono valori nella seconda repository si copia da) in SHA-1 identificatore di commettere. Se conosci SHA-1 di una modifica che desideri scegliere, non è necessario.

NOTA tuttavia che Git può saltare la copia di oggetti dal repository di origine, poiché non sa che il repository di oggetti alternativo è solo temporaneo, per un'operazione. Potrebbe essere necessario copiare oggetti dal secondo repository con:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

In questo modo gli oggetti presi in prestito dal secondo repository nella memoria del repository originale

Non testato.


Una soluzione non così hacky è seguire la risposta di knittl :

  • Vai al secondo repository da cui desideri copiare i commit e genera le patch dai commit che desideri git format-patch
  • Facoltativamente, copia le patch (0001- * ecc.) Nel tuo repository
  • Utilizzare git am --3wayper applicare le patch

1
Funziona bene. Se hai problemi con il commit, esegui 'git reset HEAD; git add. '.
gumik

5
questo è fantastico: come faresti una serie di commit? solo sha1 ... sha2?
hvgotcodes

Ho anche fatal: unable to read tree ...git reset HEAD^
capito,

@hvgotcodes ha funzionato per me semplicemente passando l'intervallo come <commit>ma al rev-parse --verifycomando non piace poiché accetta solo valori di commit singolo. Ma poiché cherry-pickaccetta sia valori di commit singoli che di intervallo, chiedo: perché è rev-parsenecessario?
Chuim

1
@Chuim: git rev-parseè necessario se si vuole fare riferimento a un commit con il suo nome ref-based in altri repository, per esempio master, HEAD^^o qualcosa del genere; rev-parse lo trasforma in un identificatore SHA-1 universale.
Jakub Narębski

207

Probabilmente vorrai usare git format-patche poi git amapplicare quella patch al tuo repository.

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

Oppure, in una riga:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3

9
Questa soluzione si è dimostrata più semplice e sicura della risposta accettata dell'utilizzo diretto della selezione GIT_ALTERNATE_OBJECT_DIRECTORIES(che avrebbe corrotto il mio repository).
Chuim

2
Quando ci sono conflitti non funzionerà perché non riesce a trovare i commit sull'altro ramo.
Roger Far

2
L'aggiunta --ignore-whitespaceal git amcomando può risolvere eventuali conflitti ed evitare di dover eseguire un'unione a 3 vie
Hugheth

98

Puoi farlo cherry-pickse aggiungi il secondo repository come telecomando al primo (e poi fetch).


11
Questo è effettivamente il modo corretto per farlo.
Wilbert

5
Anche per me questo sembra il modo giusto. E l'ho appena usato e ha funzionato bene per me.
Ricky Nelson

11
Preferirei dire: fai git fetch [remote-name]nel secondo repo e poi git cherry-pick [sha1].

5
Questo approccio ha funzionato alla grande per me, grazie. Poiché anche il secondo repository era locale, era sufficiente utilizzare un URI di file quando lo si aggiungeva come remoto.
palinsesto

2
Nel mio caso, ho due cloni di un gigantesco repository git remoto (per consentire il lavoro parallelo), il che significa che tutta la sua cronologia è già stata scaricata e archiviata due volte nel mio HD. Se dovessi anche aggiungere ciascuno come telecomando dell'altro, ciò creerebbe ancora due copie extra della stessa cronologia e richiederebbe potenzialmente sincronizzazioni tra di loro prima di poterlo fare cherry-pick. Quindi, anche se potrebbe sembrare il modo "giusto", non è sempre il più pratico.
Chuim

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.