2011-07-09 16 views
8

Ho un repository e vorrei staccare una delle sue directory in un nuovo repository. This è un posto perfetto per iniziare, c'è un avvertimento, tuttavia: la directory che voglio staccare è stata rinominata ad un certo punto. E se seguo la soluzione di quel post con il nuovo nome della directory, sembra che sto perdendo la cronologia prima del nuovo nome. Qualche idea su un tweak per farlo funzionare in questa situazione?Scollegare la sottodirectory (che è stata rinominata!) In un nuovo repository

risposta

9

git filter-branch può operare su intervalli di commit; così quello che possiamo fare è filtrare il 'prima' e 'dopo' a parte, e utilizzare innesti a virare insieme:

git branch rename $COMMIT_ID_OF_RENAME 
git branch pre-rename rename~ 
## First filter all commits up to rename, but not rename itself 
git filter-branch --subdirectory-filter $OLDNAME pre-rename 
## Add a graft, so our rename rev comes after the processed pre-rename revs 
echo `git rev-parse rename` `git rev-parse pre-rename` >> .git/info/grafts 
## The first filter-branch left a refs backup directory. Move it away so the 
## next filter-branch doesn't complain 
mv .git/refs/original .git/refs/original0 
## Now filter the rest 
git filter-branch --subdirectory-filter $NEWNAME master ^pre-rename 
## The graft is now baked into the branch, so we don't need it anymore 
rm .git/info/grafts 

Questo è leggermente più complesso, se avete bisogno di filtrare più rami o tag; i rami prima che la rinomina possa essere inclusa nel primo ramo filtro, mentre quelli successivi devono essere inclusi prima dello ^rename nel secondo ramo filtro.

Un'altra opzione potrebbe essere quella di aggiungere un filtro indice (o filtro ad albero) invece che controlli sia per le directory, vecchie e nuove, e che mantenga quella che è presente.

Poiché non hai fornito un repository di test, ecco uno script sanity-rapido controllo per questo scenario:

#!/bin/bash 

set -u 
set -e 
set -x 

rm -rf .git x y foo 

git init 
mkdir x 
echo initial > x/foo 
git add x/foo 
git commit -m 'test commit 1' 

echo tc2 >> x/foo 
git commit -a -m 'test commit 2' 

mv x y 
git rm x/foo 
git add y/foo 
git commit -a -m 'test rename' 

git branch rename HEAD 

echo post rename >> y/foo 
git commit -a -m 'test post rename' 

git branch pre-rename rename~ 

git filter-branch --subdirectory-filter x pre-rename 
echo `git rev-parse rename` `git rev-parse pre-rename` >> .git/info/grafts 

mv .git/refs/original .git/refs/original0 

git filter-branch --subdirectory-filter y master ^pre-rename 

rm .git/info/grafts 

git log -u 

Se questa procedura non funziona per voi, allora è possibile che ci sia qualcos'altro di strano sulla cronologia del repository che non hai descritto, come ad esempio un altro nome rinchiuso nella cronologia.

+0

Hmm, ho provato il metodo con gli innesti (che non so nulla) e non ha funzionato per me. Dopo aver elaborato uno dei commit "prima" si è svuotato, i file di un altro sono stati spostati nella root del repository; Non riesco a dare un senso. Stavo pensando prima di usare un filtro ad albero ma non ho alcuna esperienza con questo; ti piacerebbe elaborare mi mostra alcuni suggerimenti? – akoprowski

+0

Sei sicuro che il commit precedente stia usando la sottodir corretta? Puoi pubblicare il tuo repository git da qualche parte? – bdonlan

+0

Sì, è stato rinominato il commit che ha eseguito la ridenominazione e la pre-rinomina poco prima. Il repo è enorme e in parte privato quindi non posso davvero pubblicarlo da nessuna parte: | – akoprowski

Problemi correlati