-
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.6 Git Tools - Herskryf van Geskiedenis (Rewriting History)
Herskryf van Geskiedenis (Rewriting History)
Baie keer, wanneer jy met Git werk, wil jy dalk jou plaaslike vasleggingsgeskiedenis (commit history) hersien.
Een van die wonderlike dinge van Git is dat dit jou toelaat om besluite op die laaste moontlike oomblik te neem.
Jy kan besluit watter lêers in watter vasleggings gaan net voor jy vaslê met behulp van die voorbereidingsarea (staging area), jy kan besluit dat jy nog nie aan iets wou werk nie met git stash, en jy kan vasleggings wat reeds plaasgevind het herskryf sodat dit lyk of hulle op 'n ander manier gebeur het.
Dit kan insluit die verandering van die volgorde van die vasleggings, die verandering van boodskappe of wysiging van lêers in 'n vaslegging, die saampers (squashing) of opsplitsing van vasleggings, of die algehele verwydering van vasleggings — alles voordat jy jou werk met ander deel.
In hierdie afdeling sal jy sien hoe om hierdie take uit te voer sodat jy jou vasleggingsgeskiedenis kan laat lyk soos jy wil voordat jy dit met ander deel.
|
Note
|
Moenie jou werk push totdat jy daarmee tevrede is nie
Een van die kardinale reëls van Git is dat, aangesien soveel werk plaaslik binne jou kloon is, jy 'n groot mate van vryheid het om jou geskiedenis plaaslik te herskryf. Sodra jy egter jou werk push, is dit 'n heeltemal ander storie, en jy moet gepushte werk as finaal beskou tensy jy goeie rede het om dit te verander. Kortom, jy moet vermy om jou werk te push totdat jy daarmee tevrede is en gereed is om dit met die res van die wêreld te deel. |
Verandering van die Laaste Vaslegging (Changing the Last Commit)
Die verandering van jou mees onlangse vaslegging is waarskynlik die mees algemene herskrywing van geskiedenis wat jy sal doen. Jy sal dikwels twee basiese dinge aan jou laaste vaslegging wil doen: bloot die vasleggingsboodskap verander, of die werklike inhoud van die vaslegging verander deur lêers by te voeg, te verwyder en te wysig.
As jy bloot jou laaste vasleggingsboodskap wil verander, is dit maklik:
$ git commit --amend
Die opdrag hierbo laai die vorige vasleggingsboodskap in 'n redigeerdersessie in, waar jy veranderings aan die boodskap kan maak, daardie veranderings kan stoor en kan afsluit. Wanneer jy die redigeerder stoor en toemaak, skryf die redigeerder 'n nuwe vaslegging wat daardie opgedateerde vasleggingsboodskap bevat en maak dit jou nuwe laaste vaslegging.
As jy, aan die ander kant, die werklike inhoud van jou laaste vaslegging wil verander, werk die proses basies op dieselfde manier — maak eers die veranderings wat jy dink jy vergeet het, berei daardie veranderings voor (stage), en die daaropvolgende git commit --amend vervang daardie laaste vaslegging met jou nuwe, verbeterde vaslegging.
Jy moet versigtig wees met hierdie tegniek, want amendering verander die SHA-1 van die vaslegging. Dit is soos 'n baie klein herbasering (rebase) — moenie jou laaste vaslegging amendeer as jy dit reeds gepush het nie.
|
Tip
|
'n Geamendeerde vaslegging benodig dalk (of dalk nie) 'n geamendeerde vasleggingsboodskap
Wanneer jy 'n vaslegging amendeer, het jy die geleentheid om beide die vasleggingsboodskap en die inhoud van die vaslegging te verander. As jy die inhoud van die vaslegging wesenlik amendeer, moet jy amper sekerlik die vasleggingsboodskap opdateer om daardie geamendeerde inhoud te weerspieël. Aan die ander kant, as jou amendemente so triviaal is (soos die regmaak van 'n simpel tikfout of die byvoeging van 'n lêer wat jy vergeet het om voor te berei) dat die vroeëre vasleggingsboodskap net reg is, kan jy eenvoudig die veranderings maak, dit voorberei, en die onnodige redigeerdersessie heeltemal vermy met:
|
Verandering van Veelvuldige Vasleggingsboodskappe (Changing Multiple Commit Messages)
Om 'n vaslegging te verander wat verder terug in jou geskiedenis is, moet jy na meer komplekse gereedskap beweeg.
Git het nie 'n wysig-geskiedenis-instrument nie, maar jy kan die rebase-instrument gebruik om 'n reeks vasleggings te rebase op die HEAD waarop hulle oorspronklik gebaseer was in plaas daarvan om dit na 'n ander een te skuif.
Met die interaktiewe rebase-instrument kan jy dan na elke vaslegging wat jy wil verander stop en die boodskap verander, lêers byvoeg, of doen wat jy wil.
Jy kan rebase interaktief uitvoer deur die -i opsie by git rebase te voeg.
Jy moet aandui hoe ver terug jy vasleggings wil herskryf deur vir die opdrag te sê op watter vaslegging dit moet rebase.
Byvoorbeeld, as jy die laaste drie vasleggingsboodskappe wil verander, of enige van die vasleggingsboodskappe in daardie groep, verskaf jy as 'n argument aan git rebase -i die ouer van die laaste vaslegging wat jy wil redigeer, wat HEAD~2^ of HEAD~3 is.
Dit mag makliker wees om die ~3 te onthou, want jy probeer die laaste drie vasleggings redigeer, maar hou in gedagte dat jy eintlik vier vasleggings gelede aandui, die ouer van die laaste vaslegging wat jy wil redigeer:
$ git rebase -i HEAD~3
Onthou weereens dat hierdie 'n rebase-opdrag is — elke vaslegging in die reeks HEAD~3..HEAD met 'n veranderde boodskap en al sy afstammelinge sal herskryf word.
Moenie enige vaslegging insluit wat jy reeds na 'n sentrale bediener gepush het nie — as jy dit doen, sal dit ander ontwikkelaars verwar deur 'n alternatiewe weergawe van dieselfde verandering te verskaf.
Die uitvoering van hierdie opdrag gee jou 'n lys van vasleggings in jou teksredigeerder wat so iets soos dit lyk:
pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
Dit is belangrik om op te let dat hierdie vasleggings gelys word in die teenoorgestelde volgorde as wat jy hulle normaalweg sien wanneer jy die log opdrag gebruik.
As jy 'n log uitvoer, sien jy so iets:
$ git log --pretty=format:"%h %s" HEAD~3..HEAD
a5f4a0d Add cat-file
310154e Update README formatting and add blame
f7f3f6d Change my name a bit
Let op die omgekeerde volgorde.
Die interaktiewe rebase gee jou 'n skrip wat dit gaan uitvoer.
Dit sal begin by die vaslegging wat jy op die opdragreël spesifiseer (HEAD~3) en die veranderings wat in elkeen van hierdie vasleggings ingestel is, van bo na onder herspeel.
Dit lys die oudste boaan, eerder as die nuutste, want dit is die eerste een wat dit sal herspeel.
Jy moet die skrip redigeer sodat dit stop by die vaslegging wat jy wil redigeer. Om dit te doen, verander die woord “pick” na die woord “edit” vir elkeen van die vasleggings waarby jy wil hê die skrip moet stop. Byvoorbeeld, om slegs die derde vasleggingsboodskap te verander, verander jy die lêer om so te lyk:
edit f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
Wanneer jy die redigeerder stoor en verlaat, spoel Git jou terug na die laaste vaslegging in daardie lys en laat jou op die opdragreël met die volgende boodskap:
$ git rebase -i HEAD~3
Stopped at f7f3f6d... Change my name a bit
You can amend the commit now, with
git commit --amend
Once you're satisfied with your changes, run
git rebase --continue
Hierdie instruksies vertel jou presies wat om te doen. Tik:
$ git commit --amend
Verander die vasleggingsboodskap en verlaat die redigeerder. Voer dan die volgende uit:
$ git rebase --continue
Hierdie opdrag sal die ander twee vasleggings outomaties toepas, en dan is jy klaar.
As jy pick na edit verander op meer reëls, kan jy hierdie stappe herhaal vir elke vaslegging wat jy na edit verander.
Elke keer sal Git stop, jou toelaat om die vaslegging te amendeer, en voortgaan wanneer jy klaar is.
Herordening van Vasleggings (Reordering Commits)
Jy kan ook interaktiewe rebases gebruik om vasleggings te herorden of heeltemal te verwyder. As jy die “Add cat-file” vaslegging wil verwyder en die volgorde waarin die ander twee vasleggings ingestel is wil verander, kan jy die rebase-skrip hiervan verander:
pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
na dit toe:
pick 310154e Update README formatting and add blame
pick f7f3f6d Change my name a bit
Wanneer jy die redigeerder stoor en verlaat, spoel Git jou tak terug na die ouer van hierdie vasleggings, pas 310154e toe en dan f7f3f6d, en stop dan.
Jy het effektief die volgorde van daardie vasleggings verander en die “Add cat-file” vaslegging heeltemal verwyder.
Saampersing van Vasleggings (Squashing Commits)
Dit is ook moontlik om 'n reeks vasleggings te neem en hulle te saampers (squash) tot 'n enkele vaslegging met die interaktiewe rebasing-instrument. Die skrip plaas nuttige instruksies in die rebase-boodskap:
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
As jy in plaas van “pick” of “edit”, “squash” spesifiseer, pas Git beide daardie verandering en die verandering direk daarvoor toe en laat jou die vasleggingsboodskappe saamsmelt. So, as jy 'n enkele vaslegging van hierdie drie vasleggings wil maak, laat jy die skrip so lyk:
pick f7f3f6d Change my name a bit
squash 310154e Update README formatting and add blame
squash a5f4a0d Add cat-file
Wanneer jy die redigeerder stoor en verlaat, pas Git al drie veranderings toe en plaas jou dan terug in die redigeerder om die drie vasleggingsboodskappe saam te smelt:
# This is a combination of 3 commits.
# The first commit's message is:
Change my name a bit
# This is the 2nd commit message:
Update README formatting and add blame
# This is the 3rd commit message:
Add cat-file
Wanneer jy dit stoor, het jy 'n enkele vaslegging wat die veranderings van al drie vorige vasleggings instel.
Opsplitsing van 'n Vaslegging (Splitting a Commit)
Die opsplitsing van 'n vaslegging maak 'n vaslegging ongedaan en berei dit dan gedeeltelik voor (stages) en lê dit vas soveel keer as wat jy met nuwe vasleggings wil eindig.
Byvoorbeeld, veronderstel jy wil die middelste vaslegging van jou drie vasleggings opsplits.
In plaas van “Update README formatting and add blame”, wil jy dit opdeel in twee vasleggings: “Update README formatting” vir die eerste, en “Add blame” vir die tweede.
Jy kan dit doen in die rebase -i skrip deur die instruksie op die vaslegging wat jy wil opsplits na “edit” te verander:
pick f7f3f6d Change my name a bit
edit 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
Dan, wanneer die skrip jou na die opdragreël terugbring, stel jy (reset) daardie vaslegging terug, neem die veranderings wat teruggestel is, en skep veelvuldige vasleggings daaruit.
Wanneer jy die redigeerder stoor en verlaat, spoel Git terug na die ouer van die eerste vaslegging in jou lys, pas die eerste vaslegging toe (f7f3f6d), pas die tweede toe (310154e), en plaas jou op die konsole.
Daar kan jy 'n gemengde reset (mixed reset) van daardie vaslegging doen met git reset HEAD^, wat daardie vaslegging effektief ongedaan maak en die gewysigde lêers onvoorbereid (unstaged) laat.
Nou kan jy lêers voorberei (stage) en vaslê totdat jy verskeie vasleggings het, en git rebase --continue uitvoer wanneer jy klaar is:
$ git reset HEAD^
$ git add README
$ git commit -m 'Update README formatting'
$ git add lib/simplegit.rb
$ git commit -m 'Add blame'
$ git rebase --continue
Git pas die laaste vaslegging (a5f4a0d) in die skrip toe, en jou geskiedenis lyk soos volg:
$ git log -4 --pretty=format:"%h %s"
1c002dd Add cat-file
9b29157 Add blame
35cfb2b Update README formatting
f7f3f6d Change my name a bit
Dit verander die SHA-1’s van die drie mees onlangse vasleggings in jou lys, so maak seker dat geen veranderde vaslegging in daardie lys verskyn wat jy reeds na 'n gedeelde bewaarplek gepush het nie.
Let op dat die laaste vaslegging (f7f3f6d) in die lys onveranderd is.
Ten spyte daarvan dat hierdie vaslegging in die skrip gewys word, omdat dit as “pick” gemerk is en voor enige rebase-veranderings toegepas is, laat Git die vaslegging onveranderd.
Uitvee van 'n Vaslegging (Deleting a commit)
As jy ontslae wil raak van 'n vaslegging, kan jy dit uitvee met behulp van die rebase -i skrip.
In die lys van vasleggings, plaas die woord “drop” voor die vaslegging wat jy wil uitvee (of vee net daardie reël uit die rebase-skrip uit):
pick 461cb2a This commit is OK
drop 5aecc10 This commit is broken
As gevolg van die manier waarop Git vasleggingsobjekte bou, sal die uitvee of wysiging van 'n vaslegging veroorsaak dat al die vasleggings wat daarop volg, herskryf word. Hoe verder terug in jou bewaarplek se geskiedenis jy gaan, hoe meer vasleggings sal herskep moet word. Dit kan baie saamsmeltingskonflikte veroorsaak as jy baie vasleggings later in die ry het wat afhanklik is van die een wat jy so pas uitgevee het.
As jy halfpad deur so 'n rebase kom en besluit dit is nie 'n goeie idee nie, kan jy altyd stop.
Tik git rebase --abort, en jou bewaarplek sal teruggestel word na die toestand waarin dit was voor jy die rebase begin het.
As jy 'n rebase voltooi en besluit dis nie wat jy wil hê nie, kan jy git reflog gebruik om 'n vroeëre weergawe van jou tak te herwin.
Sien Dataherwinning vir meer inligting oor die reflog opdrag.
|
Note
|
Drew DeVault het 'n praktiese handleiding met oefeninge gemaak om te leer hoe om |
Die Kernopsie (The Nuclear Option): filter-branch
Daar is nog 'n geskiedenis-herskrywingsopsie wat jy kan gebruik as jy 'n groter aantal vasleggings op een of ander skripbare manier moet herskryf — byvoorbeeld, die globale verandering van jou e-posadres of die verwydering van 'n lêer uit elke vaslegging.
Die opdrag is filter-branch, en dit kan groot dele van jou geskiedenis herskryf, so jy moet dit waarskynlik nie gebruik nie, tensy jou projek nog nie publiek is nie en ander mense nog nie werk gebaseer het op die vasleggings wat jy op die punt is om te herskryf nie.
Dit kan egter baie nuttig wees.
Jy sal 'n paar van die algemene gebruike leer sodat jy 'n idee kan kry van sommige van die dinge waartoe dit in staat is.
|
Caution
|
|
Verwydering van 'n Lêer uit Elke Vaslegging (Removing a File from Every Commit)
Dit gebeur redelik algemeen.
Iemand lê per ongeluk 'n groot binêre lêer vas met 'n onnadenkende git add ., en jy wil dit oral verwyder.
Miskien het jy per ongeluk 'n lêer vasgelê wat 'n wagwoord bevat, en jy wil jou projek oopbron maak.
filter-branch is die instrument wat jy waarskynlik wil gebruik om jou hele geskiedenis skoon te skrop.
Om 'n lêer genaamd passwords.txt uit jou hele geskiedenis te verwyder, kan jy die --tree-filter opsie aan filter-branch gee:
$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
Ref 'refs/heads/master' was rewritten
Die --tree-filter opsie voer die gespesifiseerde opdrag uit na elke uittrekking (checkout) van die projek en lê dan die resultate weer vas (recommits).
In hierdie geval verwyder jy 'n lêer genaamd passwords.txt van elke momentopname, of dit bestaan of nie.
As jy alle per abuis vasgelegde redigeerder-rugsteunlêers (editor backup files) wil verwyder, kan jy iets soos git filter-branch --tree-filter 'rm -f *~' HEAD uitvoer.
Jy sal in staat wees om te kyk hoe Git bome en vasleggings herskryf en dan die takwyser (branch pointer) aan die einde verskuif.
Dit is oor die algemeen 'n goeie idee om dit in 'n toetstak te doen en dan jou master tak hard terug te stel (hard-reset) nadat jy vasgestel het dat die uitkoms dit is wat jy werklik wil hê.
Om filter-branch op al jou takke uit te voer, kan jy --all na die opdrag aangee.
Maak van 'n Subgids die Nuwe Wortel (Making a Subdirectory the New Root)
Sê nou jy het 'n invoer vanaf 'n ander bronbeheerstelsel gedoen en het subgidse wat geen sin maak nie (trunk, tags, ensovoorts).
As jy die trunk subgids die nuwe projekwortel vir elke vaslegging wil maak, kan filter-branch jou help om dit ook te doen:
$ git filter-branch --subdirectory-filter trunk HEAD
Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
Ref 'refs/heads/master' was rewritten
Nou is jou nuwe projekwortel dit wat elke keer in die trunk subgids was.
Git sal ook outomaties vasleggings verwyder wat nie die subgids beïnvloed het nie.
Globale Verandering van E-posadresse (Changing Email Addresses Globally)
Nog 'n algemene geval is dat jy vergeet het om git config uit te voer om jou naam en e-posadres te stel voordat jy begin werk het, of dalk wil jy 'n projek by die werk oopbron maak en al jou werks-e-posadresse na jou persoonlike adres verander.
In elk geval kan jy e-posadresse in veelvuldige vasleggings as 'n bondel met filter-branch verander.
Jy moet versigtig wees om slegs die e-posadresse te verander wat joune is, so jy gebruik --commit-filter:
$ git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
then
GIT_AUTHOR_NAME="Scott Chacon";
GIT_AUTHOR_EMAIL="schacon@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
Dit gaan deur en herskryf elke vaslegging om jou nuwe adres te hê. Omdat vasleggings die SHA-1 waardes van hul ouers bevat, verander hierdie opdrag elke vaslegging SHA-1 in jou geskiedenis, nie net dié wat die ooreenstemmende e-posadres het nie.