2010-03-11 22 views
42

Ho avuto un repository Git (A) che contiene lo sviluppo di un progetto fino a un certo punto. Poi ho perso la chiavetta USB su cui era presente il repo A. Fortunatamente ho avuto un backup dell'ultimo commit, quindi ho potuto creare un nuovo repository (B) in seguito, dove ho importato lo stato del progetto più recente e continuare lo sviluppo. Ora ho recuperato quella chiavetta USB persa, quindi ho due repository Git.Come rebase di un repository Git su un altro?

Penso che dovrei semplicemente rebase repo B su repo A in qualche modo, ma non ho idea di come farlo, magari usando fetch/pull e rebase?

risposta

57

Se A e B non sono lo stesso repository (si è creato B utilizzando la più recente copia di lavoro disponibile), è necessario utilizzare un graft per far finta che abbiano una cronologia comune.

Supponiamo che hai aggiunto A come un telecomando per B secondo VonC’s answer, e il repo assomiglia a questo :

~/B$ git tnylog 
* 6506232 (HEAD, master) Latest work on B 
* 799d6ae Imported backup from USB stick 
~/B$ git tnylog A/master 
* 33b5b16 (A/master) Head of A 
* 6092517 Initial commit 

Creare un innesto di raccontare la radice di B che il suo genitore è il testa di a:

echo '799d6aeb41095a8469d0a12167de8b45db02459c 33b5b16dde3af6f5592c2ca6a1a51d2e97357060' \ 
>> .git/info/grafts 

Ora le due storie di cui sopra appare come uno quando si richiede la cronologia per B. Fare l'innesto permanente è un semplice git filter-branch senza argomenti. Dopo il filtro-ramo, però, non sei su alcun ramo, quindi dovresti git branch -D master; git checkout -b master.


git tnylog = git log --oneline --graph --decorate

+2

+1 per prendersi cura dell '"altro scenario" dove A e B differiscono completamente nella cronologia del commit. – VonC

+3

Questo è stato un aiuto brillante; ha fatto assolutamente quello che volevo con un minimo di confusione. Grazie! –

+1

Ho appena usato l'approccio di unione secondaria per unire diversi repository in uno solo. Successivamente ho fallito nel tentativo di ribaltarli uno sull'altro. Usando i punti di innesto, ora sono riuscito a ricollegarli su una singola timeline di sviluppo, grazie! –

24

Se A e B sono gli stessi pronti contro termine (il primo SHA1 sono comuni), è possibile:

  • dichiarare A come un telecomando per B: git remote add A /path/to/A
  • git fetch A al update all remote A branches sul repo B
  • git checkout dev (su B, dove si sta sviluppando)
  • git rebase A/devBranch per riprodurre B (ovvero cosa si sviluppa o ri-sviluppa dal backup) in cima a A/devBranch (lo sviluppo perso). Un po 'come questo SO question.

L'ultimo passaggio consente di sincronizzare il proprio dev con quello perso.
Ma in realtà, una volta che hai recuperare da A, si è fatto: B ora contiene il "tutto" la storia (quello che hai perso e il vostro lavoro attuale)

+0

Grazie, sembra funzionare, basta per risolvere alcuni conflitti durante l'unione/rebase ora :) – kroimon

+0

@kroimon: i conflitti erano inevitabili, suppongo, da quando eri ri-sviluppo in B una parte del codice impegnata in A. – VonC

+0

Sono finito in un HEAD distaccato e ho dovuto fare riferimento a questo: https://stackoverflow.com/a/25670296/1807668 –

2

Prima di tutto, inizia facendo un clone di lavoro di repo A.

Quindi basta trascinarlo da B e unire. Potresti preferire creare un nuovo ramo, trascinarlo sopra, quindi unire i due rami. Potrebbe anche essere necessario un flag di forzatura; Ho fatto cose del genere in Mercurial (innestando due repository apparentemente non correlati insieme) e ha bisogno di "-f".

Problemi correlati