Come posso spostare una singola directory da un repository git a un nuovo repository mantenendo la cronologia?


110

Ho ereditato un repository git contenente più progetti in directory separate. Vorrei dividere il repository in nuovi repository individuali, uno per ogni progetto e quindi fare in modo che il repository principale contenga i progetti come sottomoduli. Vorrei fare tutto questo mantenendo, se possibile, la cronologia delle revisioni dei singoli progetti.

Potrei clonare il repository per ogni progetto e rimuovere tutti gli altri progetti ogni volta, ma esiste un modo migliore per evitare di avere la cronologia clonata in ogni nuovo repository del progetto?


2
Aggiunto tag git-submodules poiché è molto utile per convertire parte di un repo in un sottomodulo.
idbrii

Possibile duplicato della sottostruttura
utente

Risposte:


99

È possibile utilizzare git filter-branchper riscrivere la storia di un progetto. Dalla documentazione:

Per riscrivere il repository in modo che appaia come se foodir / fosse stata la radice del progetto e scartare tutta la cronologia:

git filter-branch --subdirectory-filter foodir -- --all

Crea diverse copie del tuo repository, fallo per ogni sottodirectory che vuoi dividere e dovresti finire con quello che stai cercando.


1
E se volessi escludere foodir e rimuovere tutta la sua storia?
saeedgnu

1
Nota: se desideri più directory, dovrai specificarlo --subdirectory-filterpiù volte. Ad esempio git filter-branch --subdirectory-filter foodir --subdirectory-filter bardir, ecc. --subdirectoryNon accettano più directory, ma possono essere specificate più volte.
EnabrenTane

3
@Adam Se vuoi mantenere la cronologia del foodirprogetto originale, non riscriverne la cronologia, git rm -r foodirdovrebbe essere sufficiente (questo cancellerà anche la copia nel tuo albero di lavoro; se non lo vuoi, usa --cached). Se volevi rimuoverlo completamente dalla cronologia (rispondendo anche alla domanda di @ ilius), vuoi qualcosa del tipogit filter-branch --index-filter 'git rm -r --cached --ignore-unmatched foodir' -- --all
Brian Campbell,

2
@ilius Mi dispiace di aver perso la tua domanda in precedenza, vedi la mia risposta sopra per una risposta su come rimuovere una directory e la sua cronologia.
Brian Campbell

2
@ilius Sì, funziona anche questo. Per un progetto di grandi dimensioni, la --index-filtersoluzione è più veloce di --tree-filter, poiché non deve effettivamente estrarre i file, può semplicemente manipolare l'indice direttamente. Tuttavia, --tree-filterpuò essere un po 'più facile da usare, poiché puoi usare le normali operazioni del filsystem invece di dover lavorare con le operazioni di manipolazione degli indici.
Brian Campbell

4

Per esportare una cartella come nuovo repository è necessario:

  1. Per clonare il repository in cui si trova la cartella che desideri esportare.
  2. Per creare un repository vuoto sul tuo provider di hosting come GitHub, per archiviare la cartella esportata.
  3. Apri la cartella del repository clonato ed esegui questo comando:

    git subtree push --prefix=YourFolderNameToExport https://github.com/YourUserName/YourNewCleanRepoName master
    

1
git subtreenon è disponibile come pacchetto Cygwin. Se ne hai bisogno: stackoverflow.com/a/27116828/2484903
Jack Miller

2

Il punto di git è che la cronologia è incorporata in ogni commit tramite l'hashing del commit genitore. È possibile "riprodurre" i commit (questo è essenzialmente il modo in cui funziona l'importatore svn) in un nuovo repository e conservare solo ogni sottoprogetto. Ciò, tuttavia, distruggerebbe il significato degli hash di commit. Se non hai problemi con quello, allora così sia.

In passato l'ho clonato e sono andato avanti. Questo rende le cose più grandi ma lo spazio su disco è economico; il mio tempo è costoso.

Inoltre non conosco alcuno strumento per unire una directory. Suppongo che potresti git-log sulla directory per trovare tutti i commit su di essa, quindi riprodurre i commit con qualcosa come git-fast-export?


Ho votato positivamente perché questo perché non meritavo di essere negativo - di certo non avrei seguito questo approccio ma vedo che ci stava provando
Alvin
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.