-
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
7.11 Git Tools - Submodules
Submodules
Dit gebeur dikwels dat terwyl jy aan een projek werk, jy 'n ander projek daaruit moet gebruik. Miskien is dit 'n biblioteek wat 'n derde party ontwikkel het of wat jy afsonderlik ontwikkel en in veelvuldige ouerprojekte gebruik. 'n Algemene probleem ontstaan in hierdie scenario’s: jy wil die twee projekte as afsonderlik kan hanteer, maar tog die een vanuit die ander kan gebruik.
Hier is 'n voorbeeld. Sê nou jy ontwikkel 'n webwerf en skep Atom-voere. In plaas daarvan om jou eie Atom-genererende kode te skryf, besluit jy om 'n biblioteek te gebruik. Jy sal waarskynlik hierdie kode moet insluit vanaf 'n gedeelde biblioteek soos 'n CPAN-installasie of Ruby-gem, of die bronkode in jou eie projekboom kopieer. Die probleem met die insluiting van die biblioteek is dat dit moeilik is om die biblioteek op enige manier aan te pas en dikwels moeiliker om dit te ontplooi (deploy), aangesien jy moet seker maak dat elke kliënt daardie biblioteek beskikbaar het. Die probleem met die kopiëring van die kode in jou eie projek, is dat enige pasgemaakte veranderings wat jy maak moeilik is om in te smelt wanneer stroomopwaartse veranderings beskikbaar word.
Git pak hierdie probleem aan met behulp van submodules. Submodules laat jou toe om 'n Git-bewaarplek (repository) as 'n subgids van 'n ander Git-bewaarplek te hou. Dit laat jou toe om 'n ander bewaarplek in jou projek te kloon en jou vasleggings (commits) afsonderlik te hou.
Om met Submodules te Begin
Ons sal stap vir stap deur die ontwikkeling van 'n eenvoudige projek gaan wat in 'n hoofprojek en 'n paar subprojekte opgedeel is.
Kom ons begin deur 'n bestaande Git-bewaarplek as 'n submodule by te voeg van die bewaarplek waaraan ons werk.
Om 'n nuwe submodule by te voeg, gebruik jy die git submodule add opdrag met die absolute of relatiewe URL van die projek wat jy wil begin naspoor.
In hierdie voorbeeld sal ons 'n biblioteek genaamd “DbConnector” byvoeg.
$ git submodule add https://github.com/chaconinc/DbConnector
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
By verstek sal submodules die subprojek byvoeg in 'n gids met dieselfde naam as die bewaarplek, in hierdie geval “DbConnector”. Jy kan 'n ander pad aan die einde van die opdrag byvoeg as jy wil hê dit moet iewers anders heengaan.
As jy git status op hierdie punt uitvoer, sal jy 'n paar dinge opmerk.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitmodules
new file: DbConnector
Eerstens behoort jy die nuwe .gitmodules lêer op te merk.
Dit is 'n konfigurasielêer wat die kartering (mapping) stoor tussen die projek se URL en die plaaslike subgids waarin jy dit ingetrek het:
[submodule "DbConnector"]
path = DbConnector
url = https://github.com/chaconinc/DbConnector
As jy veelvuldige submodules het, sal jy veelvuldige inskrywings in hierdie lêer hê.
Dit is belangrik om op te let dat hierdie lêer onder weergawebeheer is saam met jou ander lêers, soos jou .gitignore lêer.
Dit word met die res van jou projek opgestuur en ingetrek (pushed and pulled).
Dit is hoe ander mense wat hierdie projek kloon, weet waar om die submoduleprojekte vandaan te kry.
|
Note
|
Aangesien die URL in die .gitmodules-lêer is waarvandaan ander mense eers sal probeer kloon/afhaal, maak seker dat jy 'n URL gebruik waartoe hulle toegang het indien moontlik.
Byvoorbeeld, as jy 'n ander URL gebruik om na te push as waarvandaan ander sou pull, gebruik die een waartoe ander toegang het.
Jy kan hierdie waarde plaaslik oorskryf met |
Die ander lys in die git status afvoer is die projekvouerinskrywing.
As jy git diff daarop uitvoer, sien jy iets interessant:
$ git diff --cached DbConnector
diff --git a/DbConnector b/DbConnector
new file mode 160000
index 0000000..c3f01dc
--- /dev/null
+++ b/DbConnector
@@ -0,0 +1 @@
+Subproject commit c3f01dc8862123d317dd46284b05b6892c7b29bc
Alhoewel DbConnector 'n subgids in jou werkgids is, sien Git dit as 'n submodule en spoor nie sy inhoud na as jy nie in daardie gids is nie.
In plaas daarvan sien Git dit as 'n spesifieke vaslegging van daardie bewaarplek.
As jy 'n effens mooier diff-afvoer wil hê, kan jy die --submodule opsie aan git diff deurgee.
$ git diff --cached --submodule
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..71fc376
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "DbConnector"]
+ path = DbConnector
+ url = https://github.com/chaconinc/DbConnector
Submodule DbConnector 0000000...c3f01dc (new submodule)
Wanneer jy vaslê (commit), sien jy iets soos dit:
$ git commit -am 'Add DbConnector module'
[master fb9093c] Add DbConnector module
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 DbConnector
Let op die 160000 modus vir die DbConnector inskrywing.
Dit is 'n spesiale modus in Git wat basies beteken dat jy 'n vaslegging aanteken as 'n gidsinskrywing in plaas van 'n subgids of 'n lêer.
Laastens, push hierdie veranderings:
$ git push origin master
Kloning van 'n Projek met Submodules
Hier sal ons 'n projek kloon wat 'n submodule in het. Wanneer jy so 'n projek kloon, kry jy by verstek die gidse wat submodules bevat, maar nog geen van die lêers binne-in hulle nie:
$ git clone https://github.com/chaconinc/MainProject
Cloning into 'MainProject'...
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 14 (delta 1), reused 13 (delta 0)
Unpacking objects: 100% (14/14), done.
Checking connectivity... done.
$ cd MainProject
$ ls -la
total 16
drwxr-xr-x 9 schacon staff 306 Sep 17 15:21 .
drwxr-xr-x 7 schacon staff 238 Sep 17 15:21 ..
drwxr-xr-x 13 schacon staff 442 Sep 17 15:21 .git
-rw-r--r-- 1 schacon staff 92 Sep 17 15:21 .gitmodules
drwxr-xr-x 2 schacon staff 68 Sep 17 15:21 DbConnector
-rw-r--r-- 1 schacon staff 756 Sep 17 15:21 Makefile
drwxr-xr-x 3 schacon staff 102 Sep 17 15:21 includes
drwxr-xr-x 4 schacon staff 136 Sep 17 15:21 scripts
drwxr-xr-x 4 schacon staff 136 Sep 17 15:21 src
$ cd DbConnector/
$ ls
$
Die DbConnector gids is daar, maar leeg.
Jy moet twee opdragte vanaf die hoofprojek uitvoer: git submodule init om jou plaaslike konfigurasielêer te inisialiseer, en git submodule update om al die data van daardie projek af te haal en die toepaslike vaslegging uit te check wat in jou superprojek gelys is:
$ git submodule init
Submodule 'DbConnector' (https://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
$ git submodule update
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'
Nou is jou DbConnector subgids op die presiese toestand as wat dit was toe jy vroeër vasgelê het.
Daar is egter 'n ander manier om dit te doen wat 'n bietjie makliker is.
As jy --recurse-submodules by die git clone opdrag voeg, sal dit outomaties elke submodule in die bewaarplek inisialiseer en opdateer, insluitend geneste submodules as enige van die submodules in die bewaarplek self submodules het.
$ git clone --recurse-submodules https://github.com/chaconinc/MainProject
Cloning into 'MainProject'...
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 14 (delta 1), reused 13 (delta 0)
Unpacking objects: 100% (14/14), done.
Checking connectivity... done.
Submodule 'DbConnector' (https://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'
As jy reeds die projek gekloon het en --recurse-submodules vergeet het, kan jy die git submodule init en git submodule update stappe kombineer deur git submodule update --init uit te voer.
Om ook enige geneste submodules te inisialiseer, af te haal en uit te check, kan jy die onfeilbare git submodule update --init --recursive gebruik.
Werk aan 'n Projek met Submodules
Nou het ons 'n kopie van 'n projek met submodules daarin en sal met ons spanmaats saamwerk op beide die hoofprojek en die submoduleprojek.
Intrek van Stroomopwaartse Veranderings vanaf die Submodule-remote
Die eenvoudigste model vir die gebruik van submodules in 'n projek sal wees as jy net 'n subprojek verbruik en van tyd tot tyd opdaterings daaruit wil kry, maar nie regtig iets in jou checkout wysig nie. Kom ons stap deur 'n eenvoudige voorbeeld daarvan.
As jy wil kyk vir nuwe werk in 'n submodule, kan jy in die gids ingaan en git fetch uitvoer en git merge op die stroomopwaartse tak doen om die plaaslike kode by te werk.
$ git fetch
From https://github.com/chaconinc/DbConnector
c3f01dc..d0354fc master -> origin/master
$ git merge origin/master
Updating c3f01dc..d0354fc
Fast-forward
scripts/connect.sh | 1 +
src/db.c | 1 +
2 files changed, 2 insertions(+)
Nou as jy teruggaan na die hoofprojek en git diff --submodule uitvoer, kan jy sien dat die submodule opgedateer is en 'n lys kry van vasleggings wat daaraan bygevoeg is.
As jy nie --submodule elke keer as jy git diff uitvoer wil intik nie, kan jy dit as die verstekformaat stel deur die diff.submodule konfigurasiewaarde op “log” te stel.
$ git config --global diff.submodule log
$ git diff
Submodule DbConnector c3f01dc..d0354fc:
> more efficient db routine
> better connection routine
As jy op hierdie punt vaslê, sal jy die submodule sluit (lock) sodat dit die nuwe kode het wanneer ander mense opdateer.
Daar is ook 'n makliker manier om dit te doen, as jy verkies om nie met die hand af te haal en te smelt in die subgids nie.
As jy git submodule update --remote uitvoer, sal Git in jou submodules ingaan en namens jou afhaal en opdateer.
$ git submodule update --remote DbConnector
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 2), reused 4 (delta 2)
Unpacking objects: 100% (4/4), done.
From https://github.com/chaconinc/DbConnector
3f19983..d0354fc master -> origin/master
Submodule path 'DbConnector': checked out 'd0354fc054692d3906c85c3af05ddce39a1c0644'
Hierdie opdrag sal by verstek aanneem dat jy die checkout wil opdateer na die verstektak van die afgeleë submodule-bewaarplek (die een waarna HEAD op die remote wys).
Jy kan dit egter stel op iets anders as jy wil.
Byvoorbeeld, as jy wil hê die DbConnector submodule moet daardie bewaarplek se “stable” tak naspoor, kan jy dit stel in óf jou .gitmodules lêer (sodat almal anders dit ook naspoor), óf net in jou plaaslike .git/config lêer.
Kom ons stel dit in die .gitmodules lêer:
$ git config -f .gitmodules submodule.DbConnector.branch stable
$ git submodule update --remote
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 2), reused 4 (delta 2)
Unpacking objects: 100% (4/4), done.
From https://github.com/chaconinc/DbConnector
27cf5d3..c87d55d stable -> origin/stable
Submodule path 'DbConnector': checked out 'c87d55d4c6d4b05ee34fbc8cb6f7bf4585ae6687'
As jy die -f .gitmodules weglaat sal dit net die verandering vir jou maak, maar dit maak waarskynlik meer sin om daardie inligting saam met die bewaarplek te spoor sodat almal dit ook doen.
Wanneer ons op hierdie punt git status uitvoer, sal Git vir ons wys dat ons “new commits” (nuwe vasleggings) op die submodule het.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: .gitmodules
modified: DbConnector (new commits)
no changes added to commit (use "git add" and/or "git commit -a")
As jy die konfigurasie-instelling status.submodulesummary stel, sal Git ook vir jou 'n kort opsomming van veranderings aan jou submodules wys:
$ git config status.submodulesummary 1
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: .gitmodules
modified: DbConnector (new commits)
Submodules changed but not updated:
* DbConnector c3f01dc...c87d55d (4):
> catch non-null terminated lines
As jy op hierdie oomblik git diff uitvoer, kan ons sien dat ons beide ons .gitmodules lêer gewysig het en ook dat daar 'n aantal vasleggings is wat ons ingetrek het en gereed is om na ons submodule-projek vas te lê.
$ git diff
diff --git a/.gitmodules b/.gitmodules
index 6fc0b3d..fd1cc29 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,4 @@
[submodule "DbConnector"]
path = DbConnector
url = https://github.com/chaconinc/DbConnector
+ branch = stable
Submodule DbConnector c3f01dc..c87d55d:
> catch non-null terminated lines
> more robust error handling
> more efficient db routine
> better connection routine
Dit is nogal oulik aangesien ons regtig die log van vasleggings kan sien wat ons op die punt is om na ons submodule vas te lê.
Sodra dit vasgelê is, kan jy hierdie inligting ook agterna sien wanneer jy git log -p uitvoer.
$ git log -p --submodule
commit 0a24cfc121a8a3c118e0105ae4ae4c00281cf7ae
Author: Scott Chacon <schacon@gmail.com>
Date: Wed Sep 17 16:37:02 2014 +0200
updating DbConnector for bug fixes
diff --git a/.gitmodules b/.gitmodules
index 6fc0b3d..fd1cc29 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,4 @@
[submodule "DbConnector"]
path = DbConnector
url = https://github.com/chaconinc/DbConnector
+ branch = stable
Submodule DbConnector c3f01dc..c87d55d:
> catch non-null terminated lines
> more robust error handling
> more efficient db routine
> better connection routine
Git sal by verstek probeer om al jou submodules op te dateer wanneer jy git submodule update --remote uitvoer.
As jy baie daarvan het, sal jy dalk die naam wil deurgee van slegs die submodule wat jy wil probeer opdateer.
Intrek van Stroomopwaartse Veranderings vanaf die Projek-remote
Kom ons plaas ons nou in die skoene van jou medewerker, wat hul eie plaaslike kloon van die MainProject-bewaarplek het.
Om bloot git pull uit te voer om jou nuut-vasgelegde veranderings te kry, is nie genoeg nie:
$ git pull
From https://github.com/chaconinc/MainProject
fb9093c..0a24cfc master -> origin/master
Fetching submodule DbConnector
From https://github.com/chaconinc/DbConnector
c3f01dc..c87d55d stable -> origin/stable
Updating fb9093c..0a24cfc
Fast-forward
.gitmodules | 2 +-
DbConnector | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: DbConnector (new commits)
Submodules changed but not updated:
* DbConnector c87d55d...c3f01dc (4):
< catch non-null terminated lines
< more robust error handling
< more efficient db routine
< better connection routine
no changes added to commit (use "git add" and/or "git commit -a")
By verstek haal die git pull opdrag rekursief submoduleveranderings af (fetch), soos ons in die afvoer van die eerste opdrag hierbo kan sien.
Dit dateer egter nie die submodules op nie.
Dit word getoon deur die afvoer van die git status opdrag, wat wys dat die submodule “modified” is, en “new commits” het.
Wat meer is, die hakies wat die nuwe vasleggings wys, wys na links (<), wat aandui dat hierdie vasleggings in MainProject opgeteken is, maar nie teenwoordig is in die plaaslike DbConnector checkout nie.
Om die opdatering te finaliseer, moet jy git submodule update uitvoer:
$ git submodule update --init --recursive
Submodule path 'vendor/plugins/demo': checked out '48679c6302815f6c76f1fe30625d795d9e55fc56'
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
Let daarop dat jy om aan die veilige kant te wees, git submodule update met die --init vlag moet uitvoer vir ingeval die MainProject-vasleggings wat jy so pas ingetrek het nuwe submodules bygevoeg het, en met die --recursive vlag indien enige submodules geneste submodules het.
As jy hierdie proses wil outomatiseer, kan jy die --recurse-submodules vlag by die git pull opdrag voeg (sedert Git 2.14).
Dit sal Git git submodule update dadelik ná die pull laat uitvoer en die submodules in die regte toestand plaas.
Boonop, as jy wil hê dat Git altyd moet intrek met --recurse-submodules, kan jy die konfigurasie-opsie submodule.recurse stel na true (dit werk vir git pull sedert Git 2.15).
Hierdie opsie sal maak dat Git die --recurse-submodules vlag gebruik vir alle opdragte wat dit ondersteun (behalwe clone).
Daar is 'n spesiale situasie wat kan gebeur wanneer superprojekopdaterings ingetrek word: dit kan wees dat die stroomopwaartse bewaarplek die URL van die submodule in die .gitmodules lêer in een van die vasleggings wat jy intrek verander het.
Dit kan byvoorbeeld gebeur as die submoduleprojek sy gasheerplatform verander.
In daardie geval is dit moontlik dat git pull --recurse-submodules, of git submodule update, misluk as die superprojek verwys na 'n submodule-vaslegging wat nie gevind word in die submodule se remote soos plaaslik in jou bewaarplek opgestel is nie.
Om hierdie situasie reg te stel, word die git submodule sync opdrag benodig:
# kopieer die nuwe URL na jou plaaslike konfigurasie
$ git submodule sync --recursive
# dateer die submodule op vanaf die nuwe URL
$ git submodule update --init --recursive
Werk aan 'n Submodule
Dit is hoogs waarskynlik dat as jy submodules gebruik, jy dit doen omdat jy regtig aan die kode in die submodule wil werk terwyl jy aan die kode in die hoofprojek (of oor verskeie submodules heen) werk. Andersins sou jy waarskynlik eerder 'n eenvoudiger afhanklikheidsbestuurstelsel (dependency management system soos Maven of Rubygems) gebruik het.
Kom ons gaan nou deur 'n voorbeeld waar ons gelyktydig veranderings aan die submodule asook aan die hoofprojek maak, en daardie veranderings terselfdertyd vaslê en publiseer.
Tot dusver, wanneer ons die git submodule update opdrag uitgevoer het om veranderings van die submodule-bewaarplekke te haal, het Git die veranderings gekry en die lêers in die subgids opgedateer, maar sal die sub-bewaarplek agterlaat in 'n sogenaamde “detached HEAD” toestand.
Dit beteken dat daar geen plaaslike werktak (soos master byvoorbeeld) is wat veranderings naspoor nie.
Sonder 'n werktak wat veranderings naspoor, beteken dit dat selfs as jy veranderings na die submodule vaslê, sal daardie veranderings heel moontlik verlore raak die volgende keer as jy git submodule update uitvoer.
Jy moet 'n paar ekstra stappe doen as jy wil hê dat veranderings in 'n submodule nagespoor moet word.
Om jou submodule so op te stel dat dit makliker is om daarin te gaan en te kap, moet jy twee dinge doen.
Jy moet in elke submodule ingaan en 'n tak uittrek om aan te werk.
Dan moet jy vir Git vertel wat om te doen as jy veranderings gemaak het en later git submodule update --remote nuwe werk van stroomop intrek.
Die opsies is dat jy dit in jou plaaslike werk kan insmelt (merge), of jy kan probeer om jou plaaslike werk bo-op die nuwe veranderings te rebase.
Kom ons gaan eerstens in ons submodule-gids in en trek 'n tak uit.
$ cd DbConnector/
$ git checkout stable
Switched to branch 'stable'
Kom ons probeer ons submodule opdateer met die “merge” opsie.
Om dit handmatig te spesifiseer, kan ons bloot die --merge opsie by ons update oproep voeg.
Hier sal ons sien dat daar 'n verandering op die bediener vir hierdie submodule was en dit word ingesmelt.
$ cd ..
$ git submodule update --remote --merge
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 2), reused 4 (delta 2)
Unpacking objects: 100% (4/4), done.
From https://github.com/chaconinc/DbConnector
c87d55d..92c7337 stable -> origin/stable
Updating c87d55d..92c7337
Fast-forward
src/main.c | 1 +
1 file changed, 1 insertion(+)
Submodule path 'DbConnector': merged in '92c7337b30ef9e0893e758dac2459d07362ab5ea'
As ons in die DbConnector gids ingaan, is die nuwe veranderings reeds in ons plaaslike stable tak ingesmelt.
Kom ons kyk nou wat gebeur wanneer ons ons eie plaaslike verandering aan die biblioteek maak en iemand anders op dieselfde tyd nog 'n verandering stroomopwaarts push.
$ cd DbConnector/
$ vim src/db.c
$ git commit -am 'Unicode support'
[stable f906e16] Unicode support
1 file changed, 1 insertion(+)
As ons nou ons submodule opdateer, kan ons sien wat gebeur wanneer ons 'n plaaslike verandering aangebring het en daar stroomop ook 'n verandering is wat ons moet inkorporeer.
$ cd ..
$ git submodule update --remote --rebase
First, rewinding head to replay your work on top of it...
Applying: Unicode support
Submodule path 'DbConnector': rebased into '5d60ef9bbebf5a0c1c1050f242ceeb54ad58da94'
As jy die --rebase of --merge vergeet, sal Git bloot die submodule opdateer na wat ook al op die bediener is en jou projek terugstel na 'n "detached HEAD"-toestand.
$ git submodule update --remote
Submodule path 'DbConnector': checked out '5d60ef9bbebf5a0c1c1050f242ceeb54ad58da94'
As dit gebeur, moenie bekommerd wees nie, jy kan eenvoudig teruggaan in die gids en weer jou tak uittrek (wat steeds jou werk sal bevat) en met die hand origin/stable (of watter afgeleë tak jy ook al wil hê) insmelt of rebase.
As jy nie jou veranderings in jou submodule vasgelê het nie en jy voer 'n submodule update uit wat probleme sou veroorsaak, sal Git die veranderings afhaal, maar nie ongestoorde werk in jou submodulegids oorskryf nie.
$ git submodule update --remote
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 4 (delta 0)
Unpacking objects: 100% (4/4), done.
From https://github.com/chaconinc/DbConnector
5d60ef9..c75e92a stable -> origin/stable
error: Your local changes to the following files would be overwritten by checkout:
scripts/setup.sh
Please, commit your changes or stash them before you can switch branches.
Aborting
Unable to checkout 'c75e92a2b3855c9e5b66f915308390d9db204aca' in submodule path 'DbConnector'
As jy veranderings gemaak het wat in stryd is met iets wat stroomopwaarts verander is, sal Git jou laat weet wanneer jy die opdatering uitvoer.
$ git submodule update --remote --merge
Auto-merging scripts/setup.sh
CONFLICT (content): Merge conflict in scripts/setup.sh
Recorded preimage for 'scripts/setup.sh'
Automatic merge failed; fix conflicts and then commit the result.
Unable to merge 'c75e92a2b3855c9e5b66f915308390d9db204aca' in submodule path 'DbConnector'
Jy kan in die submodule-gids ingaan en die konflik regmaak soos jy normaalweg sou doen.
Publiseer Submodule Veranderings
Nou het ons 'n paar veranderings in ons submodule-gids. Sommige hiervan is van stroomop deur ons opdaterings ingebring en ander is plaaslik gemaak en is nog nie aan enigiemand anders beskikbaar nie aangesien ons dit nog nie gepush het nie.
$ git diff
Submodule DbConnector c87d55d..82d2ad3:
> Merge from origin/stable
> Update setup script
> Unicode support
> Remove unnecessary method
> Add new option for conn pooling
As ons in die hoofprojek vaslê en dit push sonder om ook die submoduleveranderings op te push, gaan ander mense wat ons veranderings probeer uittrek, in die moeilikheid wees, want hulle sal geen manier hê om die submoduleveranderings te kry waarvan afhanklik is nie. Daardie veranderings sal slegs op ons plaaslike kopie bestaan.
Om seker te maak dat dit nie gebeur nie, kan jy Git vra om te kyk dat al jou submodules behoorlik gepush is voordat jy die hoofprojek push.
Die git push opdrag neem die --recurse-submodules argument wat gestel kan word na óf “check” óf “on-demand”.
Die “check” opsie sal maak dat push eenvoudig misluk as enige van die vasgelegde submoduleveranderings nie gepush is nie.
$ git push --recurse-submodules=check
The following submodule paths contain changes that can
not be found on any remote:
DbConnector
Please try
git push --recurse-submodules=on-demand
or cd to the path and use
git push
to push them to a remote.
Soos jy kan sien, gee dit vir ons ook nuttige raad oor wat ons volgende sal wil doen.
Die eenvoudige opsie is om in elke submodule in te gaan en met die hand na die remotes te push om seker te maak dat hulle ekstern beskikbaar is, en dan hierdie push weer te probeer.
As jy wil hê dat die “check” gedrag vir alle pushes moet plaasvind, kan jy hierdie gedrag die verstek maak deur git config push.recurseSubmodules check uit te voer.
Die ander opsie is om die “on-demand” waarde te gebruik, wat dit vir jou sal probeer doen.
$ git push --recurse-submodules=on-demand
Pushing submodule 'DbConnector'
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.
Total 9 (delta 3), reused 0 (delta 0)
To https://github.com/chaconinc/DbConnector
c75e92a..82d2ad3 stable -> stable
Counting objects: 2, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 266 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To https://github.com/chaconinc/MainProject
3d6d338..9a377d1 master -> master
Soos jy daar kan sien, het Git na die DbConnector module gegaan en dit gepush voor die hoofprojek gepush is.
As daardie submodule-push vir een of ander rede misluk, sal die hoofprojek-push ook misluk.
Jy kan hierdie gedrag as die verstelling maak deur git config push.recurseSubmodules on-demand te doen.
Samesmelting van Submoduleveranderings
As jy 'n submodule-verwysing gelyktydig met iemand anders verander, kan jy dalk in 'n paar probleme vasloop. Dit wil sê, as die submodule geskiedenisse uiteengegaan het (diverged) en aan uiteenlopende takke in 'n superprojek vasgelê is, kan dit 'n bietjie werk verg vir jou om reg te maak.
As een van die vasleggings 'n direkte voorouer van die ander is ('n fast-forward saamsmelting), sal Git eenvoudig die laaste vir die saamsmelting kies, so dit werk goed.
Git sal egter nie eers 'n triviale saamsmelting vir jou probeer nie. As die submodule-vasleggings uiteenloop en saamgesmelt moet word, sal jy iets kry wat soos volg lyk:
$ git pull
remote: Counting objects: 2, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 2 (delta 1), reused 2 (delta 1)
Unpacking objects: 100% (2/2), done.
From https://github.com/chaconinc/MainProject
9a377d1..eb974f8 master -> origin/master
Fetching submodule DbConnector
warning: Failed to merge submodule DbConnector (merge following commits not found)
Auto-merging DbConnector
CONFLICT (submodule): Merge conflict in DbConnector
Automatic merge failed; fix conflicts and then commit the result.
So basies wat hier gebeur het, is dat Git uitgevind het dat die twee takke punte in die submodule se geskiedenis aanteken wat uiteenlopend is en saamgesmelt moet word. Dit verduidelik dit as “merge following commits not found”, wat verwarrend is, maar ons sal oor 'n rukkie verduidelik hoekom dit so is.
Om die probleem op te los, moet jy uitvind in watter toestand die submodule behoort te wees.
Vreemd genoeg gee Git jou nie regtig veel inligting om te help nie, selfs nie die SHA-1’s van die vasleggings van albei kante van die geskiedenis nie.
Gelukkig is dit maklik om uit te vind.
As jy git diff uitvoer, kan jy die SHA-1’s kry van die vasleggings wat aangeteken is in beide takke wat jy probeer saamsmelt het.
$ git diff
diff --cc DbConnector
index eb41d76,c771610..0000000
--- a/DbConnector
+++ b/DbConnector
In hierdie geval is eb41d76 die vaslegging in ons submodule wat ons gehad het, en c771610 is die vaslegging wat stroomopwaarts (upstream) was.
As ons by ons submodulegids ingaan, behoort dit reeds op eb41d76 te wees, aangesien die samesmelting dit nie sou geraak het nie.
As dit om een of ander rede nie is nie, kan jy eenvoudig 'n tak skep en onttrek wat daarna verwys.
Wat belangrik is, is die SHA-1 van die vaslegging van die ander kant af. Dit is wat jy sal moet insmelt en oplos. Jy kan net die saamsmelting met die SHA-1 direk probeer, of jy kan 'n tak daarvoor skep en dan daardie een probeer insmelt. Ons beveel laasgenoemde aan, selfs net om 'n mooier samesmeltingsboodskap te maak.
So, ons sal na ons submodulegids gaan, 'n tak met die naam “try-merge” skep gebaseer op daardie tweede SHA-1 van git diff, en handmatig saamsmelt.
$ cd DbConnector
$ git rev-parse HEAD
eb41d764bccf88be77aced643c13a7fa86714135
$ git branch try-merge c771610
$ git merge try-merge
Auto-merging src/main.c
CONFLICT (content): Merge conflict in src/main.c
Recorded preimage for 'src/main.c'
Automatic merge failed; fix conflicts and then commit the result.
Ons het hier 'n werklike samesmeltingskonflik gekry, dus as ons dit oplos en vaslê, kan ons die hoofprojek bloot bywerk met die resultaat.
$ vim src/main.c (1)
$ git add src/main.c
$ git commit -am 'merged our changes'
Recorded resolution for 'src/main.c'.
[master 9fd905e] merged our changes
$ cd .. (2)
$ git diff (3)
diff --cc DbConnector
index eb41d76,c771610..0000000
--- a/DbConnector
+++ b/DbConnector
@@@ -1,1 -1,1 +1,1 @@@
- Subproject commit eb41d764bccf88be77aced643c13a7fa86714135
-Subproject commit c77161012afbbe1f58b5053316ead08f4b7e6d1d
++Subproject commit 9fd905e5d7f45a0d4cbc43d1ee550f16a30e825a
$ git add DbConnector (4)
$ git commit -m "Merge Tom's Changes" (5)
[master 10d2c60] Merge Tom's Changes
-
Eers los ons die konflik op.
-
Dan gaan ons terug na die hoofprojekgids.
-
Ons kan die SHA-1’s weer nagaan.
-
Los die konfliksituasie met die submodule-inskrywing op.
-
Lê ons saamsmelting vas.
Dit mag 'n bietjie verwarrend wees, maar dit is nie regtig te moeilik nie.
Interessant genoeg is daar 'n ander scenario wat Git hanteer. As daar 'n samesmeltingsvaslegging in die submodulegids is wat beide vasleggings in sy geskiedenis bevat, sal Git dit as 'n moontlike oplossing vir jou voorstel. Dit sien dat iemand iewers in die submoduleprojek takke saamgesmelt het wat hierdie twee vasleggings bevat, sodat jy miskien daardie een wil hê.
Dit is hoekom die foutboodskap vroeër was “merge following commits not found”, aangesien dit nie dit kon doen nie. Dit is verwarrend, want wie sou verwag het dat dit dit sou probeer doen?
As dit wel 'n enkele aanvaarbare samesmeltingsvaslegging vind, sal jy iets soos volg sien:
$ git merge origin/master
warning: Failed to merge submodule DbConnector (not fast-forward)
Found a possible merge resolution for the submodule:
9fd905e5d7f45a0d4cbc43d1ee550f16a30e825a: > merged our changes
If this is correct simply add it to the index for example
by using:
git update-index --cacheinfo 160000 9fd905e5d7f45a0d4cbc43d1ee550f16a30e825a "DbConnector"
which will accept this suggestion.
Auto-merging DbConnector
CONFLICT (submodule): Merge conflict in DbConnector
Automatic merge failed; fix conflicts and then commit the result.
Die voorgestelde opdrag wat Git verskaf, sal die indeks opdateer asof jy git add uitgevoer het (wat die konflik verwyder), en dan vaslê.
Jy moet dit waarskynlik egter nie doen nie.
Jy kan net so maklik na die submodulegids gaan, sien wat die verskil is, met fast-forward na hierdie vaslegging versnel, dit deeglik toets, en dit dan vaslê.
$ cd DbConnector/
$ git merge 9fd905e
Updating eb41d76..9fd905e
Fast-forward
$ cd ..
$ git add DbConnector
$ git commit -am 'Fast forward to a common submodule child'
Dit bereik dieselfde doel, maar op hierdie manier kan jy ten minste verifieer dat dit werk en het jy die kode in jou submodulegids wanneer jy klaar is.
Submodule Wenke
Daar is 'n paar dinge wat jy kan doen om werk met submodules 'n bietjie makliker te maak.
Submodule Foreach
Daar is 'n foreach submodule opdrag om enige willekeurige opdrag in elke submodule uit te voer.
Dit kan regtig baie nuttig wees as jy 'n aantal submodules in dieselfde projek het.
Byvoorbeeld, gestel ons wil 'n nuwe funksionaliteit begin of 'n foutsuiwering (bugfix) doen, en ons het werk aan die gang in verskeie submodules. Ons kan maklik al die werk in al ons submodules wegbêre (stash).
$ git submodule foreach 'git stash'
Entering 'CryptoLibrary'
No local changes to save
Entering 'DbConnector'
Saved working directory and index state WIP on stable: 82d2ad3 Merge from origin/stable
HEAD is now at 82d2ad3 Merge from origin/stable
Dan kan ons 'n nuwe tak skep en na dit in al ons submodules oorslaan.
$ git submodule foreach 'git checkout -b featureA'
Entering 'CryptoLibrary'
Switched to a new branch 'featureA'
Entering 'DbConnector'
Switched to a new branch 'featureA'
Jy verstaan die idee. Een regtig nuttige ding wat jy kan doen, is om 'n oulike verenigde verskil (unified diff) van wat verander het in jou hoofprojek en al jou subprojekte asook voor te berei.
$ git diff; git submodule foreach 'git diff'
Submodule DbConnector contains modified content
diff --git a/src/main.c b/src/main.c
index 210f1ae..1f0acdc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -245,6 +245,8 @@ static int handle_alias(int *argcp, const char ***argv)
commit_pager_choice();
+ url = url_decode(url_orig);
+
/* build alias_argv */
alias_argv = xmalloc(sizeof(*alias_argv) * (argc + 1));
alias_argv[0] = alias_string + 1;
Entering 'DbConnector'
diff --git a/src/db.c b/src/db.c
index 1aaefb6..5297645 100644
--- a/src/db.c
+++ b/src/db.c
@@ -93,6 +93,11 @@ char *url_decode_mem(const char *url, int len)
return url_decode_internal(&url, len, NULL, &out, 0);
}
+char *url_decode(const char *url)
+{
+ return url_decode_mem(url, strlen(url));
+}
+
char *url_decode_parameter_name(const char **query)
{
struct strbuf out = STRBUF_INIT;
Hier kan ons sien dat ons 'n funksie in 'n submodule definieer en dit in die hoofprojek oproep. Dit is natuurlik 'n vereenvoudigde voorbeeld, maar hopelik gee dit jou 'n idee van hoe dit nuttig mag wees.
Nuttige Aliassen
Jy mag dalk wil oorweeg om sekere aliassen op te stel vir sommige van hierdie opdragte aangesien hulle redelik lank kan wees en jy nie konfigurasieopsies vir meeste van hulle kan stel om as verstekwaardes te dien nie. Ons het gehandel oor die opstel van Git-aliassen in Git-aliasse, maar hier is 'n voorbeeld van wat jy dalk wil opstel as jy van plan is om baie met submodules in Git te werk.
$ git config alias.sdiff '!'"git diff && git submodule foreach 'git diff'"
$ git config alias.spush 'push --recurse-submodules=on-demand'
$ git config alias.supdate 'submodule update --remote --merge'
Op hierdie manier kan jy net git supdate uitvoer wanneer jy jou submodules wil opdateer, of git spush om te push terwyl daar vir afhanklikhede van submodules gekontroleer word.
Probleme met Submodules
Die gebruik van submodules is egter nie sonder hikke nie.
Verandering van Takke
Byvoorbeeld, die verandering van takke met submodules daarin kan ook moeilik wees met Git-weergawes ouer as Git 2.13. As jy 'n nuwe tak skep, 'n submodule byvoeg, en dan terugverander na 'n tak sonder daardie submodule, bly jou submodulegids steeds daar as 'n ongeregistreerde (untracked) gids:
$ git --version
git version 2.12.2
$ git checkout -b add-crypto
Switched to a new branch 'add-crypto'
$ git submodule add https://github.com/chaconinc/CryptoLibrary
Cloning into 'CryptoLibrary'...
...
$ git commit -am 'Add crypto library'
[add-crypto 4445836] Add crypto library
2 files changed, 4 insertions(+)
create mode 160000 CryptoLibrary
$ git checkout master
warning: unable to rmdir CryptoLibrary: Directory not empty
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
CryptoLibrary/
nothing added to commit but untracked files present (use "git add" to track)
Dit is nie moeilik om die gids te verwyder nie, maar dit kan 'n bietjie verwarrend wees om dit daar in te hê.
As jy dit wel verwyder en dan terugwissel na die tak wat daardie submodule het, sal jy submodule update --init moet laat loop om dit te herbevolk.
$ git clean -ffdx
Removing CryptoLibrary/
$ git checkout add-crypto
Switched to branch 'add-crypto'
$ ls CryptoLibrary/
$ git submodule update --init
Submodule path 'CryptoLibrary': checked out 'b8dda6aa182ea4464f3f3264b11e0268545172af'
$ ls CryptoLibrary/
Makefile includes scripts src
Weereens, nie werklik moeilik nie, maar dit kan 'n bietjie verwarrend wees.
Nuwer weergawes van Git (Git >= 2.13) vereenvoudig alles deur die --recurse-submodules vlag by die git checkout opdrag by te voeg, wat sorg dra om die submodules in die regte toestand te plaas vir die tak waarna ons oorskakel.
$ git --version
git version 2.13.3
$ git checkout -b add-crypto
Switched to a new branch 'add-crypto'
$ git submodule add https://github.com/chaconinc/CryptoLibrary
Cloning into 'CryptoLibrary'...
...
$ git commit -am 'Add crypto library'
[add-crypto 4445836] Add crypto library
2 files changed, 4 insertions(+)
create mode 160000 CryptoLibrary
$ git checkout --recurse-submodules master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
Die gebruik van die --recurse-submodules vlag met git checkout kan ook nuttig wees as jy aan verskeie takke werk binne die superprojek, waar elkeen van jou submodules na verskillende vasleggings wys.
Inderdaad, as jy oorskakel tussen takke wat na die submodule in verskillende vasleggings wys, sal die submodule in git status as “modified” vertoon word, asook “new commits” aandui.
Dit is omdat die submodule se toestand by verstek nie oorgedra word by die oorskakeling na ander takke nie.
Dit kan baie verwarrend wees, so dit is 'n goeie idee om altyd git checkout --recurse-submodules te gebruik as jou projek submodules het.
By ouer weergawes van Git, wat nie die --recurse-submodules vlag het nie, kan jy na die "checkout", git submodule update --init --recursive gebruik om die submodules weer reg in hul korrekte toestand te plaas.
Gelukkig kan jy vir Git (>=2.14) sê om altyd die --recurse-submodules vlag te gebruik deur die konfigurasie-opsie submodule.recurse in te stel: git config submodule.recurse true.
Soos hierbo genoem, sal dit Git ook in submodules in laat afdaal vir elke opdrag wat 'n --recurse-submodules opsie het (behalwe git clone).
Skakeling van subgidse na submodules
Die ander hoofstrik waarin mense trap behels die skakeling van subgidse na submodules.
As jy lêers in jou projek genaspoor het en jy hulle nou in 'n submodule wil plaas, moet jy versigtig wees anders gaan Git met jou ontevrede wees.
Neem aan dat jy lêers in 'n subgids in jou projek het, en jy wil dit na 'n submodule verander.
As jy die subgids verwyder en dan submodule add uitvoer, raas Git met jou:
$ rm -Rf CryptoLibrary/
$ git submodule add https://github.com/chaconinc/CryptoLibrary
'CryptoLibrary' already exists in the index
Jy moet eers die voorbereiding (staging) van die CryptoLibrary subgids ophef.
Dan kan jy die submodule byvoeg:
$ git rm -r CryptoLibrary
$ git submodule add https://github.com/chaconinc/CryptoLibrary
Cloning into 'CryptoLibrary'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Gestel nou jy het dit in 'n tak gedoen. As jy poog om terug te skakel na 'n tak waar daardie lêers steeds in die werklike boom (tree) is eerder as 'n submodule, sal jy hierdie fout ontvang:
$ git checkout master
error: The following untracked working tree files would be overwritten by checkout:
CryptoLibrary/Makefile
CryptoLibrary/includes/crypto.h
...
Please move or remove them before you can switch branches.
Aborting
Jy kan dit forseer om oor te slaan na daardie tak toe met checkout -f, maar pasop dat jy nie nog-ongestoorde werk daarbinne het nie aangesien dit oorgeskryf kan word met hierdie opdrag.
$ git checkout -f master
warning: unable to rmdir CryptoLibrary: Directory not empty
Switched to branch 'master'
Dan, as jy weer teruggaan, kry jy om die een of ander rede 'n leë CryptoLibrary subgids en git submodule update herstel dit dalk ook nie.
Jy mag dalk self binne die betrokke submodulegids moet inbeweeg en git checkout . daar uitvoer om al jou lêers weer terug te kan verkry.
Jy kan dalk dink om eerder dit deur 'n submodule foreach draaiboekie (script) uit te voer wat dit weereens vir verskeie submodules self sal verrig.
Dit is belangrik om op te merk dat in deesdae se submodules, hulle al hul Git data stoor in die boonste projek se .git gids, so in teendeel as met baie ou weergawes van Git sal jy geen vasleggings of takke van 'n submodule kan kwytraak by die verwydering van daardie submodulegids nie.
Submodules met hierdie nutsgoed is nogal 'n vereenvoudigde en doeltreffende oplossing by die saamomgewing om in 'n verskeidenheid afsonderlike verhoudings of interafhanklike maar afsonderlike projekte terselfdertyd mee te werk.