-
1. Aan die slag
- 1.1 Oor Weergawebeheer
- 1.2 Wat is Git?
- 1.3 Die Opdragreël
- 1.4 Git Installeer
- 1.5 Git klaarmaak vir eerste gebruik
- 1.6 Hulp Verkry
- 1.7 Opsomming
-
2. Git Basics
-
3. Git Branching
-
4. Git on the Server
- 4.1 Die Protokolle (The Protocols)
- 4.2 Git op 'n Bediener kry (Getting Git on a Server)
- 4.3 Jou Publieke SSH-sleutel Genereer (Generating Your SSH Public Key)
- 4.4 Die Bediener Opstel (Setting Up the Server)
- 4.5 Git Daemon
- 4.6 Slim HTTP (Smart HTTP)
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Derdeparty-gasheuroplossings (Third-Party Hosting Solutions)
- 4.10 Summary
-
5. Distributed Git
-
6. GitHub
-
7. Git Tools
- 7.1 Hersieningseleksie (Revision Selection)
- 7.2 Interaktiewe Voorbereiding (Interactive Staging)
- 7.3 Bêre en Skoonmaak (Stashing and Cleaning)
- 7.4 Ondertekening van Jou Werk (Signing Your Work)
- 7.5 Soek (Searching)
- 7.6 Herskryf van Geskiedenis (Rewriting History)
- 7.7 Reset Ontmystifiseer (Reset Demystified)
- 7.8 Gevorderde Saamsmelting (Advanced Merging)
- 7.9 Rerere
- 7.10 Ontfouting met Git (Debugging with Git)
- 7.11 Submodules
- 7.12 Bundeling (Bundling)
- 7.13 Vervang (Replace)
- 7.14 Die Stoor van Aanmeldbewyse (Credential Storage)
- 7.15 Summary
-
8. Customizing Git
-
9. Git and Other Systems
- 9.1 Git as a Client
- 9.2 Migrating to Git
- 9.3 Summary
-
10. Git Internals
9.2 Git and Other Systems - Migrating to Git
Migrating to Git
If you have an existing codebase in another VCS but you’ve decided to start using Git, you must migrate your project one way or another. This section goes over some importers for common systems, and then demonstrates how to develop your own custom importer. You’ll learn how to import data from several of the bigger professionally used SCM systems, because they make up the majority of users who are switching, and because high-quality tools for them are easy to come by.
Subversion
As jy die vorige afdeling gelees het oor die gebruik van git svn, kan jy daardie instruksies maklik gebruik om git svn clone van 'n bewaarplek te doen; stop dan om die Subversion-bediener te gebruik, push na 'n nuwe Git-bediener, en begin dit gebruik.
As jy die geskiedenis wil hê, kan jy dit bereik so vinnig as wat jy die data uit die Subversion-bediener kan uittrek (wat 'n rukkie kan neem).
Die invoer is egter nie perfek nie; en omdat dit so lank sal neem, kan jy dit net as goed reg doen.
Die eerste probleem is die outeurinligting.
In Subversion het elke persoon wat 'n vaslegging doen, 'n gebruiker op die stelsel wat in die vasleggingsinligting opgeteken word.
Die voorbeelde in die vorige afdeling wys schacon op sommige plekke, soos die blame-afvoer en die git svn log.
As jy dit na betere Git-outeurdata wil kaart, benodig jy 'n kartering van die Subversion-gebruikers na die Git-outeurs.
Skep 'n lêer genaamd users.txt wat hierdie kartering in 'n formaat soos dit het:
schacon = Scott Chacon <schacon@geemail.com>
selse = Someo Nelse <selse@geemail.com>
Om 'n lys te kry van die outeursname wat SVN gebruik, kan jy dit uitvoer:
$ svn log --xml --quiet | grep author | sort -u | \
perl -pe 's/.*>(.*?)<.*/$1 = /'
Dit genereer die log-afvoer in XML-formaat, behou dan slegs die reëls met outeurinligting, gooi duplikate weg en stroop die XML-merkers uit.
Dit werk uiteraard net op 'n masjien waarop grep, sort en perl geïnstalleer is.
Leid dan daardie afvoer na jou users.txt lêer om sodat jy die ekwivalente Git-gebruikersdata langs elke inskrywing kan byvoeg.
|
Note
|
As jy dit op 'n Windows-masjien probeer, is dit die punt waar jy in die moeilikheid sal kom. Microsoft het goeie advies en voorbeelde verskaf by https://learn.microsoft.com/en-us/azure/devops/repos/git/perform-migration-from-svn-to-git. |
Jy kan hierdie lêer aan git svn verskaf om dit te help om die outeurdata akkuraat te kaart.
Jy kan ook vir git svn sê om nie die metadata in te sluit wat Subversion normaalweg invoer nie, deur --no-metadata na die clone of init opdrag deur te gee.
Die metadata sluit 'n git-svn-id binne elke vasleggingsboodskap in wat Git tydens invoer sal genereer.
Dit kan jou Git-log laat uitswel en dit dalk 'n bietjie onduidelik maak.
|
Note
|
Jy moet die metadata behou wanneer jy vasleggings wat in die Git-bewaarplek gemaak is, terug wil spieël in die oorspronklike SVN-bewaarplek.
As jy nie die sinchronisasie in jou vasleggingslog wil hê nie, voel vry om die |
Dit laat jou import-opdrag so lyk:
$ git svn clone http://my-project.googlecode.com/svn/ \
--authors-file=users.txt --no-metadata --prefix "" -s my_project
$ cd my_project
Nou behoort jy 'n mooier Subversion-invoer in jou my_project gids te hê.
In plaas van vasleggings wat so lyk:
commit 37efa680e8473b615de980fa935944215428a35a
Author: schacon <schacon@4c93b258-373f-11de-be05-5f7a86268029>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
be05-5f7a86268029
lyk hulle soos dit:
commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
Author: Scott Chacon <schacon@geemail.com>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
Nie net lyk die Outeurveld baie beter nie, maar die git-svn-id is ook nie meer daar nie.
Jy moet ook 'n bietjie skoonmaak na die invoer doen.
Een ding is dat jy die vreemde verwysings wat git svn opgestel het, moet skoonmaak.
Eers sal jy die merkers skuif sodat dit werklike merkers is eerder as vreemde afgeleë takke, en dan sal jy die res van die takke skuif sodat hulle plaaslik is.
Om die merkers na egte Git-merkers te skuif, voer uit:
$ for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done
Dit neem die verwysings wat afgeleë takke was wat met refs/remotes/tags/ begin het, en maak werklike (liggewig) merkers daarvan.
Volgende, skuif die res van die verwysings onder refs/remotes om plaaslike takke te wees:
$ for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done
Dit kan gebeur dat jy 'n paar ekstra takke sal sien wat agtervoegsels het van @xxx (waar xxx 'n nommer is), terwyl jy in Subversion net een tak sien.
Dit is eintlik 'n Subversion-funksie genaamd “peg-revisions”, wat iets is waarvoor Git eenvoudig geen sintaktiese eweknie het nie.
Vandaar dat git svn eenvoudig die SVN-weergawenommer by die taknaam voeg op presies dieselfde manier as wat jy dit in SVN sou geskryf het om die peg-hersiening van daardie tak te adresseer.
As jy nie meer omgee vir die peg-hersienings nie, verwyder hulle eenvoudig:
$ for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done
Nou is al die ou takke egte Git-takke en al die ou merkers egte Git-merkers.
Daar is een laaste ding om op te skoon.
Ongelukkig skep git svn 'n ekstra tak genaamd trunk, wat na Subversion se verstektak karteer, maar die trunk verwysing wys na dieselfde plek as master.
Aangesien master meer idiomaties Git is, is hier hoe om die ekstra tak te verwyder:
$ git branch -d trunk
Die laaste ding om te doen is om jou nuwe Git-bediener as 'n remote by te voeg en daarna te push. Hier is 'n voorbeeld van die byvoeging van jou bediener as 'n remote:
$ git remote add origin git@my-git-server:myrepository.git
Omdat jy wil hê al jou takke en merkers moet opstoot, kan jy nou dit uitvoer:
$ git push origin --all
$ git push origin --tags
Al jou takke en merkers behoort op jou nuwe Git-bediener te wees in 'n lekker, skoon invoer.
Mercurial
Aangesien Mercurial en Git taamlik soortgelyke modelle het om weergawes te verteenwoordig, en aangesien Git 'n bietjie more buigsaam is, is dit vrij eenvoudig om 'n bewaarplek van Mercurial na Git te konverteer deur gebruik te maak van 'n hulpmiddel genaamd "hg-fast-export", waarvan jy 'n kopie nodig sal hê:
$ git clone https://github.com/frej/fast-export.git
Die eerste stap in die omskakeling is om 'n volledige kloon te kry van die Mercurial-bewaarplek wat jy wil konverteer:
$ hg clone <remote repo URL> /tmp/hg-repo
Die volgende stap is om 'n outeurskarteringslêer te skep.
Mercurial is 'n bietjie meer vergewensgesind as Git oor wat dit in die outeursveld vir wysigingstelle (changesets) plaas, so dit is 'n goeie tyd om huis skoon te maak.
Om dit te genereer is 'n eenreël-opdrag in 'n bash dop:
$ cd /tmp/hg-repo
$ hg log | grep user: | sort | uniq | sed 's/user: *//' > ../authors
Dit sal 'n paar sekondes neem, afhangende van hoe lank jou projek se geskiedenis is, en daarna sal die /tmp/authors lêer so iets lyk:
bob
bob@localhost
bob <bob@company.com>
bob jones <bob <AT> company <DOT> com>
Bob Jones <bob@company.com>
Joe Smith <joe@company.com>
In hierdie voorbeeld het dieselfde persoon (Bob) wysigingstelle geskep onder vier verskillende name, waarvan een eintlich korrek lyk, en een daarvoor heeltemal ongeldig sou wees vir 'n Git-vaslegging.
hg-fast-export laat ons dit regmaak deur elke reël in 'n reël te verander: "<input>"="<output>", wat 'n <input> na 'n <output> karteer.
Binne die <input> en <output> stringe word alle ontsnappingsreekse (escape sequences) wat deur die Python string_escape kodering verstaan word, ondersteun.
As die outeurskarteringslêer nie 'n ooreenstemmende <input> bevat nie, sal daardie outeur ongewijzigd na Git aangestuur word.
As al die gebruikersname goed lyk, benodig ons hierdie lêer glad nie.
In hierdie voorbeeld wil ons hê ons lêer moet so lyk:
"bob"="Bob Jones <bob@company.com>"
"bob@localhost"="Bob Jones <bob@company.com>"
"bob <bob@company.com>"="Bob Jones <bob@company.com>"
"bob jones <bob <AT> company <DOT> com>"="Bob Jones <bob@company.com>"
Dieselfde soort karteringslêer kan gebruik word om takke en merkers te hernoem wanneer die Mercurial-naam nie deur Git toegelaat word nie.
Die volgende stap is om ons nuwe Git-bewaarplek te skep en die uitvoerskrip te laat loop:
$ git init /tmp/converted
$ cd /tmp/converted
$ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors
Die -r vlag vertel hg-fast-export waar om die Mercurial-bewaarplek te vind wat ons wil konverteer, en die -A vlag vertel dit waar om die outeurskarteringslêer te vind (tak- en merkerkarteringslêers word onderskeidelik deur die -B en -T vlae gespesifiseer).
Die skrip ontleed Mercurial-wysigingstelle en skakel dit om in 'n skrip vir Git se "fast-import" kenmerk (wat ons 'n bietjie later in detail sal bespreek).
Dit neem 'n bietjie (alhoewel dit baie vinniger is as wat dit oor die netwerk sou wees), en die afvoer is taamlik lankdradig (verbose):
$ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors
Loaded 4 authors
master: Exporting full revision 1/22208 with 13/0/0 added/changed/removed files
master: Exporting simple delta revision 2/22208 with 1/1/0 added/changed/removed files
master: Exporting simple delta revision 3/22208 with 0/1/0 added/changed/removed files
[…]
master: Exporting simple delta revision 22206/22208 with 0/4/0 added/changed/removed files
master: Exporting simple delta revision 22207/22208 with 0/2/0 added/changed/removed files
master: Exporting thorough delta revision 22208/22208 with 3/213/0 added/changed/removed files
Exporting tag [0.4c] at [hg r9] [git :10]
Exporting tag [0.4d] at [hg r16] [git :17]
[…]
Exporting tag [3.1-rc] at [hg r21926] [git :21927]
Exporting tag [3.1] at [hg r21973] [git :21974]
Issued 22315 commands
git-fast-import statistics:
---------------------------------------------------------------------
Alloc'd objects: 120000
Total objects: 115032 ( 208171 duplicates )
blobs : 40504 ( 205320 duplicates 26117 deltas of 39602 attempts)
trees : 52320 ( 2851 duplicates 47467 deltas of 47599 attempts)
commits: 22208 ( 0 duplicates 0 deltas of 0 attempts)
tags : 0 ( 0 duplicates 0 deltas of 0 attempts)
Total branches: 109 ( 1 loads )
marks: 1048576 ( 22208 unique )
atoms: 1952
Memory total: 7860 KiB
pools: 2235 KiB
objects: 5625 KiB
---------------------------------------------------------------------
pack_report: getpagesize() = 4096
pack_report: core.packedGitWindowSize = 1073741824
pack_report: core.packedGitLimit = 8589934592
pack_report: pack_used_ctr = 90430
pack_report: pack_mmap_calls = 46771
pack_report: pack_open_windows = 1 / 1
pack_report: pack_mapped = 340852700 / 340852700
---------------------------------------------------------------------
$ git shortlog -sn
369 Bob Jones
365 Joe Smith
Dis omtrent al wat daar is. Al die Mercurial-merkers is na Git-merkers omgeskakel, en Mercurial-takke en -boekmerke is na Git-takke omgeskakel. Nou is jy gereed om die bewaarplek na sy nuwe bedienerkant-tuis te push:
$ git remote add origin git@my-git-server:myrepository.git
$ git push origin --all
Perforce
Die volgende stelsel waarna jy sal kyk om van in te voer, is Perforce.
Soos ons hierbo bespreek het, is daar twee maniere om Git en Perforce met mekaar te laat praat: git-p4 en Perforce Git Fusion.
Perforce Git Fusion
Git Fusion maak hierdie proses redelik pynloos. Konfigureer net jou projekinstellings, gebruikerskarterings (user mappings) en takke deur 'n konfigurasielêer te gebruik (soos bespreek in Git Fusion), en kloon die bewaarplek. Git Fusion laat jou met wat lyk soos 'n eie (native) Git-bewaarplek, wat dan gereed is om na 'n eie Git-gasheer gepush te word as jy wil. Jy kan selfs Perforce as jou Git-gasheer gebruik as jy verkies.
Git-p4
git-p4 kan ook as 'n invoerhulpmiddel dien.
As 'n voorbeeld sal ons die Jam-projek vanaf die Perforce Public Depot invoer.
Om jou kliënt op te stel, moet jy die P4PORT omgewingsveranderlike uitvoer (export) om na die Perforce-depot te wys:
$ export P4PORT=public.perforce.com:1666
|
Note
|
Om te kan volg, sal jy 'n Perforce-depot nodig hê om mee te verbind. Ons sal die openbare depot by public.perforce.com vir ons voorbeelde gebruik, maar jy kan enige depot gebruik waartoe jy toegang het. |
Voer die git p4 clone opdrag uit om die Jam-projek van die Perforce-bediener in te voer, deur die depot- en projekpad te verskaf asook die pad waarheen jy die projek wil invoer:
$ git-p4 clone //guest/perforce_software/jam@all p4import
Importing from //guest/perforce_software/jam@all into p4import
Initialized empty Git repository in /private/tmp/p4import/.git/
Import destination: refs/remotes/p4/master
Importing revision 9957 (100%)
Hierdie spesifieke projek het slegs een tak, maar as jy takke het wat opgestel is met tak-aansigte (branch views) (of net 'n stel gidse), kan jy die --detect-branches vlag saam met git p4 clone gebruik om al die projek se takke ook in te voer.
Sien Takking (Branching) vir 'n bietjie meer besonderhede hieroor.
Op hierdie stadium is jy amper klaar.
As jy na die p4import gids gaan en git log uitvoer, kan jy jou ingevoerde werk sien:
$ git log -2
commit e5da1c909e5db3036475419f6379f2c73710c4e6
Author: giles <giles@giles@perforce.com>
Date: Wed Feb 8 03:13:27 2012 -0800
Correction to line 355; change </UL> to </OL>.
[git-p4: depot-paths = "//public/jam/src/": change = 8068]
commit aa21359a0a135dda85c50a7f7cf249e4f7b8fd98
Author: kwirth <kwirth@perforce.com>
Date: Tue Jul 7 01:35:51 2009 -0800
Fix spelling error on Jam doc page (cummulative -> cumulative).
[git-p4: depot-paths = "//public/jam/src/": change = 7304]
Jy kan sien dat git-p4 'n identifiseerder in elke vasleggingsboodskap gelaat het.
Dit is heeltemal reg om daardie identifiseerder daar te hou, vir ingeval jy later na die Perforce-veranderingsnommer moet verwys.
As jy egter die identifiseerder wil verwyder, is dít nou die tyd om dit te doen – voordat jy aan die nuwe bewaarplek begin werk.
Jy kan git filter-branch gebruik om die identifiseerder-stringe en masse te verwyder:
$ git filter-branch --msg-filter 'sed -e "/^\[git-p4:/d"'
Rewrite e5da1c909e5db3036475419f6379f2c73710c4e6 (125/125)
Ref 'refs/heads/master' was rewritten
As jy git log uitvoer, kan jy sien dat al die SHA-1 kontrolesomme (checksums) vir die vasleggings verander het, maar die git-p4 stringe is nie meer in die vasleggingsboodskappe nie:
$ git log -2
commit b17341801ed838d97f7800a54a6f9b95750839b7
Author: giles <giles@giles@perforce.com>
Date: Wed Feb 8 03:13:27 2012 -0800
Correction to line 355; change </UL> to </OL>.
commit 3e68c2e26cd89cb983eb52c024ecdfba1d6b3fff
Author: kwirth <kwirth@perforce.com>
Date: Tue Jul 7 01:35:51 2009 -0800
Fix spelling error on Jam doc page (cummulative -> cumulative).
Jou invoer is gereed om na jou nuwe Git-bediener gepush te word.
'n Pasgemaakte Invoerder (A Custom Importer)
As jou stelsel nie een van bogenoemde is nie, moet jy aanlyn na 'n invoerder soek – gehalte-invoerders is beskikbaar vir baie ander stelsels, insluitend CVS, Clear Case, Visual Source Safe, selfs 'n gids van argiewe.
As geen van hierdie hulpmiddels vir jou werk nie, jy 'n meer obskure hulpmiddel het, of jy andersins 'n meer pasgemaakte invoerproses benodig, moet jy git fast-import gebruik.
Hierdie opdrag lees eenvoudige instruksies vanaf stdin om spesifieke Git-data te skryk.
Dit is baie makliker om Git-objekte op hierdie manier te skep as om die rou Git-opdragte uit te voer of te probeer om die rou objekte te skryf (sien Git Internals vir meer inligting).
Op hierdie manier kan jy 'n invoerskrip skryf wat die nodige inligting uit die stelsel lees waaruit jy invoer en reguit instruksies na stdout druk.
Jy kan dan hierdie program uitvoer en sy afvoer deur git fast-import pyp (pipe).
Om vinnig te demonstreer, gaan jy 'n eenvoudige invoerder skryf.
Sê nou jy werk in current, jy rugsteun jou projek deur die gids af en toe te kopieer na 'n tydgestempelde back_YYYY_MM_DD rugsteungids, en jy wil dit in Git invoer.
Jou gidsstruktuur lyk soos dit:
$ ls /opt/import_from
back_2014_01_02
back_2014_01_04
back_2014_01_14
back_2014_02_03
current
Ten einde 'n Git-gids in te voer, moet jy hersien hoe Git sy data stoor.
Soos jy dalk onthou, is Git fundamenteel 'n gekoppelde lys van vasleggingsobjekte (commit objects) wat wys na 'n momentopname (snapshot) van inhoud.
Al wat jy hoef te doen is om vir fast-import te sê wat die inhoudmomentopnames is, watter vasleggingsdata daarna wys, en die volgorde waarin hulle gaan.
Jou strategie sal wees om een vir een deur die momentopnames te gaan en vasleggings te skep met die inhoud van elke gids, en elke vaslegging terug te skakel na die vorige een.
Soos ons in 'n Voorbeeld van 'n Git-Afgedwonge Beleid (An Example Git-Enforced Policy) gedoen het, sal ons dit in Ruby skryf, omdat dit is waarmee ons gewoonlik werk en dit geneig is om maklik te lees te wees.
Jy kan hierdie voorbeeld pretty maklik skryf in enigiets waarmee jy vertroud is – dit hoef net die gepaste inligting na stdout te druk.
En, as jy op Windows loop, beteken dit dat jy spesiale sorg moet dra om nie wa-terugvoere (carriage returns) aan die einde van jou reëls in te voer nie – git fast-import is baie kieskeurig oor net die wil van reëltoevoere (line feeds - LF) en nie die wa-terugvoer-reëltoevoere (CRLF) wat Windows gebruik nie.
Om te begin, sal jy na die teikengids verander en elke subgids identifiseer, wat elk 'n momentopname is wat jy as 'n vaslegging wil invoer. Jy sal in elke subgids verander en die opdragte druk wat nodig is om dit te eksporteer. Jou basiese hooflus lyk soos dit:
last_mark = nil
# loop through the directories
Dir.chdir(ARGV[0]) do
Dir.glob("*").each do |dir|
next if File.file?(dir)
# move into the target directory
Dir.chdir(dir) do
last_mark = print_export(dir, last_mark)
end
end
end
Jy voer print_export binne elke gids uit, wat die manifes en merker van die vorige momentopname neem en die manifes en merker van hierdie een teruggee; op daardie manier kan jy hulle behoorlik koppel.
“Merker” (Mark) is die fast-import term vir 'n identifiseerder wat jy aan 'n vaslegging gee; terwyl jy vasleggings skep, gee jy elkeen 'n merker wat jy kan gebruik om van ander vasleggings daaraan te skakel.
Dus, die eerste ding om te doen in jou print_export metode is om 'n merker uit die gidself te genereer:
mark = convert_dir_to_mark(dir)
Jy sal dit doen deur 'n skikking (array) van gidse te skep en die indeksiewaarde as die merker te gebruik, omdat 'n merker 'n heelgetal (integer) moet wees. Jou metode lyk soos dit:
$marks = []
def convert_dir_to_mark(dir)
if !$marks.include?(dir)
$marks << dir
end
($marks.index(dir) + 1).to_s
end
Noudat jy 'n heelgetalvoorstelling van jou vaslegging het, benodig jy 'n datum vir die vasleggingsmetadata.
Omdat die datum in die naam van die gids uitgedruk word, gaan jy dit ontleed.
Die volgende reël in jou print_export lêer is:
date = convert_dir_to_date(dir)
waar convert_dir_to_date gedefinieer word as:
def convert_dir_to_date(dir)
if dir == 'current'
return Time.now().to_i
else
dir = dir.gsub('back_', '')
(year, month, day) = dir.split('_')
return Time.local(year, month, day).to_i
end
end
Dit gee 'n heelgetalwaarde terug vir die datum van elke gids. Die laaste stukmetainligting wat jy vir elke vaslegging benodig, is die vaslêerdata (committer data), wat jy hardkodeer in 'n globale veranderlike:
$author = 'John Doe <john@example.com>'
Nou is jy gereed om te begin met die druk van die vasleggingsdata vir jou invoerder. Die aanvanklike inligting vermeld dat jy 'n vasleggingsobjek definieer en op watter tak dit is, gevolg deur die merker wat jy gegenereer het, die vaslêerinligting en vasleggingsboodskap, en dan die vorige vaslegging, indien enige. Die code lyk soos dit:
# print the import information
puts 'commit refs/heads/master'
puts 'mark :' + mark
puts "committer #{$author} #{date} -0700"
export_data('imported from ' + dir)
puts 'from :' + last_mark if last_mark
Jy hardkodeer die tydsone (-0700) omdat dit maklik is om dit te doen. As jy van 'n ander stelsel invoer, moet jy die tydsone as 'n verrekening (offset) spesifiseer. Die vasleggingsboodskap moet in 'n spesiale formaat uitgedruk word:
data (size)\n(contents)
Die formaat bestaan uit die woord data, die grootte van die data wat gelees moet word, 'n nuwe reël, en uiteindelik die data.
Omdat jy dieselfde formaat moet gebruik om die lêerinhoud later te spesifiseer, skep jy 'n hulpmetode, export_data:
def export_data(string)
print "data #{string.size}\n#{string}"
end
Al wat oorbly, is om die lêerinhoud vir elke momentopname te spesifiseer.
Dit is maklik, omdat jy elk in 'n gids het – jy kan die deleteall opdrag druk, gevolg deur die inhoud van elke lêer in die gids.
Git sal dan elke momentopname gepas opteken:
puts 'deleteall'
Dir.glob("**/*").each do |file|
next if !File.file?(file)
inline_data(file)
end
Let wel: Omdat baie stelsels dink aan hul hersienings as veranderings van een vaslegging na 'n ander, kan fast-import ook opdragte neem met elke vaslegging om te spesifiseer watter lêers bygevoeg, verwyder of gewysig is en wat die nuwe inhoud is.
Jy kan die verskille tussen momentopnames bereken en slegs hierdie data verskaf, maar om dit te doen is more kompleks – jy kan net as well vir Git al die data gee en dit laat uitvind.
As dit beter by jou data pas, kyk na die fast-import man-bladsy vir besonderhede oor hoe om jou data op hierdie manier te verskaf.
Die formaat vir die lys van die nuwe lêerinhoud of die spesifikasie van 'n gewysigde lêer met die nuwe inhoud is as volg:
M 644 inline path/to/file
data (size)
(file contents)
Hier is 644 die modus (as jy uitvoerbare lêers het, moet jy 755 in plaas daarvan detekteer en spesifiseer), en inline sê dat jy die inhoud onmiddellik na hierdie reël sal lys.
Jou inline_data metode lyk soos dit:
def inline_data(file, code = 'M', mode = '644')
content = File.read(file)
puts "#{code} #{mode} inline #{file}"
export_data(content)
end
Jy hergebruik die export_data metode wat jy vroeër gedefinieer het, omdat dit dieselfde is as die manier waarop jy jou vasleggingsboodskapdata gespesifiseer het.
Die laaste ding wat jy moet doen is om die huidige merker terug te gee sodat dit aan die volgende herhaling (iteration) deurgegee kan word:
return mark
|
Note
|
As jy op Windows loop, moet jy seker maak dat jy een ekstra stap byvoeg.
Soos voorheen genoem, gebruik Windows CRLF vir nuwe reëlkarakters terwyl
|
Dis dit. Hier is die skrip in sy geheel:
#!/usr/bin/env ruby
$stdout.binmode
$author = "John Doe <john@example.com>"
$marks = []
def convert_dir_to_mark(dir)
if !$marks.include?(dir)
$marks << dir
end
($marks.index(dir)+1).to_s
end
def convert_dir_to_date(dir)
if dir == 'current'
return Time.now().to_i
else
dir = dir.gsub('back_', '')
(year, month, day) = dir.split('_')
return Time.local(year, month, day).to_i
end
end
def export_data(string)
print "data #{string.size}\n#{string}"
end
def inline_data(file, code='M', mode='644')
content = File.read(file)
puts "#{code} #{mode} inline #{file}"
export_data(content)
end
def print_export(dir, last_mark)
date = convert_dir_to_date(dir)
mark = convert_dir_to_mark(dir)
puts 'commit refs/heads/master'
puts "mark :#{mark}"
puts "committer #{$author} #{date} -0700"
export_data("imported from #{dir}")
puts "from :#{last_mark}" if last_mark
puts 'deleteall'
Dir.glob("**/*").each do |file|
next if !File.file?(file)
inline_data(file)
end
mark
end
# Loop through the directories
last_mark = nil
Dir.chdir(ARGV[0]) do
Dir.glob("*").each do |dir|
next if File.file?(dir)
# move into the target directory
Dir.chdir(dir) do
last_mark = print_export(dir, last_mark)
end
end
end
As jy hierdie skrip uitvoer, kry jy inhoud wat so iets lyk:
$ ruby import.rb /opt/import_from
commit refs/heads/master
mark :1
committer John Doe <john@example.com> 1388649600 -0700
data 29
imported from back_2014_01_02deleteall
M 644 inline README.md
data 28
# Hello
This is my readme.
commit refs/heads/master
mark :2
committer John Doe <john@example.com> 1388822400 -0700
data 29
imported from back_2014_01_04from :1
deleteall
M 644 inline main.rb
data 34
#!/bin/env ruby
puts "Hey there"
M 644 inline README.md
(...)
Om die invoerder te laat loop, pyp hierdie afvoer deur git fast-import terwyl jy in die Git-gids is waarin jy wil invoer.
Jy kan 'n nuwe gids skep en dan git init daarin uitvoer vir 'n beginpunt, en dan jou skrip uitvoer:
$ git init
Initialized empty Git repository in /opt/import_to/.git/
$ ruby import.rb /opt/import_from | git fast-import
git-fast-import statistics:
---------------------------------------------------------------------
Alloc'd objects: 5000
Total objects: 13 ( 6 duplicates )
blobs : 5 ( 4 duplicates 3 deltas of 5 attempts)
trees : 4 ( 1 duplicates 0 deltas of 4 attempts)
commits: 4 ( 1 duplicates 0 deltas of 0 attempts)
tags : 0 ( 0 duplicates 0 deltas of 0 attempts)
Total branches: 1 ( 1 loads )
marks: 1024 ( 5 unique )
atoms: 2
Memory total: 2344 KiB
pools: 2110 KiB
objects: 234 KiB
---------------------------------------------------------------------
pack_report: getpagesize() = 4096
pack_report: core.packedGitWindowSize = 1073741824
pack_report: core.packedGitLimit = 8589934592
pack_report: pack_used_ctr = 10
pack_report: pack_mmap_calls = 5
pack_report: pack_open_windows = 2 / 2
pack_report: pack_mapped = 1457 / 1457
---------------------------------------------------------------------
Soos jy kan sien, wanneer dit suksesvol voltooi word, gee dit vir jou 'n trop statistieke oor wat dit bereik het.
In hierdie geval het jy in totaal 13 objekte vir 4 vasleggings in 1 tak ingevoer.
Nou kan jy git log uitvoer om jou nuwe geskiedenis te sien:
$ git log -2
commit 3caa046d4aac682a55867132ccdfbe0d3fdee498
Author: John Doe <john@example.com>
Date: Tue Jul 29 19:39:04 2014 -0700
imported from current
commit 4afc2b945d0d3c8cd00556fbe2e8224569dc9def
Author: John Doe <john@example.com>
Date: Mon Feb 3 01:00:00 2014 -0700
imported from back_2014_02_03
Daar het jy dit – 'n lekker, skoon Git-bewaarplek.
Dit is belangrik om op te let dat niks uitgetrek is nie – jy het aanvanklik geen lêers in jou werkgids nie.
Om hulle te kry, moet jy jou tak herstel (reset) na waar master nou is:
$ ls
$ git reset --hard master
HEAD is now at 3caa046 imported from current
$ ls
README.md main.rb
Jy kan baie meer met die fast-import hulpmiddel doen – verskillende modusse hanteer, binêre data, veelvuldige takke en saamsmelting, merkers, vorderingaanwysers, en meer.
'n Aantal voorbeelde van meer kompleks scenario’s is beskikbaar in die contrib/fast-import gids van die Git-bronkode.