Har du en java-applikasjon i et git-repository som du har lyst til å dele opp i flere deler, men helst med så mye historikk som mulig? Det hadde jeg, og jeg fikk fikset det på et slags vis:
-
Lag en arbeidskopi av git-repositoriet (dette kan du i og for seg skippe om du er kul nok):
cp -r mitt-repo mitt-repo-kopi cd mitt-repo-kopi
-
Kjør en subtree-split med git
git subtree split -P src/main/java/[path]/det-du-vil-ha-ut -b tree-split-branch
Nå har du en branch i indeksen i repoet ditt som er et subtree som bare inneholder filene + historikken for filene i den delen av treet du splittet ut.
-
Lag et nytt repo, pull inn den nye branchen
cd .. mkdir mitt-nye-repo && cd mitt-nye-repo git init git pull ../mitt-repo-kopi/.git tree-split-branch
Du har alt. Men det ligger på rot. Nå må vi rydde litt så ikke java dør:
-
Siden vi driver med java, er det en streng sammenheng mellom plasseringen til filene i filsystemet, og package-navn i filen. Det må fikses (nå bør du tenke over hvordan det skal se ut i 5. på forhånd):
git filter-branch -f --tree-filter 'for i in $( ls *.java); do sed -e "s/filenes gamle package/filenes nye package/" -i "" $i; done'
Om du har flere packages i samme repo må du seff fikse på det også
-
git subtree
flyttet mappen din til roten i den nye repoet, men den må jo selvfølgelig ligge isrc/main/java/din/package/din-applikasjon
for at java skal fungere:git filter-branch -f --tree-filter 'mkdir -p src/main/java/din/package/din-applikasjon && mv *.java src/main/java/din/package/din-applikasjon' HEAD
NB: Det er betydelig enklere å gjøre dette skrittet etter 4. og ikke omvendt.
-
Nå viser det seg sikkert at den koden du flyttet ikke var helt uavhengig allikevel, så da må du kopiere over noen filer fra det gamle repoet.
git checkout --orphan ny_initial_commit git clean -f -d cp ../mitt-repo/ting-du-vil-ha . git add . git commit -m "initial commit ;)" git checkout master git rebase --onto ny_initial_commit --root master
Et tips: Det er ofte litt tricky å finne ut hva du mangler, det kan fort være at det enkleste er å ikke sjekke ut den tomme commiten før du vet det, og er klar:
git checkout -b temp-branch cp ../mitt-repo/ting-du-vil-ha [build] cp ../mitt-repo/src/main/resources/hva-faen.txt src/main/resources/ [build] git add . git commit -m "temp" git format-patch -1 mv 0001-temp.patch .. git checkout --orphan ny_initial_commit git apply ../0001-temp.patch git commit -am "initial commit ;)" (resten som over) ... git branch -D temp-branch
-
Nå har du et nytt repo, med historikk, som antagelig til og med bygger om du sjekker ut historiske commits. Helt vilt. Thank u git.
Lag et nytt repo upstream (på github, ikke sant), push med
git push -u origin master
Men vent, hva med testene?
-
Trinn 2, 4, og 5 er de samme for testene dine også. For å kunne gjøre alle operasjonene i samme repository kan du sjekke ut en ny orphan-branch og pulle endringene rett inn i den, i stedet for å lage et nytt repo:
git checkout --orphan din-applikasjon-tester git reset --hard git pull ../mitt-repo-kopi/.git applikasjon-tester
Gjør trinn 4 og 5, men med
test
på de rette stedene. Gjør til slutt en rebase opp på master (eller på ditt initielle commit, om du mener det er bedre). Merge test-branchen med master.git rebase --onto master --root din-applikasjon-tester git checkout master git merge din-applikasjon-tester