Si potrebbe provare a utilizzare il file di trapianto (.git/info/grafts
) dove si poteva sovrascrivere il genitore di un commit (come il primo di projectB
avere per il genitore l'ultima delle projectA
)
Vedi anche "What are .git/info/grafts for?" e "How to prepend the past to a git repository?" per ulteriori informazioni su questa manipolazione.
skaleecomments circa l'articolo "Git: Grafting repositories" (da SO utente Ben Straub) per un esempio concreto.
Ora quello che vogliamo fare è cambiare il primo commit nel “nuevo
” pronti contro termine (“New commit #1
”) in modo che il suo genitore è l'ultimo commit nel “vecchio” pronti contro termine (“Old # 3”). Tempo per un po 'voodoo:
git fetch ../old master:ancient_history
Git permette di essere prelevati dal qualsiasi altro repository git, se questo repo è legato ad esso o no! Brillante! Questo ci lascia con questo:
Nota come abbiamo ribattezzato il vecchio ramo master per ancient_history. Se non lo avessimo fatto, Git avrebbe cercato di unire i due, e probabilmente si sarebbe arreso disgustato.
Ora abbiamo ancora un problema.
I due alberi non sono collegati, e in effetti una tirata di git non otterrà nemmeno il ramo antico_history. Abbiamo bisogno di un modo per creare una connessione tra i due.
Git ha una funzione chiamata innesto, che fondamentalmente simula un collegamento genitore tra due commit.
per fare uno, basta inserire una riga nel file .git/info/grafts
in questo formato:
[ref] [parent]
Entrambi questi hanno bisogno di essere la piena hash dei commit in questione. Quindi cerchiamo di trovarli:
$ git rev-list master | tail -n 1
d7737bffdad86dc05bbade271a9c16f8f912d3c6
$ git rev-parse ancient_history
463d0401a3f34bd381c456c6166e514564289ab2
$ echo d7737bffdad86dc05bbade271a9c16f8f912d3c6 \
463d0401a3f34bd381c456c6166e514564289ab2 \
> .git/info/grafts
(in una linea, come suggested da ssokolow)
echo $(git rev-list master | tail -n 1) $(git rev-parse ancient_history) > .git/info/grafts
Ci.Ora la nostra storia si presenta così:
clonato questa repo risultati in questo:
Woops. Si scopre che gli innesti hanno effetto solo per il repository locale. Siamo in grado di risolvere questo problema con l'applicazione giudiziosa di git fast-import
:
$ git fast-export --all > ../export
$ mkdir ../nuevo-complete
$ cd ../nuevo-complete
$ git init
$ git fast-import < ../export
git-fast-import statistics: [...]
(in una linea, come suggested da ssokolow)
git filter-branch $(git rev-parse ancient_history)..HEAD
Questo trasforma in modo efficace il nostro “falso” collegamento di cronologia in sono soli.
Tutti gli ingegneri dovranno ri-clonare da questo nuovo repository, poiché gli hash saranno tutti diversi, ma questo è un piccolo prezzo da pagare per nessun tempo di inattività e una cronologia completa.
Come Qix commenti below:
fast-import
sembra importare solo le informazioni git, ma non controlla nulla.
git init
in origine mette il master, quindi è necessario un git reset --hard HEAD
per verificare effettivamente i file dopo fast-import
.
Ha funzionato bene per me, grazie VonC, non pensavo che sarebbe stato così semplice. – SilentGhost
Quindi puoi riscrivere la cronologia usando 'git filter-branch' per fare ciò che l'innesto ha portato permanente ... ma questo riscrive la storia. –
Articolo breve e accurato che mi ha davvero aiutato a capire quali innesti sono e passo dopo passo come unire quelle storie: http://ben.straubnet.net/post/939181602/git-grafting-repositories – skalee