From 3033b7b2a3fbe84885ee82e38cd7f40ef9b0e053 Mon Sep 17 00:00:00 2001 From: Cor Date: Tue, 11 Feb 2014 11:57:37 +0100 Subject: [PATCH] [nl] Chapter09 Retranslate and resequence Retranslated the chapter and resequenced the sentences so they sound less Dunglish. --- nl/09-git-internals/01-chapter9.markdown | 284 +++++++++++------------ 1 file changed, 142 insertions(+), 142 deletions(-) diff --git a/nl/09-git-internals/01-chapter9.markdown b/nl/09-git-internals/01-chapter9.markdown index c73cbd7c1..7727ea3cf 100644 --- a/nl/09-git-internals/01-chapter9.markdown +++ b/nl/09-git-internals/01-chapter9.markdown @@ -1,20 +1,20 @@ # Het binnenwerk van Git # -Je zult misschien naar dit hoofdstuk gesprongen zijn vanuit een vorig hoofdstuk, of je zult hier gekomen zijn nadat je de rest van het boek gelezen hebt – in ieder geval, zal hier het binnenwerk en implementatie van Git behandeld worden. Ik heb gemerkt dat het leren van deze informatie van fundamenteel belang is om te begrijpen hoe bruikbaar en krachtig Git is, maar anderen hebben daar tegenin gebracht dat het erg verwarrend en onnodig complex kan zijn voor beginners. Daarom heb ik deze beschrijving het laatste hoofdstuk gemaakt in het boek, zodat je het vroeg of later kunt lezen in je leerproces. Ik laat het aan jou over om dat te beslissen. +Je zult misschien naar dit hoofdstuk gesprongen zijn vanuit een eerdere hoofdstuk, of je zult hier gekomen zijn nadat je de rest van het boek gelezen hebt; hoe dan ook zal hier het binnenwerk en implementatie van Git behandeld worden. Ik heb gemerkt dat het leren van deze informatie van fundamenteel belang is om te begrijpen hoe bruikbaar en krachtig Git is, maar anderen hebben daar tegenin gebracht dat het erg verwarrend en onnodig complex kan zijn voor beginners. Daarom heb ik deze beschrijving het laatste hoofdstuk gemaakt in het boek, zodat je het vroeg of later in je leerproces kunt lezen. Ik laat het aan jou over om dat te beslissen. -Laten we beginnen, nu je hier bent. Als eerste, mocht het nog niet duidelijk zijn, is Git eigenlijk een inhouds-toegankelijk bestandssysteem met een gebruikersinterface voor versiebeheer er bovenop geschreven. Je zult over een poosje meer leren over wat dit betekent. +Nu je hier bent, laten we beginnen. Ten eerste, mocht het nog niet duidelijk zijn, is Git eigenlijk een inhouds-adresseerbaar bestandssysteem met een gebruikersinterface voor versiebeheer er bovenop geschreven. Je zult over een poosje meer leren over wat dit betekent. -In de eerste dagen van Git (het merendeel pre 1.5), wat de gebruikersinterface veel complexer, omdat het de nadruk legde op dit bestandssysteem in plaats van op een gepolijst VCS. De laatste paar jaren is de interface verfijnd totdat het zo netjes en eenvoudig te gebruiken is als ieder systeem dat er bestaat; maar vaak blijft het stereotype hangen over de vroegere Gitinterface, die complex was en moeilijk te leren. +In de eerste dagen van Git (het merendeel pre 1.5), was de gebruikersinterface veel complexer, omdat het de nadruk legde op dit bestandssysteem in plaats van op een gepolijst VCS. De laatste paar jaren is de interface verfijnd totdat het zo netjes en eenvoudig te gebruiken is als een willekeurig ander systeem; maar vaak blijft het stereotype hangen van de vroegere Gitinterface die complex was en moeilijk te leren. -Deze laag met het inhouds-toegankelijke bestandssysteem is ongelofelijk gaaf, dus dat behandel ik dat als eerste dit hoofdstuk; daarna leer je over de transportmechanismen en het onderhouden van je repository's, iets waar je uiteindelijk te maken mee kunt krijgen. +Deze laag met het inhouds-toegankelijke bestandssysteem is ongelofelijk gaaf, dus dat behandel ik dat als eerste dit hoofdstuk; daarna leer je over de transportmechanismen en het onderhouden van je repository's, iets waar je uiteindelijk mee te maken kunt krijgen. -## Sanitaire inrichtingen en porselein ## +## Sanitaire voorzieningen en porselein ## -Dit boek behandeld Git met ongeveer 30 werkwoorden zoals `checkout`, `branch`, `remote` enzovoorts. Maar omdat Git in eerste instantie een toolkit voor een VCS was, in plaats van een volledig gebruiksvriendelijk VCS, heeft het een berg werkwoorden die laag-bij-de-gronds werk doen en ontworpen waren om samengevoegd te worden zoals in UNIX gebruikelijk is, of vanuit scripts aangeroepen te worden. Naar deze commando's wordt over het algemeen als "plumbing" (sanitaire voorzieningen) commando's verwezen, en de meer gebruiksvriendelijke commando's worden "porcelain" (porselein) commando's genoemd. +In dit boek wordt Git met ongeveer 30 werkwoorden zoals `checkout`, `branch`, `remote` enzovoorts behandeld. Maar omdat Git in eerste instantie een toolkit voor een VCS was, in plaats van een volledig gebruiksvriendelijk VCS, heeft het een berg werkwoorden die laag-bij-de-gronds werk doen en ontworpen waren om gebruikt te worden zoals in UNIX gebruikelijk is, of vanuit scripts aangeroepen te worden. Naar deze commando's wordt over het algemeen als "plumbing" (sanitaire voorzieningen) commando's gerefereerd, en de meer gebruiksvriendelijke commando's worden "porcelain" (porselein) commando's genoemd. -De eerste acht hoofdstukken van het boek behandelen bijna alleen porseleincommando's. Maar in dit hoofdstuk zul je het meest op het laagste niveau van de sanitaire voorzieningen om te gaan. Zij geven je toegang tot de diepste delen van Git, en demonstreren hoe en waarom Git doet wat het doet. Deze commando's zijn niet bedoeld voor normaal gebruik op de commandoregel, maar meer om als bouwstenen voor nieuwe tools en scripts gebruikt te worden. +De eerste acht hoofdstukken van het boek behandelen bijna alleen porselein commando's. Maar in dit hoofdstuk zul je het meest op het laagste niveau van de plumbing commando's om te gaan. Zij geven je toegang tot het binnenwerk van Git, en laten zien hoe en waarom Git doet wat het doet. Deze commando's zijn niet bedoeld voor normaal gebruik op de commandoregel, maar meer om als bouwstenen voor nieuwe tools en scripts gebruikt te worden. -Als je `git init` uitvoert in een nieuwe of bestaande map, zal Git de map `.git` aanmaken, wat de plek is waar Git bijna alles opslaat en manipuleert. Als je een backup of kopie van je repository wilt maken, dan hoef je alleen maar die map te kopiëren, en je hebt bijna alles wat je nodig hebt. Dit hele hoofdstuk gaat in essentie over de inhoud van deze map. Hier zie je hoe het eruit ziet: +Als je `git init` uitvoert in een nieuwe of bestaande directory, zal Git de directory `.git` aanmaken, wat de plek is waar bijna alles is wordt bewaard wat Git opslaat en manipuleert. Als je een backup of kopie van je repository wilt maken, dan hoef je alleen maar die directory te kopiëren, en je hebt bijna alles wat je nodig hebt. Dit hele hoofdstuk gaat in essentie over de inhoud van deze directory. Hier zie je hoe het eruit ziet: $ ls HEAD @@ -27,14 +27,14 @@ Als je `git init` uitvoert in een nieuwe of bestaande map, zal Git de map `.git` objects/ refs/ -Je kunt een paar andere bestanden zien, maar dit is een verse `git init` repository – dit is wat je standaard ziet. De `branches` map wordt niet gebruikt door nieuwere Git versies, en het `description` bestand wordt alleen gebruikt door het programma GitWeb, dus je hoeft je daar niet druk over te maken. Het bestand `config` bevat je project-specifieke configuratieopties, en de `info` map bevat een bestand met bestandsnaampatronen die je niet wilt volgen, maar ook niet wilt opnemen in een .gitignore bestand. De map `hooks` bevat scripts die aan bepaalde acties zijn “gehaakt” van gebruikers- en serverkant, die in detail beschreven zijn in Hoofdstuk 6. +Je kunt een paar andere bestanden zien, maar dit is een verse `git init` repository; dit is wat je standaard ziet. De `branches` directory wordt niet gebruikt door nieuwere Git versies, en het `description` bestand wordt alleen gebruikt door het programma GitWeb, dus je hoeft je daar geen zorgen over te maken. Het bestand `config` bevat je project-specifieke configuratieopties, en de `info` directory bevat een bestand met bestandsnaampatronen die je niet wilt volgen, maar niet wilt opnemen in een .gitignore bestand. De directory `hooks` bevat scripts die aan bepaalde acties zijn “gehaakt” aan client- en serverkant, die in detail beschreven zijn in Hoofdstuk 7. -Dit laat vier belangrijke vermeldingen over: de bestanden `HEAD` en `index`, en de mappen `objects` en `refs`. Dit zijn de kernbestandsdelen van Git. De map `objects` bewaart alle inhoud van je databank, de map `refs` bevat verwijzingen (branches) naar commitobjecten in die databank, het bestand `HEAD` wijst naar de branch die je op dit moment uitgechecked hebt, en het bestand `index` is waar Git de informatie van je wachtrij opslaat. Je gaat nu in detail naar elk van deze secties kijken om te zien hoe Git werkt. +Dit laat vier belangrijke vermeldingen over: de bestanden `HEAD` en `index`, en de directories `objects` en `refs`. Dit zijn de kernbestandsdelen van Git. De directory `objects` bevat alle inhoud van je databank, de directory `refs` bevat verwijzingen naar commitobjecten (branches) in die databank, het bestand `HEAD` wijst naar de branch die je op dit moment uitgechecked hebt, en het bestand `index` is waar Git de informatie van je wachtrij (staging area) opslaat. Je gaat nu in detail naar elk van deze onderdelen kijken om te zien hoe Git werkt. ## Git objecten ## -Git is een inhouds-adresseerbaar bestandssysteem. Mooi. Wat betekend dat? -Het betekend dat in de kern van Git een eenvoudige sleutel-waarde gegevens opslag zit. Je kunt er ieder soort inhoud in stoppen, en het zal je een sleutel geven die je kunt gebruiken om de inhoud op ieder moment terug te krijgen. Om te demonstreren, kun je het sanitaire voorzieningen commando `hash-object` gebruiken, die wat gegevens aanneemt, het in je `.git` map opslaat, en je de sleutel teruggeeft waarmee de gegevens zijn opgeslagen. Als eerste initialiseer je een nieuw Git repository en verifieer je dat er niets in de `objects` map staat: +Git is een inhouds-adresseerbaar bestandssysteem. Mooi. Wat betekent dat? +Het betekent dat in de kern van Git een eenvoudige sleutel-waarde gegevensopslag zit. Je kunt er elk soort inhoud in stoppen, en het zal je een sleutel geven die je kunt gebruiken om de inhoud op ieder moment terug te krijgen. Om te demonstreren kan je het plumbing commando `hash-object` gebruiken die wat gegevens aanneemt, het in je `.git` directory opslaat, en je de sleutel teruggeeft waarmee de gegevens zijn opgeslagen. Als eerste initialiseer je een nieuw Git repository en verifieer je dat er niets in de `objects` directory staat: $ mkdir test $ cd test @@ -47,24 +47,24 @@ Het betekend dat in de kern van Git een eenvoudige sleutel-waarde gegevens opsla $ find .git/objects -type f $ -Git heeft de `objects` map geïnitialiseerd en de `pack` en `info` submappen erin aangemaakt, maar er zijn geen reguliere bestanden. Nu sla je wat tekst in je Git databank op: +Git heeft de `objects` directory geïnitialiseerd en de `pack` en `info` subdirectories erin aangemaakt, maar er zijn geen reguliere bestanden. Nu sla je wat tekst in je Git databank op: $ echo 'test content' | git hash-object -w --stdin d670460b4b4aece5915caf5c68d12f560a9fe3e4 -De `-w` verteld `hash-object` dat het object opgeslagen moet worden; anders zal het commando je alleen vertellen wat de sleutel zou zijn. `--stdin` verteld het commando dat het moet lezen van stdin; als je dit niet specificeert verwatch `hash-object` een pad naar een bestand. De uitvoer van het commando is een hash checksum van 40 karakters. Dit is de SHA-1 hash – een checksum van de inhoud die je opslaat plus een kop, waarover je zo meteen meer zult leren. Nu kun je zien hoe Git je gegevens opgeslagen heeft: +De `-w` vertelt `hash-object` dat het object opgeslagen moet worden; anders zal het commando je alleen vertellen wat de sleutel zou zijn. Met `--stdin` vertel je het commando dat het de inhoud moet lezen van stdin; als je dit niet specificeert verwacht `hash-object` een pad naar een bestand. De uitvoer van het commando is een hash checksum van 40 karakters. Dit is de SHA-1 hash: een checksum van de inhoud die je opslaat plus een kop, waarover je zo meteen meer zult leren. Nu kun je zien hoe Git je gegevens opgeslagen heeft: $ find .git/objects -type f .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 -Je kunt een bestand in de `objects` map zien. Dit is hoe Git de inhoud initieel opslaat – as een enkel bestand per stuk inhoud, vernoemd naar de SHA-1 checksum van de inhoud en z'n kop. De submap is vernoemd naar de eerste 2 karakters van de SHA, het het bestandsnaam zijn de overige 38 karakters. +Je kunt een bestand in de `objects` directory zien. Dit is hoe Git de inhoud initieel opslaat: als een enkel bestand per stuk inhoud, vernoemd naar de SHA-1 checksum van de inhoud en z'n kop. De subdirectory is vernoemd naar de eerste 2 karakters van de SHA, en de bestandsnaam is de overige 38 karakters. -Je kunt de inhoud terug uit Git halen met het `cat-file` commando. Dit commando is een soort Zwitsers zakmes om Git objecten mee te inspecteren. Door de `-p` optie mee te geven, instrueer je het `cat-file` commando om uit te zoeken van het type van de inhoud is en om het netjes aan je te tonen: +Je kunt de inhoud terug uit Git halen met het `cat-file` commando. Dit commando is een soort Zwitsers zakmes om Git objecten mee te inspecteren. Door de `-p` optie mee te geven, instrueer je het `cat-file` commando om uit te zoeken wat het type van de inhoud is en om het netjes aan je te tonen: $ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4 test content -Nu kun je inhoud aan Git toevoegen, en het er weer uit halen. Je kunt dit ook doen met inhoud in bestanden. Bijvoorbeeld, je kunt wat eenvoudig versie beheer op een bestand doen. Als eerste maak je een nieuw bestand en slaat de inhoud op in je databank: +Nu kun je inhoud aan Git toevoegen en het er weer uit halen. Je kunt dit ook doen met de inhoud van bestanden. Bijvoorbeeld, je kunt wat eenvoudig versie beheer op een bestand doen. Als eerste maak je een nieuw bestand en slaat de inhoud op in je databank: $ echo 'version 1' > test.txt $ git hash-object -w test.txt @@ -95,21 +95,21 @@ of de tweede versie: $ cat test.txt version 2 -Maar de SHA-1 sleutel voor iedere versie van je bestand onthouden is niet erg praktisch; plus, je bewaard de bestandsnaam niet in je systeem – alleen de inhoud. Dit objecttype heet een blob. Je kunt Git jou het objecttype van ieder object in Git laten vertellen, gegeven de SHA-1 sleutel, met `cat-file -t`: +Maar de SHA-1 sleutel voor iedere versie van je bestand onthouden is niet erg praktisch; plus je bewaart de bestandsnaam niet in je systeem, alleen de inhoud. Dit objecttype heet een blob. Je kunt Git het objecttype van ieder object in Git laten vertellen, gegeven de SHA-1 sleutel, met `cat-file -t`: $ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a blob -### Boom objecten ### +### Boom (tree) objecten ### -Het volgende type waar je naar gaat kijken is het boom object, wat het probleem van het opslaan van de bestandsnaam oplost en het je ook mogelijk maakt om een groep bestanden samen op te slaan. Git slaat inhoud op in dezelfde wijze als een UNIX bestandssysteem, maar dan wat vereenvoudigd. Alle inhoud wordt opgeslagen als boom- en blob-objecten, waarbij bomen corresponderen met UNIX map vermeldingen en blobs min of meer corresponderen aan inodes of bestandsinhoud. Een enkel boomobject bevat één of meer boom vermeldingen, waarvan ieder een SHA-1 point naar een blob of subboom bevat met zijn geassocieerde mode, type en bestandsnaam. Bijvoorbeeld, de meest recente boom in het simplegit project zou er zo uit kunnen zien: +Het volgende type waar je naar gaat kijken is het tree object, wat het probleem van het opslaan van de bestandsnaam oplost en het ook mogelijk maakt om een groep bestanden gezamenlijk op te slaan. Git bewaart inhoud op vergelijkbare wijze als een UNIX bestandssysteem, maar dan wat vereenvoudigd. Alle inhoud wordt opgeslagen als tree- en blob-objecten, waarbij trees corresponderen met UNIX directory vermeldingen en blobs min of meer corresponderen aan inodes of bestandsinhoud. Een enkel treeobject bevat één of meer tree vermeldingen, waarvan ieder een SHA-1 pointer naar een blob of subtree bevat met zijn geassocieerde mode, type en bestandsnaam. Bijvoorbeeld, de meest recente tree in het simplegit project zou er zo uit kunnen zien: $ git cat-file -p master^{tree} 100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README 100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile 040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib -De `master^{tree}` syntax specificeert het boom object waarnaar gewezen wordt door de laatste commit op je `master` branch. Zie dat de `lib` submap geen blob is, maar een pointer naar een andere boom: +De `master^{tree}` syntax specificeert het tree object waarnaar gewezen wordt door de laatste commit op je `master` branch. Merk op dat de `lib` subdirectory geen blob is, maar een pointer naar een andere tree: $ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb @@ -119,32 +119,32 @@ Conceptueel zijn de gegevens die Git opslaat zoiets als in Figuur 9-1. Insert 18333fig0901.png Figuur 9-1. Eenvoudige versie van het Git data model. -Je kunt je eigen boom maken. Normaal gesproken maakt Git een boom door de status van je staging gebied of index te pakken en daar een boom object mee te schrijven. Dus, om een boomobject te maken moet je eerst een index instellen door een paar bestanden te stagen. Om een index te maken met een enkele vermelding – de eerste versie van je test.txt bestand – kun je het sanitaire voorzieningen commando `update-index` gebruiken. Je gebruikt dit commando om kunstmatig de eerdere versie van het test.txt bestand toe te voegen aan een nieuw staging gebied. Je moet het de `--add` optie meegeven, omdat het bestand nog niet bestaat in je staging gebied (je hebt zelfs nog geen staging gebied ingesteld) en `--cacheinfo` omdat het bestand dat je toevoegt niet in je map staat, maar wel in je databank. Daarna specificeer je de mode, SHA-1 en bestandsnaam: +Je kunt je eigen tree maken. Normaal gesproken maakt Git een tree door de status van je staging gebied of index te pakken en daar een tree object mee te schrijven. Dus, om een treeobject te maken moet je eerst een index opzetten door een paar bestanden te stagen. Om een index te maken met een enkele vermelding, de eerste versie van je test.txt bestand, kun je het plumbing commando `update-index` gebruiken. Je gebruikt dit commando om kunstmatig de eerdere versie van het test.txt bestand toe te voegen aan een nieuw staging gebied. Je moet het de `--add` optie meegeven omdat het bestand nog niet bestaat in je staging gebied (je hebt zelfs nog geen staging gebied ingesteld) en `--cacheinfo` omdat het bestand dat je toevoegt niet in je directory staat maar in je databank. Daarna specificeer je de modus, SHA-1 en bestandsnaam: $ git update-index --add --cacheinfo 100644 \ 83baae61804e65cc73a7201a7252750c76066a30 test.txt -In dit geval specificeer je een mode van `100644`, wat betekend dat het een normaal bestand is. Andere opties zijn `100755`, wat betekend dat het een uitvoerbaar bestand is; en `120000`, wat een symbolische link specificeert. De mode is genomen van normale UNIX modes, maar is veel minder flexibel – deze drie modi zijn de enigen die geldig zijn voor bestanden (blobs) in Git (alhoewel andere modi worden gebruikt voor mappen en submodules). +In dit geval specificeer je een modus `100644`, wat aangeeft dat het een normaal bestand is. Andere opties zijn `100755`, wat aangeeft dat het een uitvoerbaar bestand is, en `120000` wat een symbolische link specificeert. De modus is afgekeken van normale UNIX modi, maar is veel minder flexibel; deze drie modi zijn de enige die geldig zijn voor bestanden (blobs) in Git (alhoewel andere modi worden gebruikt voor directories en submodules). -Nu kun je het `write-tree` commando gebruiken om het staging gebied naar een boomobject te schrijven. Er is geen `-w` optie nodig – `write-tree` aanroepen zorgt er automatisch voor dat een boomobject gecreëerd wordt van de status van de index als die boom nog niet bestaat: +Nu kun je het `write-tree` commando gebruiken om het staging area naar een treeobject te schrijven. Er is geen `-w` optie nodig, `write-tree` aanroepen zorgt er automatisch voor dat een treeobject gecreëerd wordt van de status van de index als die tree nog niet bestaat: $ git write-tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 $ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579 100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt -Je kunt ook verifiëren dat dit een boomobject is: +Je kunt ook verifiëren dat dit een treeobject is: $ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579 tree -Je zult nu een nieuwe boom aanmaken met de tweede versie van het test.txt bestand en ook een nieuw bestand: +Je gaat nu een nieuwe tree aanmaken met de tweede versie van het test.txt bestand en ook een nieuw bestand: $ echo 'new file' > new.txt $ git update-index test.txt $ git update-index --add new.txt -Je staging gebied heeft nu een nieuwe versie van test.txt, als ook het nieuwe new.txt bestand. Schrijf de boom (sla de status van het staging gebied of index op als boom object) en kijk hoe het er uit ziet: +Je staging area heeft nu een nieuwe versie van test.txt, als ook het nieuwe new.txt bestand. Schrijf de tree (wat de status van het staging area of index opslaat als tree object) en kijk hoe het er uit ziet: $ git write-tree 0155eb4229851634a0f03eb265b69f5a2d56f341 @@ -152,7 +152,7 @@ Je staging gebied heeft nu een nieuwe versie van test.txt, als ook het nieuwe ne 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt 100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt -Zie dat deze boom beide bestandsvermeldingen bevat en ook dat de SHA van test.txt dezelfde "versie 2" SHA is als eerder (`1f7a7a`). Je zult nu voor de lol de eerste boom als een subboom toevoegen aan deze. Je kunt bomen in je staging gebied lezen door `read-tree` aan te roepen. In dit geval kun je een bestaande boom in je staging gebied lezen als een subboom met de `--prefix` optie aan `read-tree`: +Merk op dat deze tree beide bestandsvermeldingen bevat en ook dat de SHA van test.txt de "versie 2" SHA is van eerder (`1f7a7a`). Je gaat nu voor de lol de eerste tree als een subtree toevoegen aan deze. Je kunt trees in je staging area lezen door `read-tree` aan te roepen. In dit geval kun je een bestaande tree in je staging area lezen als een subtree met de `--prefix` optie aan `read-tree`: $ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579 $ git write-tree @@ -162,16 +162,16 @@ Zie dat deze boom beide bestandsvermeldingen bevat en ook dat de SHA van test.tx 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt 100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt -Als je een werkmap zou maken van de nieuwe boom die je zojuist geschreven hebt, zou je de twee bestanden in het bovenste niveau van de werkmap krijgen en een submap genaamd `bak` die de eerste versie van het test.txt bestand bevatte. Je kunt over de gegevens die Git bevat voor deze structuren denken zoals getoond in Figuur 9-2. +Als je een werkdirectory zou maken van de nieuwe tree die je zojuist geschreven hebt, zou je de twee bestanden in het hoogste niveau van de werkdirectory krijgen en een subdirectory genaamd `bak` die de eerste versie van het test.txt bestand bevat. Je kunt de gegevens die Git bevat voor deze structuren zien zoals getoond in Figuur 9-2. Insert 18333fig0902.png Figuur 9-2. De inhoud structuur van je huidige Git gegevens. ### Commit objecten ### -Je hebt drie bomen die de verschillende snapshots specificeren die je wilt volgen, maar het eerdere probleem blijft: je moet alledrie de SHA-1 waarden onthouden om de snapshots weer op te halen. Je hebt ook geen informatie over wie de snapshots opgeslagen heeft, wanneer ze opgeslagen zijn, of waarom ze opgeslagen zijn. Dit is de basale informatie die het commit object voor je opslaat. +Je hebt drie trees die de verschillende snapshots specificeren die je wilt volgen, maar het eerdere probleem blijft: je moet alledrie SHA-1 waarden onthouden om de snapshots weer op te halen. Je hebt ook geen informatie over wie de snapshots opgeslagen heeft, wanneer ze opgeslagen zijn of waarom ze opgeslagen zijn. Dit is de basale informatie die het commit object voor je bevat. -Om een commit object te creëren moet je `commit-tree` aanroepen en één boom SHA-1 specificeren en welke commit objecten, als er die zijn, er direct aan vooraf gingen. Start met de eerste boom, die je geschreven hebt: +Om een commit object te creëren moet je `commit-tree` aanroepen en één tree SHA-1 specificeren en welke commit objecten, als er die zijn, er direct aan vooraf gingen. Begin met de eerste tree die je geschreven hebt: $ echo 'first commit' | git commit-tree d8329f fdf4fc3344e67ab068f836878b6c4951e3b15f3d @@ -185,16 +185,16 @@ Nu kun je je nieuwe commit object bekijken met `cat-file`: first commit -Het formaat van een commit object is simpel: het specificeert de bovenste boom voor het snapshot van het project op dat punt; de auteur/committer informatie die uit je `user.name` en `user.email` configuratie instellingen gehaald is, met de huidige tijd; een lege regel, en dan de commit boodschap. +Het formaat van een commit object is simpel: het specificeert de hoogste tree voor de snapshot van het project op dat punt, de auteur/committer informatie die uit de `user.name` en `user.email` configuratie instellingen gehaald is, met de huidige tijd, een lege regel en dan de commit boodschap. -Nu zul je de twee andere commit objecten schrijven, waarbij ze elk het commit object dat er direct voor komt refereren: +Nu ga je de twee andere commit objecten schrijven, waarbij ze elk naar het commit object dat er direct voor komt verwijzen: $ echo 'second commit' | git commit-tree 0155eb -p fdf4fc3 cac0cab538b970a37ea1e769cbbde608743bc96d $ echo 'third commit' | git commit-tree 3c4e9c -p cac0cab 1a410efbd13591db07496601ebc7a059dd55cfe9 -Ieder van de drie commit objecten wijst naar één van de drie snapshots die je gemaakt hebt. Vreemd genoeg heb je nu een echte Git historie, die je kunt bekijken met het `git log` commando, als je dat op de SHA-1 van de laatste commit uitvoert: +Ieder van de drie commit objecten wijst naar één van de drie snapshots die je gemaakt hebt. Grappig genoeg heb je nu een echte Git historie die je kunt bekijken met het `git log` commando, als je dat op de SHA-1 van de laatste commit uitvoert: $ git log --stat 1a410e commit 1a410efbd13591db07496601ebc7a059dd55cfe9 @@ -225,7 +225,7 @@ Ieder van de drie commit objecten wijst naar één van de drie snapshots die je test.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) -Verbazingwekkend. Je hebt zojuist de lagere operaties uitgevoerd om een Git history op te bouwen, zonder één van de front ends te gebruiken. Dit is in essentie wat Git doet als je de `git add` en `git commit` commando's uitvoert – het slaat de blobs voor de gewijzigde bestanden op, ververst de index, schrijft de bomen weg, en schrijft commit objecten die de bovenste bomen en commits refereren die vlak voor ze kwamen. Deze drie hoofd Git-objecten – de blob, de boom en de commit – worden in eerste instantie als aparte bestanden opgeslagen in je `.git/objects` map. Hier zijn alle objecten die nu in de voorbeeld map staan, voorzien van commentaar met wat ze bevatten: +Verbazingwekkend. Je hebt zojuist de lagere operaties uitgevoerd om een Git history op te bouwen, zonder één van de front ends te gebruiken. Dit is in essentie wat Git doet als je de `git add` en `git commit` commando's uitvoert: het slaat de blobs voor de gewijzigde bestanden op, ververst de index, schrijft de trees weg, en schrijft commit objecten die de bovenste trees en commits refereren die vlak voor ze kwamen. Deze drie hoofd Git-objecten – de blob, de tree en de commit – worden in eerste instantie als aparte bestanden opgeslagen in je `.git/objects` directory. Hier zijn alle objecten die nu in de voorbeeld directory staan, voorzien van commentaar met wat ze bevatten: $ find .git/objects -type f .git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2 @@ -242,22 +242,22 @@ Verbazingwekkend. Je hebt zojuist de lagere operaties uitgevoerd om een Git hist Als je alle interne verwijzingen volgt, krijg je een object-graaf die er uitzien zoals Figuur 9-3. Insert 18333fig0903.png -Figuur 9-3. Alle objecten in je Git map. +Figuur 9-3. Alle objecten in je Git directory. ### Object opslag ### -Ik vertelde eerder dat er een kop wordt opgeslagen bij de inhoud. Laten we eens een minuutje kijken naar hoe Git zijn objecten opslaat. Je zult zien hoe je interactief een blob object opslaat – in dit geval de tekst "what is up, doc?" – in de Ruby scripttaal. Je kunt de interactieve Ruby modus starten met het `irb` commando: +Ik vertelde eerder dat er een kop wordt opgeslagen bij de inhoud. Laten we eens even kijken naar hoe Git zijn objecten opslaat. Je zult zien hoe je interactief een blob object opslaat, in dit geval de tekst "what is up, doc?", in de Ruby scripttaal. Je kunt de interactieve Ruby modus starten met het `irb` commando: $ irb >> content = "what is up, doc?" => "what is up, doc?" -Git construeert een kop, die begint met het type van het object, in dit geval een blob. Daarna voegt het een spatie toe, gevolgd door de grootte van de inhoud en als laatste een null byte: +Git stelt een kop samen die begint met het type van het object, in dit geval een blob. Daarna voegt het een spatie toe, gevolgd door de grootte van de inhoud en als laatste een null byte: >> header = "blob #{content.length}\0" => "blob 16\000" -Git voegt de kop en de originele inhoud samen, en berekent vervolgens de SHA-1 checksum van die nieuwe inhoud. Je kunt de SHA-1 waarde van een regel tekst in Ruby berekenen door de SHA1 verwerkingsbibliotheek op te nemen met het `require` commando en dan `Digest::SHA1.hexdigest()` aan te roepen met de tekst: +Git voegt de kop en de originele inhoud samen en berekent vervolgens de SHA-1 checksum van die nieuwe inhoud. Je kunt de SHA-1 waarde van een regel tekst in Ruby berekenen door de SHA1 verwerkingsbibliotheek op te nemen met het `require` commando en dan `Digest::SHA1.hexdigest()` aan te roepen met de tekst: >> store = header + content => "blob 16\000what is up, doc?" @@ -273,7 +273,7 @@ Git comprimeert de nieuwe inhoud met zlib, wat je in Ruby kunt doen met de zlib >> zlib_content = Zlib::Deflate.deflate(store) => "x\234K\312\311OR04c(\317H,Q\310,V(-\320QH\311O\266\a\000_\034\a\235" -Als laatste schrijf je je zlib-gecomprimeerde inhoud naar een object op de schijf. Je zult het pad van het object dat je wilt wegschrijven moeten bepalen (de eerste twee karakters van de SHA-1 waarde zijn de submap naam, en de laatste 38 karakters zijn de bestandsnaam in die map). In Ruby kun je de `FileUtils.mkdir_p()` functie gebruiken om de submap aan te maken als hij nog niet bestaat. Daarna open je het bestand met `File.open()` en schrijft de eerder met zlib gecomprimeerde inhoud in het bestand met een aanroep van `write()` op het resulterende bestands-aangrijpingspunt. +Als laatste schrijf je de zlib-gecomprimeerde inhoud naar een object op de schijf. Je bepaalt het pad van het object dat je wilt wegschrijven (de eerste twee karakters van de SHA-1 waarde zijn de subdirectory naam, en de laatste 38 karakters zijn de bestandsnaam in die directory). In Ruby kun je de `FileUtils.mkdir_p()` functie gebruiken om de subdirectory aan te maken als hij nog niet bestaat. Daarna open je het bestand met `File.open()` en schrijft de eerder met zlib gecomprimeerde inhoud in het bestand met een aanroep van `write()` op het resulterende bestands-aangrijpingspunt (file handle). >> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38] => ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37" @@ -284,13 +284,13 @@ Als laatste schrijf je je zlib-gecomprimeerde inhoud naar een object op de schij >> File.open(path, 'w') { |f| f.write zlib_content } => 32 -Dat is het – je hebt nu een geldig Git blob object aangemaakt. Alle Git objecten zijn op dezelfde manier opgeslagen, alleen de types verschillen – in plaats van de tekst blob, zal de kop beginnen met commit of tree. En alhoewel de blob inhoud vrijwel alles kan zijn, hebben de commit en boom inhoud een zeer specifiek formaat. +Dat is alles: je hebt nu een geldig Git blob object aangemaakt. Alle Git objecten zijn op dezelfde manier opgeslagen, alleen de types verschillen. In plaats van de tekst blob, zal de kop beginnen met commit of tree. En alhoewel de blob inhoud vrijwel alles kan zijn, hebben de commit en tree inhoud een zeer specifiek formaat. ## Git referenties ## -Je kunt zoiets als `git log 1a410e` uitvoeren om door je hele geschiedenis te kijken, maar je moet nog steeds onthouden dat `1a410e` de laatste commit is om die geschiedenis te doorlopen en alle objecten te vinden. Je hebt een bestand nodig waarin je de SHA-1 waarde als een eenvoudige naam kunt opslaan, zodat je die als wijzer kunt gebruiken in plaats van de rauwe SHA-1 waarde. +Je kunt zoiets als `git log 1a410e` uitvoeren om door je hele geschiedenis te kijken, maar je moet nog steeds onthouden dat `1a410e` de laatste commit is om die geschiedenis te doorlopen en alle objecten te vinden. Je hebt een bestand nodig waarin je de SHA-1 waarde als een eenvoudige naam kunt opslaan, zodat je die als wijzer kunt gebruiken in plaats van de kale SHA-1 waarde. -In Git worden deze "referenties" of "refs" genoemd; je kunt de bestanden die de SHA-1 waarden bevatten vinden in de `.git/refs` map. In het huidige project bevat deze map geen bestanden, maar het bevat wel een eenvoudige structuur: +In Git worden deze "referenties" of "refs" genoemd; je kunt de bestanden die de SHA-1 waarden bevatten vinden in de `.git/refs` directory. In het huidige project bevat deze directory geen bestanden, maar het bevat wel een eenvoudige structuur: $ find .git/refs .git/refs @@ -299,18 +299,18 @@ In Git worden deze "referenties" of "refs" genoemd; je kunt de bestanden die de $ find .git/refs -type f $ -Om een nieuwe referentie aan te maken, die je zal helpen herinneren waar je laatste commit is, kun je technisch zoiets eenvoudigs als dit doen: +Om een nieuwe referentie aan te maken,die je zal helpen herinneren waar je laatste commit is, kun je technisch zoiets eenvoudigs als dit doen: $ echo "1a410efbd13591db07496601ebc7a059dd55cfe9" > .git/refs/heads/master -Nu kun je de head referentie, die je zojuist hebt aangemaakt, gebruiken in je Git commando's, in plaats van de SHA-1 waarde: +Nu kan je de head referentie die je zojuist hebt aangemaakt gebruiken in je Git commando's, in plaats van de SHA-1 waarde: $ git log --pretty=oneline master 1a410efbd13591db07496601ebc7a059dd55cfe9 third commit cac0cab538b970a37ea1e769cbbde608743bc96d second commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit -Je wordt niet aangemoedigd om de referentie bestanden direct aan te passen. Git levert een veiliger commando mee om dit te doen als je een referentie wilt aanpassen, genaamd `update-ref`: +Het wordt niet aangeraden om de referentie bestanden direct aan te passen. Git levert een veiliger commando mee om dit te doen als je een referentie wilt aanpassen, genaamd `update-ref`: $ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9 @@ -318,7 +318,7 @@ Dat is eigenlijk wat een branch in Git is: een eenvoudige wijzer of referentie n $ git update-ref refs/heads/test cac0ca -Je branch zal alleen werk bevatten vanaf die commit en verder: +Je branch zal alleen werk bevatten vanaf die commit en eerder: $ git log --pretty=oneline test cac0cab538b970a37ea1e769cbbde608743bc96d second commit @@ -327,13 +327,13 @@ Je branch zal alleen werk bevatten vanaf die commit en verder: Nu ziet je Git gegevensbank er conceptueel ongeveer uit zoals in Figuur 9-4. Insert 18333fig0904.png -Figuur 9-4. Git map objecten met branch head referenties erbij. +Figuur 9-4. Git directory objecten met branch head referenties erbij. -Als je commando's zoals `git branch (branchnaam)` uitvoert, voert Git eigenlijk dat `update-ref` commando uit om de SHA-1 van de laatste commit van de branch waarop je zit, toe te voegen aan welke referentie je ook wil maken. +Als je commando's zoals `git branch (branchnaam)` uitvoert, voert Git eigenlijk dat `update-ref` commando uit om de SHA-1 van de laatste commit van de branch waarop je zit toe te voegen aan welke referentie je ook wil maken. ### De HEAD ### -De vraag is nu, als je `git branch (branchnaam)` uitvoert, hoe weet Git de SHA-1 van de laatste commit? Het antwoord is het HEAD bestand. Het HEAD bestand is een symbolische referentie naar de branch waar je momenteel op zit. Met symbolische referentie bedoel ik dat, in tegenstelling tot een normale referentie, het over het algemeen geen SHA-1 waarde bevat maar een pointer naar een andere referentie. Als je naar het bestand kijkt, zul je normaal gesproken zoiets als dit zien: +De vraag is nu: als je `git branch (branchnaam)` uitvoert, hoe weet Git de SHA-1 van de laatste commit? Het antwoord is het HEAD bestand. Het HEAD bestand is een symbolische referentie naar de branch waar je momenteel op zit. Met symbolische referentie bedoel ik dat, in tegenstelling tot een normale referentie, het over het algemeen geen SHA-1 waarde bevat maar een verwijzing naar een andere referentie. Als je naar het bestand kijkt, zul je normaal gesproken zoiets als dit zien: $ cat .git/HEAD ref: refs/heads/master @@ -343,7 +343,7 @@ Als je `git checkout test` uitvoert, zal Git het bestand vernieuwen zodat het er $ cat .git/HEAD ref: refs/heads/test -Als je `git commit` uitvoert, wordt het commit object gecreëerd, waarbij de ouder van dat commit object gezet wordt naar welke SHA-1 waarde de referentie in HEAD ook wijst. +Als je `git commit` uitvoert wordt het commit object gecreëerd, waarbij de ouder van die commit object gezet wordt op de SHA-1 waarde van de referentie waar de HEAD op dat moment naar verwijst. Je kunt dit bestand ook handmatig aanpassen, maar ook daar bestaat weer een veiliger commando voor: `symbolic-ref`. Je kunt de waarde van je HEAD lezen via dit commando: @@ -363,13 +363,13 @@ Je kunt geen symbolische referentie instellen die buiten de refs stijl valt: ### Tags ### -Je bent zojuist door drie hoofdobject types van Git gegaan, maar er bestaat een vierde. Het tag object komt veel overeen met een commit object – het bevat een tagger, een datum, een bericht, en een pointer. Het grootste verschil is dat een tag object naar een commit wijst in plaats van een boom. Het is vergelijkbaar met een branch referentie, maar het beweegt nooit – het zal altijd naar dezelfde commit wijzen, maar geeft het een vriendelijker naam. +We hebben zojuist de drie hoofdobject types van Git behandeld, maar er bestaat een vierde. Het tag object lijkt erg op een commit object: het bevat een tagger, een datum, een bericht en een pointer. Het grootste verschil is dat een tag object naar een commit wijst in plaats van een tree. Het is vergelijkbaar met een branch referentie, maar het beweegt nooit. Het zal altijd naar dezelfde commit wijzen, maar geeft het een vriendelijker naam. Zoals besproken in hoofdstuk 2, zijn er twee soorten tags: beschreven en lichtgewicht. Je kunt een lichtgewicht tag maken door zoiets als dit uit te voeren: $ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d -Dat is wat een lichtgewicht tag is – een branch die nooit beweegt. Een beschreven tag is echter complexer. Als je een beschreven tag aanmaakt, creëert Git een tag object en schrijft een referentie die daar naar wijst, in plaats van direct naar de commit. Je kunt dit zien door een beschreven tag aan te maken (`-a` specificeert dat het een beschreven tag is): +Dat is wat een lichtgewicht tag is: een branch die nooit beweegt. Een beschreven tag is echter ingewikkelder. Als je een beschreven tag aanmaakt, creëert Git een tag object en schrijft een referentie die daar naar wijst in plaats van direct naar de commit. Je kunt dit zien door een beschreven tag aan te maken (`-a` specificeert dat het een beschreven tag is): $ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 –m 'test tag' @@ -388,15 +388,15 @@ Voer nu het `cat-file` commando uit op die SHA-1 waarde: test tag -Zie dat de object regel wijst naar de SHA-1 waarde die je getagged hebt. Zie ook dat het niet naar een commit hoeft te wijzen: je kunt ieder Git object een tag geven. In de Git broncode bijvoorbeeld, heeft de maintainer zijn publieke GPG sleutel als een blob object toegevoegd en het een tag gegeven. Je kunt de publieke sleutel bekijken door dit uit te voeren +Merk op dat de object regel wijst naar de SHA-1 waarde die je getagged hebt. Merk ook op dat het niet naar een commit hoeft te wijzen; je kunt ieder Git object een tag geven. In de Git broncode bijvoorbeeld, heeft de maintainer zijn publieke GPG sleutel als een blob object toegevoegd en het een tag gegeven. Je kunt de publieke sleutel bekijken door dit uit te voeren $ git cat-file blob junio-gpg-pub -in de Git broncode. De Linux kernel heeft ook een non-commit-wijzend tag object – het eerste tag object wijst naar de eerste tree van de import van de broncode. +in de Git broncode. De Linux kernel heeft ook een non-commit-verwijzend tag object – het eerste tag object wijst naar de eerste tree van de import van de broncode. ### Remotes ### -Het derde soort referentie dat je zult zien is een remote referentie. Als je een remote toevoegt en er naar pusht, slaat Git de laatste waarde van iedere branch op die je gepusht hebt naar die remote in de `refs/remotes` map. Bijvoorbeeld, je kunt een remote genaamd `origin` toevoegen en je master branch hier naar pushen: +Het derde soort referentie dat je zult zien is een remote referentie. Als je een remote toevoegt en er naar pushed, slaat Git de laatste waarde van iedere branch op die je gepushed hebt naar die remote in de `refs/remotes` directory. Bijvoorbeeld, je kunt een remote genaamd `origin` toevoegen en je master branch hier naar pushen: $ git remote add origin git@github.com:schacon/simplegit-progit.git $ git push origin master @@ -416,7 +416,7 @@ Remote referenties verschillen hoofdzakelijk van branches (`refs/heads` referent ## Packfiles ## -Laten we eens terug gaan naar de object-databank van je test Git repository. Op dit punt heb je 11 objecten – 4 blobs, 3 bomen, 3 commits en 1 tag: +Laten we eens terug gaan naar de object-databank van je test Git repository. Op dit punt heb je 11 objecten – 4 blobs, 3 trees, 3 commits en 1 tag: $ find .git/objects -type f .git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2 @@ -431,7 +431,7 @@ Laten we eens terug gaan naar de object-databank van je test Git repository. Op .git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt .git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1 -Git comprimeert de inhoud van deze bestanden met zlib, en je slaat maar weinig op, dus nemen deze bestanden samen maar 925 bytes in beslag. Je zult nu wat grotere inhoud toevoegen aan het repository om een interessante eigenschap van Git te demonstreren. Voeg het repo.rb bestand toe van de Grit bibliotheek waaraan je eerder gewerkt hebt – dit is een broncode bestand van ongeveer 12K groot: +Git comprimeert de inhoud van deze bestanden met zlib en je slaat maar weinig op, dus nemen deze bestanden samen maar 925 bytes in beslag. Je zult nu wat grotere inhoud toevoegen aan het repository om een interessante eigenschap van Git te demonstreren. Voeg het repo.rb bestand toe van de Grit bibliotheek waaraan je eerder gewerkt hebt, dit is een broncode bestand van ongeveer 12K groot: $ curl http://github.com/mojombo/grit/raw/master/lib/grit/repo.rb > repo.rb $ git add repo.rb @@ -442,40 +442,40 @@ Git comprimeert de inhoud van deze bestanden met zlib, en je slaat maar weinig o create mode 100644 repo.rb rewrite test.txt (100%) -Als je naar de resulterende boom kijkt, kun je zien welke SHA-1 waarde je repo.rb gekregen heeft voor het blob object: +Als je naar de resulterende tree kijkt, kun je zien welke SHA-1 waarde repo.rb gekregen heeft voor het blob object: $ git cat-file -p master^{tree} 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt 100644 blob 9bc1dc421dcd51b4ac296e3e5b6e2a99cf44391e repo.rb 100644 blob e3f094f522629ae358806b17daf78246c27c007b test.txt -Je kunt dan het `git cat-file` commando gebruiken om te zien hoe groot dat object is: +Dan controleer je hoe groot het object is op jouw schijf: - $ git cat-file -s 9bc1dc421dcd51b4ac296e3e5b6e2a99cf44391e - 12898 + $ du -b .git/objects/9b/c1dc421dcd51b4ac296e3e5b6e2a99cf44391e + 4102 .git/objects/9b/c1dc421dcd51b4ac296e3e5b6e2a99cf44391e -Pas het bestand nu eens een beetje aan, en kijk wat er gebeurd: +Pas het bestand nu eens een beetje aan, en kijk wat er gebeurt: $ echo '# testing' >> repo.rb $ git commit -am 'modified repo a bit' [master ab1afef] modified repo a bit 1 files changed, 1 insertions(+), 0 deletions(-) -Bekijk de boom die door de commit gemaakt is, en je zult iets interessants zien: +Bekijk de tree die door de commit gemaakt is, en je zult iets interessants zien: $ git cat-file -p master^{tree} 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt 100644 blob 05408d195263d853f09dca71d55116663690c27c repo.rb 100644 blob e3f094f522629ae358806b17daf78246c27c007b test.txt -De blob is nu een andere blob, wat betekent dat alhoewel je slechts een enkele regel aan het eind van een bestand van 400 regels toegevoegd hebt, Git die nieuwe inhoud als een compleet nieuw object opgeslagen heeft: +De blob is nu een andere blob, wat betekent dat, alhoewel je slechts een enkele regel aan het eind van een bestand van 400 regels toegevoegd hebt, Git die nieuwe inhoud als een compleet nieuw object opgeslagen heeft: - $ git cat-file -s 05408d195263d853f09dca71d55116663690c27c - 12908 + $ du -b .git/objects/05/408d195263d853f09dca71d55116663690c27c + 4109 .git/objects/05/408d195263d853f09dca71d55116663690c27c -Je hebt nu twee vrijwel identieke 12K grote objecten op je harde schijf. Zou het niet fijn zijn als Git één van de twee volledig op kon slaan, en het tweede object slechts als delta tussen die en de eerste? +Je hebt nu twee vrijwel identieke 12K grote objecten op je harde schijf. Zou het niet prettig zijn als Git één van de twee volledig op kon slaan, en het tweede object slechts als delta tussen die en de eerste? -Het blijkt dat dat kan. Het initiële formaat waarin Git objecten opslaat op de harde schijf wordt een los object formaat genoemd. Maar, eens in de zoveel tijd pakt Git een aantal van die objecten in een enkel binair bestand wat een packfile genoemd wordt, om wat ruimte te besparen en efficiënter te zijn. Git doet dit als je teveel losse objecten rond hebt slingeren, als je het `git gc` commando handmatig uitvoert, of als je naar een remote server pusht. Om te zien wat er gebeurd, kun je Git handmatig vragen om de objecten in te pakken met het `git gc` commando: +Dat kan dus. Het initiële formaat waarin Git objecten opslaat op de harde schijf wordt een los ('loose') object formaat genoemd. Maar, eens in de zoveel tijd pakt Git een aantal van die objecten samen in een enkel binair bestand wat een packfile genoemd wordt, om ruimte te besparen en efficiënter te zijn. Git doet dit als je teveel losse objecten rond hebt slingeren als je het `git gc` commando handmatig uitvoert, of als je naar een remote server pushed. Om te zien wat er gebeurt, kun je Git handmatig vragen om de objecten in te pakken met het `git gc` commando: $ git gc Counting objects: 17, done. @@ -484,7 +484,7 @@ Het blijkt dat dat kan. Het initiële formaat waarin Git objecten opslaat op de Writing objects: 100% (17/17), done. Total 17 (delta 1), reused 10 (delta 0) -Als je in je objecten map kijkt, zul je zien dat de meeste objecten verdwenen zijn, en er een aantal nieuwe bestanden verschenen zijn: +Als je in je objecten directory kijkt, zul je zien dat de meeste objecten verdwenen zijn, en er een aantal nieuwe bestanden verschenen zijn: $ find .git/objects -type f .git/objects/71/08f7ecb345ee9d0084193f147cdad4d2998293 @@ -493,11 +493,11 @@ Als je in je objecten map kijkt, zul je zien dat de meeste objecten verdwenen zi .git/objects/pack/pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.idx .git/objects/pack/pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.pack -De objecten die overgebleven zijn, zijn de blobs waarnaar geen enkel commit wijst – in dit geval zijn het de "what is up, doc?" en de "test content" voorbeeld-blobs die je eerder aangemaakt hebt. Omdat je ze nooit aan een commit toegevoegd hebt, worden ze beschouwd als 'rondslingerend' en worden ze niet in je nieuwe packfile ingepakt. +De objecten die overgebleven zijn, zijn de blobs waarnaar geen enkel commit wijst; in dit geval zijn het de "what is up, doc?" en de "test content" voorbeeld-blobs die je eerder aangemaakt hebt. Omdat je ze nooit aan een commit toegevoegd hebt, worden ze beschouwd als rondslingerend ('dangling') en niet in je nieuwe packfile ingepakt. -De andere bestanden zijn je nieuwe packfile en een index. De packfile is een enkel bestand dat de inhoud bevat van alle objecten die van je bestandssysteem verwijderd zijn. De index is een bestand dat offsets binnen de packfile bevat, zodat je snel naar een specifiek object kunt zoeken. Wat cool is, is dat alhoewel de objecten op de harde schijf voordat je `gc` aanriep samen zo'n 12K groot waren, is de nieuwe packfile slechts 6K. Je hebt je schijfgebruik gehalveerd door je bestanden in te pakken. +De andere bestanden zijn het nieuwe packbestand en een index. Het packbestand is een enkel bestand dat de inhoud bevat van alle objecten die van je bestandssysteem verwijderd zijn. De index is een bestand dat offsets binnen de packfile bevat, zodat je snel naar een specifiek object kunt zoeken. Wat stoer is, is dat waar de objecten op de harde schijf voordat je `gc` aanriep samen zo'n 8K groot waren, de nieuwe packfile slechts 4K groot is. Je hebt je schijfgebruik gehalveerd door je bestanden in te pakken. -Hoe doet Git dit? Als Git objecten inpakt, zoekt het naar bestanden die gelijk genaamd en in grootte zijn, en slaat slechts de delta's van één versie van het bestand naar de volgende op. Je kunt in de packfile kijken en zien wat Git gedaan heeft om ruimte te besparen. Het `git verify-pack` sanitaire voorzieningen commando stelt je in staat om te zien wat er ingepakt is: +Hoe doet Git dit? Als Git objecten inpakt, zoekt het naar bestanden die qua naam en grootte gelijk zijn, en slaat slechts de delta's van de ene versie van het bestand naar de volgende op. Je kunt in de packfile kijken en zien wat Git gedaan heeft om ruimte te besparen. Het `git verify-pack` plumbing commando stelt je in staat om te zien wat er ingepakt is: $ git verify-pack -v \ .git/objects/pack/pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.idx @@ -522,26 +522,26 @@ Hoe doet Git dit? Als Git objecten inpakt, zoekt het naar bestanden die gelijk g chain length = 1: 1 object pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.pack: ok -Hier refereert de `9bc1d` blob, wat als je je dat herinnert de eerste versie is van je repo.rb bestand, aan de `05408` blob, wat de tweede versie was van het bestand. De derde kolom in de uitvoer is e grootte van het object in het pakket, zodat je kunt zien dat `05408` 12K van het bestand in beslag neemt maar dat `9bc1d` slechts 7 bytes in beslag neemt. Wat ook interessant is, is dat de tweede versie van het bestand degene is die intact opgeslagen wordt, terwijl de originele versie als delta opgeslagen wordt – dit is zo gedaan omdat het waarschijnlijker is dat je snellere toegang nodig hebt tot de meest recente versie van het bestand. +Hier refereert de `9bc1d` blob wat, als je dat nog kunt herinneren, de eerste versie is van je repo.rb bestand, aan de `05408` blob, wat de tweede versie was van het bestand. De derde kolom in de uitvoer is de grootte van het object in het pakket, zodat je kunt zien dat `05408` 12K van het bestand in beslag neemt maar dat `9bc1d` slechts 7 bytes in beslag neemt. Wat ook interessant is, is dat de tweede versie van het bestand degene is die intact opgeslagen wordt, terwijl de originele versie als delta opgeslagen wordt. Dit is zo gedaan omdat het aannemelijk is dat je snellere toegang nodig hebt tot de meest recente versie van het bestand. -Het fijnste van dit alles is, is dat het op ieder gewenst moment opnieuw ingepakt kan worden. Git zal op z'n tijd je databank automatisch opnieuw inpakken, waarmee het altijd meer ruimte wil besparen. Je kunt ook handmatig opnieuw inpakken op ieder tijdstip, door `git gc` met de hand uit te voeren. +Het echt prettige van dit alles is, dat het op ieder gewenst moment opnieuw ingepakt kan worden. Git zal op gezette tijden je databank automatisch opnieuw inpakken, waarmee het altijd meer ruimte wil besparen. Je kunt ook handmatig opnieuw inpakken op elk gewenst tijdstip, door `git gc` met de hand uit te voeren. ## De refspec ## -Door dit boek heen heb je eenvoudige verwijzingen van remote branches naar lokale referenties gebruikt; maar ze kunnen complexer zijn. +Door dit boek heen heb je eenvoudige verwijzingen van remote branches naar lokale referenties gebruikt, maar ze kunnen ingewikkelder zijn. Stel dat je een remote zoals dit toevoegt: $ git remote add origin git@github.com:schacon/simplegit-progit.git -Dit voegt een sectie aan je `.git/config` bestand toe, wat de naam van de remote (`origin`) specificeert, de URL van de remote repository, en de refspec die nodig is om te fetchen: +Dit voegt een sectie toe aan je `.git/config` bestand, met de naam van de remote (`origin`), de URL van de remote repository, en de refspec die nodig is om te fetchen: [remote "origin"] url = git@github.com:schacon/simplegit-progit.git fetch = +refs/heads/*:refs/remotes/origin/* -Het formaat van de refspec is een optionele `+`, gevolgd door `:`, waarbij `` het patroon voor referenties aan de remote kant is, en `` is de locatie waar die referenties lokaal geschreven worden. De `+` verteld Git om de referentie zelfs te vernieuwen als het geen fast-forward is. +Het formaat van de refspec is een optionele `+`, gevolgd door `:`, waarbij `` het patroon voor referenties aan de remote kant is, en `` is de locatie waar die referenties lokaal geschreven zullen worden. De `+` vertelt Git om de referentie zelfs te vernieuwen als het geen fast-forward is. -In het standaard geval dat automatisch geschreven wordt door een `git remote add` commando, haalt Git alle referenties onder `refs/heads/` van de server en schrijft ze lokaal naar `refs/remotes/origin/`. Dus als er een `master` branch op de server bestaat, kun je de log van die branch lokaal benaderen via +In het standaard geval dat automatisch geschreven wordt door een `git remote add` commando, haalt Git alle referenties onder `refs/heads/` van de server op en schrijft ze lokaal naar `refs/remotes/origin/`. Dus als er een `master` branch op de server bestaat, kun je de log van die branch lokaal benaderen via $ git log origin/master $ git log remotes/origin/master @@ -553,7 +553,7 @@ Als je wilt dat Git alleen de `master` branch pulled, en niet alle andere branch fetch = +refs/heads/master:refs/remotes/origin/master -Dit is alleen de standaard refspec voor `git fetch` voor die remote. Als je iets alleen eenmalig wilt doen, kun je de refspec ook op de commandoregel specificeren. Om de `master` branch op de remote naar de lokale `origin/mymaster` te pullen, kun je dit uitvoeren +Dit is alleen de standaard refspec voor `git fetch` voor die remote. Als je iets echt eenmalig wilt doen, kun je de refspec ook op de commandoregel specificeren. Om de `master` branch op de remote naar de lokale `origin/mymaster` te pullen, kun je dit uitvoeren $ git fetch origin master:refs/remotes/origin/mymaster @@ -565,9 +565,9 @@ Je kunt ook meerdere refspecs specificeren. Met de commandoregel kun je meerdere ! [rejected] master -> origin/mymaster (non fast forward) * [new branch] topic -> origin/topic -In dit geval wordt de pull van de master branch geweigerd, omdat het geen fast-forward referentie is. Je kunt dat teniet doen door de `+` voor de refspec te zetten. +In dit geval werd de pull van de master branch geweigerd, omdat het geen fast-forward referentie is. Je kunt dat teniet doen door de `+` voor de refspec te zetten. -Je kun ook meerdere refspecs voor het fetchen specificeren in je configuratie bestand. Als je altijd de master en experiment branches wilt fetchen, voeg dan twee regels toe: +Je kun ook meerdere refspecs voor het fetchen specificeren in je configuratie bestand. Als je altijd de master en experiment branches wilt fetchen, voeg je twee regels toe: [remote "origin"] url = git@github.com:schacon/simplegit-progit.git @@ -578,18 +578,18 @@ Je kunt geen gedeeltelijke globs in het patroon gebruiken, dus het volgende zou fetch = +refs/heads/qa*:refs/remotes/origin/qa* -Maar je kunt wel naamruimtes gebruiken om zoiets voor elkaar te krijgen. Als je een QA team hebt dat naar een serie branches pusht, en je wilt de master branch en alle QA team branches hebben, maar niets anders, kun je een configuratie sectie zoals dit gebruiken: +Maar je kunt wel naamruimtes ('namespaces') gebruiken om zoiets voor elkaar te krijgen. Als je een QA team hebt dat naar een serie branches pushed, en je wilt de master branch en alle QA team branches hebben, maar niets anders, kun je een configuratie sectie zoals dit gebruiken: [remote "origin"] url = git@github.com:schacon/simplegit-progit.git fetch = +refs/heads/master:refs/remotes/origin/master fetch = +refs/heads/qa/*:refs/remotes/origin/qa/* -Als je een ingewikkeld werkproces hebt waarbij het QA team branches pusht, ontwikkelaars branches pushen, en integratie teams pushen en samenwerken op remote branches, kun je ze op deze manier eenvoudig in naamruimten stoppen. +Als je een ingewikkelde workflow hebt waarbij het QA team branches pushed, ontwikkelaars branches pushen, en integratie teams op remote branches pushen en samenwerken, kun je ze op deze manier eenvoudig in namespaces onderverdelen. ### Refspecs pushen ### -Het is fijn dat je op die manier referenties in naamruimten kunt fetchen, maar hoe krijgt het QA team in de eerste plaats al hun branches in een `qa/` naamruimte? Je krijgt dat voor elkaar door refspecs te gebruiken om mee te pushen. +Het is prettig dat je op die manier referenties met namespaces kunt fetchen, maar hoe krijgt het QA team om te beginnen al hun branches in een `qa/` namespace? Je krijgt dat voor elkaar door refspecs te gebruiken voor het pushen. Als het QA team hun `master` branch naar `qa/master` op de remote server wil pushen, kunnen ze dit uitvoeren @@ -610,35 +610,35 @@ Je kunt de refspec ook gebruiken om referenties te verwijderen van de remote ser $ git push origin :topic -Omdat de refspec `:` is, verteld het weglaten van het `` gedeelte in feite dat de onderwerp branch op de remote niks is, wat het verwijderd. +Omdat de refspec `:` is wordt, door het weglaten van het `` gedeelte, in feite verteld dat de onderwerp branch op de remote niets is, waardoor het verwijderd wordt. ## Overdracht protocollen ## -Git kan gegevens tussen twee repositories hoofdzakelijk overdragen op twee manieren: via HTTP en via de zogenaamde slimme protocollen die in de `file://`, `ssh://` en `git://` overdrachten gebruikt worden. Deze sectie zal laten zien hoe deze hoofdprotocollen werken. +Git draagt gegevens tussen twee repositories hoofdzakelijk op twee manieren over: via HTTP en via de zogenaamde slimme protocollen die in de `file://`, `ssh://` en `git://` overdrachten gebruikt worden. Deze paragraaf zal laten zien hoe deze hoofdprotocollen werken. ### Het domme Protocol ### -Naar Git overdracht over HTTP wordt vaak gerefereerd als het domme protocol, omdat het geen Git-specifieke code vereist op de server gedurende het overdrachtsproces. Het fetch proces is een reeks van GET verzoeken, waarbij de client de opmaak van het Git repository van de server kan overnemen. Laten we het `http-fetch` proces eens volgen voor de simplegit bibliotheek: +Naar Git-overdracht via HTTP wordt vaak gerefereerd als het domme protocol, omdat het geen Git-specifieke code vereist op de server tijdens het overdrachtsproces. Het fetch proces is een reeks van GET verzoeken, waarbij de client de indeling van het Git repository van de server kent. Laten we het `http-fetch` proces eens volgen voor de simplegit bibliotheek: $ git clone http://github.com/schacon/simplegit-progit.git -Het eerste wat dit commando doet is het `info/refs` bestand pullen. Dit bestand wordt geschreven door het `update-server-info` commando, en dat is de reden waarom je dat als een `post-recieve` haak in moet stellen voordat de HTTP overdracht naar behoren werkt: +Het eerste wat dit commando doet is het `info/refs` bestand pullen. Dit bestand wordt geschreven door het `update-server-info` commando, en dat is de reden waarom je dat als een `post-recieve` hook in moet stellen voordat de HTTP overdracht naar behoren werkt: => GET info/refs ca82a6dff817ec66f44342007202690a93763949 refs/heads/master -Nu heb je een lijst met de remote referenties en SHA's. Daarna kijk je naar wat de HEAD referentie is, zodat je weet wat je uit moet checken zodra je klaar bent: +Nu heb je een lijst met de remote referenties en SHA's. Daarna kijk je naar de waarde van de HEAD referentie, zodat je weet wat je uit moet checken zodra je klaar bent: => GET HEAD ref: refs/heads/master Je moet de `master` branch uitchecken zodra je het proces afgerond hebt. -Op dit punt ben je klaar om het doorloop proces te starten. Omdat je startpunt het `ca82a6` commit object is dat je in het `info/refs` bestand zag, begin je met dit op te halen: +Op dit punt ben je klaar om het proces doorlopen te starten. Omdat je startpunt het `ca82a6` commit object is dat je in het `info/refs` bestand zag, begin je met dit op te halen: => GET objects/ca/82a6dff817ec66f44342007202690a93763949 (179 bytes of binary data) -Je krijgt een object terug – dat object staat in los formaat op de server, en je hebt het gehaald door een statisch HTTP GET verzoek. Je kunt het met zlib decomprimeren, de kop eraf halen, en naar de commit inhoud kijken: +Je krijgt een object terug, dat object staat in los formaat op de server, en je hebt het gehaald met een statisch HTTP GET verzoek. Je kunt het met zlib decomprimeren, de kop eraf halen en naar de commit inhoud kijken: $ git cat-file -p ca82a6dff817ec66f44342007202690a93763949 tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf @@ -648,37 +648,37 @@ Je krijgt een object terug – dat object staat in los formaat op de server, en changed the version number -Daarna heb je nog twee objecten op te halen – `cfda3b`, wat de boom is met inhoud waar de commit die je zojuist hebt opgehaald naar wijst; en `085bb3`, wat de ouder commit is: +Daarna heb je nog twee objecten op te halen: `cfda3b`, wat de tree is met inhoud waar de commit die je zojuist hebt opgehaald naar wijst, en `085bb3`, wat de ouder commit is: => GET objects/08/5bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 (179 bytes of data) -Dat geeft je je volgende commit object. Pak het boom object: +Dat geeft je het volgende commit object. Pak het tree object: => GET objects/cf/da3bf379e4f8dba8717dee55aab78aef7f4daf (404 - Not Found) -Oops – het ziet ernaar uit dat dat boom object niet in het losse formaat op de server bestaat, dus krijg je een 404 antwoord. Er zijn hiervoor een aantal redenen – het object kan in een ander repository staat, of het kan in een packfile in dit repository staat. Git gaat eerst naar de genoemde alternatieven kijken: +Oeps, het ziet ernaar uit dat die tree object niet in het losse formaat op de server bestaat, dus krijg je een 404 antwoord. Er zijn hiervoor een aantal redenen: het object kan in een ander repository staat, of het kan in een packfile in dit repository staan. Git gaat eerst naar de benoemde alternatieven kijken: => GET objects/info/http-alternates (empty file) -Als dit een lijst met alternatieve URL's bevat, zal Git daar voor losse bestanden en packfiles gaan kijken – dit is een fijn mechanisme voor projecten die forks zijn van een ander zodat ze objecten kunnen delen op de schijf. Maar, omdat er in dit geval geen alternatieven vermeld staan, moet je object in een packfile zitten. Om te zien welke packfiles beschikbaar zijn op deze server, moet je het `objects/info/packs` bestand halen, wat een lijst hiervan bevat (ook gegenereerd door `update-server-info`): +Als dit een lijst met alternatieve URL's bevat, zal Git daar voor losse bestanden en packfiles gaan kijken. Dit is een prettig mechanisme voor projecten die forks zijn van een ander zodat ze objecten kunnen delen op de schijf. Maar omdat er in dit geval geen alternatieven vermeld staan, moet het object in een packfile zitten. Om te zien welke packfiles beschikbaar zijn op deze server moet je het `objects/info/packs` bestand ophalen, wat een lijst hiervan bevat (ook gegenereerd door `update-server-info`): => GET objects/info/packs P pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack -Er is slechts één packfile op de server, dus je object zit daar natuurlijk in, maar je bekijkt het index bestand om het zeker te weten. Dit is ook handig als je meerdere packfiles op de server hebt, zodat je kunt zien welke packfile het object dat je nodig hebt bevat: +Er is slechts één packfile op de server dus dat object zit daar natuurlijk in, maar je controleert het index bestand om het zeker te weten. Dit is ook handig als je meerdere packfiles op de server hebt, zodat je kunt zien welke packfile het object dat je nodig hebt bevat: => GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.idx (4k of binary data) -Nu dat je de packfile index hebt, kun je zien of je object hier in zit – omdat de index de SHA's van de objecten in de packfile toont en de offset naar die objecten. Je object is aanwezig, dus ga ervoor en haal de hele packfile op: +Nu je de packfile index hebt kun je zien of het object hier in zit; omdat de index de SHA's van de objecten in de packfile toont en de offsets naar die objecten. Het gezochte object is aanwezig, dus gaat verder en haalt de hele packfile op: => GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack (13k of binary data) -Je hebt je boom object, dus je kunt verder gaan met het doorlopen van je commits. Ze zitten ook allemaal in de packfile die je zojuist gedownload hebt, dus je hoeft geen verzoeken meer te doen aan je server. Git checked een werkkopie uit van de `master` branch waarnaar gewezen werd door de HEAD referentie, die je aan het begin gedownload hebt. +Je hebt de tree object te pakken, dus je kunt verder gaan met het doorlopen van de commits. Ze zitten ook allemaal in de packfile die je zojuist gedownload hebt, dus je hoeft geen verzoeken meer te doen aan je server. Git checked een werkkopie uit van de `master` branch waarnaar gewezen werd door de HEAD referentie, die je aan het begin gedownload hebt. Het gehele uitvoer van dit proces ziet er zo uit: @@ -697,46 +697,46 @@ Het gehele uitvoer van dit proces ziet er zo uit: ### Het slimme protocol ### -De HTTP methode is eenvoudig, maar een beetje inefficiënt. Slimme protocollen gebruiken is een meer gebruikte manier van gegevensoverdracht. Deze protocollen hebben een proces aan de remote kant dat bewust is van Git – het kan lokale gegevens lezen en uitvinden wat de client heeft, of nodig heeft en hier eigen gegevens voor genereren. Er zijn twee sets processen voor gegevensoverdracht: een paar voor het uploaden van gegevens, en een paar voor het downloaden van gegevens. +De HTTP methode is eenvoudig, maar een beetje inefficiënt. Slimme protocollen gebruiken is een meer gebruikelijke manier van gegevensoverdracht. Deze protocollen hebben een proces aan de remote kant dat bewust is van Git: het kan lokale gegevens lezen en uitvinden wat de client heeft of nodig heeft en hier specifieke gegevens voor genereren. Er zijn twee paar processen voor gegevensoverdracht: één paar voor het uploaden van gegevens en één paar voor het downloaden van gegevens. #### Gegevens uploaden #### Om gegevens te uploaden naar een remote proces, gebruikt Git de `send-pack` en `receive-pack` processen. Het `send-pack` proces draait op de client en maakt contact met een `receive-pack` proces aan de remote kant. -Bijvoorbeeld, stel dat je `git push origin master` uitvoert in je project, en `origin` is gedefinieerd als een URL dat het SSH protocol gebruikt. Git start het `send-pack` proces, wat een verbinding initieert, via SSH, naar je server. Het probeert een commando op de remote server uit te voeren met behulp van een SSH aanroep die er ongeveer zo uit ziet: +Bijvoorbeeld, stel dat je `git push origin master` uitvoert in je project en `origin` is gedefinieerd als een URL dat het SSH protocol gebruikt. Git start het `send-pack` proces, wat een SSH verbinding initieert naar de server. Het probeert een commando op de remote server uit te voeren met behulp van een SSH aanroep die er ongeveer zo uit ziet: $ ssh -x git@github.com "git-receive-pack 'schacon/simplegit-progit.git'" 005bca82a6dff817ec66f4437202690a93763949 refs/heads/master report-status delete-refs 003e085bb3bcb608e1e84b2432f8ecbe6306e7e7 refs/heads/topic 0000 -Het `git-receive-pack` commando antwoord onmiddellijk met één regel voor iedere referentie die het momenteel heeft – in dit geval alleen de `master` branch en zijn SHA. De eerste regel bevat ook een lijst van de mogelijkheden van de server (in dit geval, `report-status` en `delete-refs`). +Het `git-receive-pack` commando antwoordt onmiddellijk met één regel voor iedere referentie die het momenteel heeft; in dit geval alleen de `master` branch en zijn SHA. De eerste regel bevat ook een lijst van de mogelijkheden van de server (hier: `report-status` en `delete-refs`). -Iedere regel begint met een hexadecimale waarde van 4 bytes, die specificeert hoe lang de rest van de regel is. Je eerste regel begint met 005b, wat 91 in hex is, wat betekend dat er nog 91 bytes over zijn op deze regel. De volgende regel begint met 003e, wat 62 is, zodat je de overgebleven 62 bytes leest. De volgende regel is 0000, wat betekent dat de server klaar is met het tonen van zijn referenties. +Iedere regel begint met een hexadecimale waarde van 4 bytes, die specificeert hoe lang de rest van de regel is. Je eerste regel begint met 005b, wat 91 in hex is, wat betekent dat er nog 91 bytes over zijn op deze regel. De volgende regel begint met 003e, wat 62 is, waarna je de overgebleven 62 bytes leest. De volgende regel is 0000, wat betekent dat de server klaar is met het tonen van zijn referenties. -Nu dat het de status van de server weet, bepaalt je `send-pack` proces welke commits dat het heeft, die de server nog niet heeft. Voor iedere referentie die deze push zal vernieuwen, verteld het `send-pack` het `receive-pack` proces die informatie. Bijvoorbeeld, als je de `master` branch vernieuwt en een `experiment` branch toevoegt, zou het `send-pack` antwoord er zo uit kunnen zien: +Nu de status van de server bekend is, bepaalt het `send-pack` proces welke commits het heeft die de server nog niet heeft. Voor iedere referentie die deze push zal vernieuwen, geeft het `send-pack` die informatie aan het `receive-pack` door. Bijvoorbeeld, als je de `master` branch vernieuwt en een `experiment` branch toevoegt, zou het `send-pack` antwoord er zo uit kunnen zien: 0085ca82a6dff817ec66f44342007202690a93763949 15027957951b64cf874c3557a0f3547bd83b3ff6 refs/heads/master report-status 00670000000000000000000000000000000000000000 cdfdb42577e2506715f8cfeacdbabc092bf63e8d refs/heads/experiment 0000 -Een SHA-1 waarde met alleen '0' betekent dat er nog niets was – omdat je de experiment referentie toevoegt. Als je een referentie aan het verwijderen was, zou je het tegenovergestelde zien: allemaal '0' aan de rechterkant. +Een SHA-1 waarde met alleen '0' betekent dat er nog niets was; omdat je de experiment referentie toevoegt. Als je een referentie aan het verwijderen was, zou je het tegenovergestelde zien: allemaal '0'en aan de rechterkant. -Git stuurt een regel voor iedere referentie die je vernieuwt, met de oude SHA, de nieuwe SHA en de referentie die vernieuwd wordt. De eerste regel bevat ook de mogelijkheden van de client. Vervolgens upload de client een packfile met alle objecten die de server nog niet heeft. Als laatste antwoord de server met een succes (of mislukking) indicatie: +Git stuurt een regel voor iedere referentie die je vernieuwt met de oude SHA, de nieuwe SHA en de referentie die vernieuwd wordt. De eerste regel bevat ook de mogelijkheden van de client. Vervolgens uploadt de client een packfile met alle objecten die de server nog niet heeft. Als laatste antwoordt de server met een indicatie van succes (of mislukking): 000Aunpack ok #### Gegevens downloaden #### -Op het moment dat je gegevens download zijn de `fetch-pack` en `upload-pack` processen betrokken. De client start een `fetch-pack` proces dat verbinding maakt met een `upload-pack` proces aan de remote kant om te onderhandelen welke gegevens gestuurd moeten worden. +Zodra je gegevens downloadt zijn de `fetch-pack` en `upload-pack` processen erbij betrokken. De client start een `fetch-pack` proces dat verbinding maakt met een `upload-pack` proces aan de remote kant om te onderhandelen welke gegevens opgehaald moeten worden. -Er zijn verschillende manieren om het `upload-pack` proces op de remote repository te starten. Je kunt het uitvoeren via SSH, op dezelfde manier als het `receive-pack` proces. Je kunt het proces ook starten via de Git daemon, die standaard op poort 9418 luistert. Het `fetch-pack` proces stuurt gegevens, die er zo uitzien voor de daemon na het maken van de verbinding: +Er zijn verschillende manieren om het `upload-pack` proces op de remote repository te starten. Je kunt het uitvoeren via SSH, zoals bij het `receive-pack` proces. Je kunt het proces ook starten via de Git daemon, die standaard op poort 9418 luistert. Het `fetch-pack` proces stuurt gegevens, naar de daemon na het maken van de verbinding die er zo uitzien: 003fgit-upload-pack schacon/simplegit-progit.git\0host=myserver.com\0 -Het begint met de 4 bytes die specificeren hoeveel gegevens er volgen, daarna het commando gevolgd door een null byte, en dan de hostname van de server gevolgd door een laatste null byte. De Git daemon bekijkt of dat commando uitgevoerd kan worden, dat het repository bestaat en dat het publieke permissies heeft. Als alles OK is, dan start het het `upload-pack` proces en geeft hier het verzoek aan door. +Het begint met de 4 bytes die specificeren hoeveel gegevens er volgen, daarna het commando gevolgd door een null byte, en dan de hostname van de server gevolgd door een laatste null byte. De Git daemon bekijkt of dat commando uitgevoerd kan worden, dat de repository bestaat en dat het publieke permissies heeft. Als alles OK is, dan start het het `upload-pack` proces en geeft het verzoek hier aan door. -Als je de fetch via SSH dper, voert het `fetch-pack` in plaats daarvan zoiets als dit uit: +Als je de fetch via SSH doet, voert het `fetch-pack` in plaats daarvan zoiets als dit uit: $ ssh -x git@github.com "git-upload-pack 'schacon/simplegit-progit.git'" @@ -748,24 +748,24 @@ In beide gevallen stuurt `upload-pack`, nadat `fetch-pack` verbinding gemaakt he 003e085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 refs/heads/topic 0000 -Dit komt erg overeen met waarmee `receive-pack` antwoord, maar de mogelijkheden zijn verschillend. Daarnaast stuurt het de HEAD referentie zodat de client weet wat er uitgechecked moet worden als dit een kloon is. +Dit komt erg overeen met hoe `receive-pack` antwoordt, maar de mogelijkheden zijn verschillend. Daarnaast stuurt het de HEAD referentie zodat de client weet wat er uitgechecked moet worden als dit een kloon is. -Op dit punt kijkt het `fetch-pack` proces naar welk objecten dat het heeft en antwoord met de objecten die het nodig heeft door "want" te sturen, gevolgd door de SHA die het wil. Het stuurt al de objecten die het al heeft met "have" en dan de SHA. Aan het einde van deze lijst, schrijft het "done" om het `upload-pack` proces te starten met het sturen van de packfile van de gegevens die het nodig heeft: +Op dit punt kijkt het `fetch-pack` proces naar welke objecten het heeft en antwoordt met de objecten die het nodig heeft door "want" te sturen, gevolgd door de SHA die het wil hebben. Het stuurt al de objecten die het al heeft met "have" en dan de SHA. Aan het einde van deze lijst schrijft het "done" om het `upload-pack` proces te laten beginnen met het sturen van de packfile met de gegevens die het nodig heeft: 0054want ca82a6dff817ec66f44342007202690a93763949 ofs-delta 0032have 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 0000 0009done -Dat is een basaal geval van de overdrachtsprotocollen. In meer complexe gevallen ondersteunt de client `multi_ack` of `side-band` mogelijkheden; maar dit voorbeeld toont je de basale heen en weer gang die gebruikt wordt door de slimme protocol processen. +Dat is een basaal geval van de overdrachtsprotocollen. In meer complexe gevallen ondersteunt de client `multi_ack` of `side-band` mogelijkheden; maar dit voorbeeld toont je het basale over en weer dat gebruikt wordt door de slimme protocol processen. ## Onderhoud en het herstellen van gegevens ## -Soms moet je wat opruimen – een repository compacter maken, een geïmporteerd repository opruimen, of verloren werk terughalen. Deze sectie zal deze scenario's doorlopen. +Soms moet je wat opruimen: een repository compacter maken, een geïmporteerd repository opruimen of verloren werk terughalen. Deze paragraaf zal deze scenario's behandelen. ### Onderhoud ### -Soms voert Git automatisch een commando genaamd "auto gc" uit. Het merendeel van de tijd doet dit commando niets. Maar, als je teveel losse objecten (objecten die niet in een packfile zitten) of teveel packfiles hebt, dan lanceert Git een volledig `git gc` commando. Het `gc` staat voor garbage collect (afval ophalen), en het commando doet een aantal zaken: het haalt alle losse objecten op en stopt ze in packfiles, het voegt packfiles samen in één grote packfile, en het verwijderd objecten die niet bereikbaar zijn vanuit een commit en die een paar maanden oud zijn. +Geregeld voert Git automatisch een commando genaamd "auto gc" uit. Het merendeel van de tijd doet dit commando niets. Maar, als je teveel losse objecten (objecten die niet in een packfile zitten) of teveel packfiles hebt, lanceert Git een uitgebreid `git gc` commando. Het `gc` staat voor garbage collect (afval ophalen), en het commando doet een aantal zaken: het haalt alle losse objecten op en stopt ze in packfiles, het voegt packfiles samen in één grote packfile, en het verwijdert objecten die niet bereikbaar zijn vanuit een commit en een paar maanden oud zijn. Je kunt auto gc als volgt handmatig uitvoeren: @@ -773,7 +773,7 @@ Je kunt auto gc als volgt handmatig uitvoeren: Nogmaals, over het algemeen doet dit commando niets. Je moet ongeveer 7.000 losse objecten of meer dan 50 packfiles hebben voordat Git een echt gc commando start. Je kunt deze grenzen respectievelijk met de `gc.auto` en `gc.autopacklimit` configuratie instellingen aanpassen. -Het andere ding dat `gc` zal doen is je referenties in een enkel bestand inpakken. Stel dat je repository de volgende branches en tags bevat: +Het andere dat `gc` zal doen is je referenties in een enkel bestand inpakken. Stel dat je repository de volgende branches en tags bevat: $ find .git/refs -type f .git/refs/heads/experiment @@ -781,7 +781,7 @@ Het andere ding dat `gc` zal doen is je referenties in een enkel bestand inpakke .git/refs/tags/v1.0 .git/refs/tags/v1.1 -Als je `git gc` uitvoert, zul je deze bestanden niet langer in de `refs` map hebben. Git zal ze omwille van efficiëntie in een bestand genaamd `.git/packed-refs` stoppen, dat er zo uitziet: +Als je `git gc` uitvoert, zul je deze bestanden niet langer in de `refs` directory hebben. Git zal ze omwille van efficiëntie in een bestand genaamd `.git/packed-refs` stoppen, dat er zo uitziet: $ cat .git/packed-refs # pack-refs with: peeled @@ -791,13 +791,13 @@ Als je `git gc` uitvoert, zul je deze bestanden niet langer in de `refs` map heb 9585191f37f7b0fb9444f35a9bf50de191beadc2 refs/tags/v1.1 ^1a410efbd13591db07496601ebc7a059dd55cfe9 -Als je een referentie vernieuwt, zal Git dit bestand niet aanpassen maar een nieuw bestand in `refs/heads` schrijven. Om de juiste SHA voor een gegeven referentie te krijgen, kijkt Git voor die referentie in de `refs` map en kijkt in het `packed-res` bestand als terugval optie. Hoe dan ook, als je een referentie niet in de `refs` map kunt vinden, zit het waarschijnlijk in je `packed-refs` bestand. +Als je een referentie vernieuwt, zal Git dit bestand niet aanpassen maar een nieuw bestand in `refs/heads` schrijven. Om de juiste SHA voor een gegeven referentie te krijgen, kijkt Git voor die referentie in de `refs` directory en kijkt in het `packed-res` bestand als terugval optie. Hoe dan ook, als je een referentie niet in de `refs` directory kunt vinden zit het waarschijnlijk in je `packed-refs` bestand. -Let op de laatste regel van het bestand, die begint met een `^`. Dit betekent dat de tag die er direct boven staat een beschreven tag is, en dat die regel e commit is waar de beschreven tag naar wijst. +Let op de laatste regel van het bestand, die begint met een `^`. Dit betekent dat de tag die er direct boven staat een beschreven tag is, en dat die regel de commit is waar de beschreven tag naar wijst. ### Gegevens herstellen ### -Op een bepaald punt in je reis met Git, kun je per ongeluk wel eens een commit verliezen. Over het algemeen gebeurd dit omdat je een branch force-delete, waar werk op zat, en het blijkt dat je de branch uit eindelijk toch wou hebben; of je hard-reset een branch, waarmee je commits achterlaat waar je iets van wou hebben. Stel dat dit gebeurd, hoe kun je dan je commits terug halen? +Op een bepaald punt in je reis met Git, is het mogelijk dat je per ongeluk eens een commit verliest. Over het algemeen gebeurt dit omdat je een branch waar werk op zat geforceerd verwijdert, en het blijkt dat je de branch achteraf toch had willen houden. Of je hard-reset een branch, waarmee je commits achterlaat waar je iets van wilde hebben. Stel dat dit gebeurt, hoe kun je dan je commits terug halen? Hier is een voorbeeld dat een hard-reset doet naar een oudere commit op de master branch in je test repository, en de verloren commits terug haalt. Laten we eerst eens bekijken waar je repository op dit punt staat: @@ -817,15 +817,15 @@ Nu verplaats je de `master` branch terug naar de middelste commit: cac0cab538b970a37ea1e769cbbde608743bc96d second commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit -Je bent nu effectief de twee bovenste commits kwijt – je hebt geen branch vanwaar deze commits bereikbaar zijn. Je moet de laatste commit SHA vinden en dan een branch toevoegen die daar naar wijst. De truc is om de laatste commit SHA te vinden – het is toch niet alsof je die onthouden hebt, toch? +Je bent nu effectief de twee bovenste commits kwijt: je hebt geen branch van waaruit deze commits bereikbaar zijn. Je moet de laatste commit SHA vinden en dan een branch toevoegen die daar naar wijst. De truuk is om de laatste commit SHA te vinden, het is toch niet waarschijnlijk dat je die onthouden hebt, toch? -Vaak is de snelste manier een tool genaamd `git reflog` te gebruiken. Terwijl je werkt slaat Git stilletjes op wat je HEAD is, iedere keer als je die wijzigt. Iedere keer dat je commit, of van branch veranderd wordt de reflog vernieuwd. Het reflog wordt ook vernieuwd door het `git update-ref` commando, wat nog een reden is om het te gebruiken in plaats van gewoon de SHA's naar je ref bestanden te schrijven, zoals we beschreven hebben in de "Git References" sectie eerder in dit hoofdstuk. Je kunt op ieder moment zien waar je geweest bent, door `git reflog` uit te voeren. +Vaak is de snelste manier een tool genaamd `git reflog` te gebruiken. Terwijl je werkt slaat Git stilletjes op wat je HEAD is, iedere keer als je die wijzigt. Elke keer als je commit, of van branch verandert wordt de reflog vernieuwd. Het reflog wordt ook vernieuwd door het `git update-ref` commando, wat nog een reden is om het te gebruiken in plaats van gewoon de SHA's naar je ref bestanden te schrijven, zoals we beschreven hebben in de "Git Referenties" paragraaf eerder in dit hoofdstuk. Je kunt op ieder moment zien waar je geweest bent, door `git reflog` uit te voeren. $ git reflog 1a410ef HEAD@{0}: 1a410efbd13591db07496601ebc7a059dd55cfe9: updating HEAD ab1afef HEAD@{1}: ab1afef80fac8e34258ff41fc1b867c702daa24b: updating HEAD -Hier kunnen we de twee commits zien die we uitgechecked hadden, maar er is niet veel informatie aanwezig. Om dezelfde informatie op een veel bruikbaarder manier kunnen we `git log -g` uitvoeren, wat je een normale log uitvoer geeft voor je reflog. +Hier kunnen we de twee commits zien die we uitgechecked hadden, maar er is hier niet veel informatie aanwezig. Om dezelfde informatie op een veel bruikbaarder manier te zien kunnen we `git log -g` uitvoeren, wat je een normale log uitvoer geeft voor je reflog. $ git log -g commit 1a410efbd13591db07496601ebc7a059dd55cfe9 @@ -854,13 +854,13 @@ Het ziet er naar uit dat de onderste commit degene is die je kwijt bent geraakt, cac0cab538b970a37ea1e769cbbde608743bc96d second commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit -Vet – nu heb je een branch genaamd `recover-branch` die staat op het punt waar je `master` branch was, waarmee de eerste twee commits weer bereikbaar zijn. -Vervolgens, stel dat je verloren commit om een of andere reden niet in de reflog stond – je kunt dat simuleren door `recover-branch` te verwijderen en het reflog te wissen. Nu zijn de eerste twee commits niet meer bereikbaar door wat dan ook: +Vet – nu heb je een branch genaamd `recover-branch` die staat op het punt waar je `master` branch eerder was, waarmee de eerste twee commits weer bereikbaar zijn. +Vervolgens, stel dat je verloren commit om een of andere reden niet in de reflog stond; je kunt dat simuleren door `recover-branch` te verwijderen en het reflog te wissen. Nu zijn de eerste twee commits nergens meer mee te bereiken: $ git branch –D recover-branch $ rm -Rf .git/logs/ -Omdat de reflog gegevens bewaard worden in de `.git/logs/` map, heb je effectief geen reflog. Hoe kun je die commit op dat punt herstellen? Één manier is om gebruik te maken van het `git fsck` tool, wat de integriteit van je gegevensbank controleert. Als je het met de `--full` optie uitvoert, dan toont het je alle objecten waarnaar niet gewezen wordt door een ander object: +Omdat de reflog gegevens bewaard worden in de `.git/logs/` directory, heb je nu effectief geen reflog meer. Hoe kun je die commit op dat punt herstellen? Één manier is om gebruik te maken van het `git fsck` tool, wat de integriteit van je gegevensbank controleert. Als je het met de `--full` optie uitvoert, dan toont het je alle objecten waarnaar niet gewezen wordt door een ander object: $ git fsck --full dangling blob d670460b4b4aece5915caf5c68d12f560a9fe3e4 @@ -868,17 +868,17 @@ Omdat de reflog gegevens bewaard worden in de `.git/logs/` map, heb je effectief dangling tree aea790b9a58f6cf6f2804eeac9f0abbe9631e4c9 dangling blob 7108f7ecb345ee9d0084193f147cdad4d2998293 -In dit geval, kun je je vermiste commit zien na de hangende commit. Je kunt het op dezelfde manier herstellen, door een branch toe te voegen die naar die SHA wijst. +In dit geval, kun je de vermiste commit zien na de hangende ('dangling') commit. Je kunt het op dezelfde manier herstellen, door een branch te maken die naar die SHA wijst. ### Objecten verwijderen ### -Er zijn een hoop geweldige dingen aan Git, maar één eigenschap die problemen kan geven is het feit dat `git clone` de hele historie van het project download, inclusief alle versies van alle bestanden. Dat is geen probleem als het hele ding broncode is, omdat Git zeer geoptimaliseerd is om die gegevens optimaal te comprimeren. Maar, als iemand op een bepaald punt in de geschiedenis een enkel enorm bestand heeft toegevoegd, zal iedere kloon voor altijd gedwongen worden om dat grote bestand te downloaden, zelfs als het uit het project was verwijderd in de volgende commit. Omdat het bereikbaar is vanuit de geschiedenis, zal het er altijd zijn. +Er zijn een hoop geweldige dingen aan Git, maar één eigenschap die problemen kan geven is het feit dat `git clone` de hele historie van het project download, inclusief alle versies van alle bestanden. Dat is geen probleem als het hele project broncode is, omdat Git zeer geoptimaliseerd is om die gegevens optimaal te comprimeren. Maar, als iemand op een bepaald punt in de geschiedenis een enorm bestand heeft toegevoegd, zal iedere kloon voor altijd gedwongen worden om dat grote bestand te downloaden, zelfs als het uit het project was verwijderd in de eerstvolgende commit. Omdat het bereikbaar is vanuit de geschiedenis, zal het er altijd zijn. -Dit kan een groot probleem zijn als je Subversion of Perforce repositories omzet naar Git. Omdat je niet de hele geschiedenis download in die systemen, zal dit soort toevoeging een paar gevolgen met zich meebrengen. Als je een import vanuit een ander systeem deed, of om een andere reden vindt dat je repository veel groter is dan het zou moeten zijn, kun je hier zien hoe je grote objecten kunt vinden en verwijderen. +Dit kan een groot probleem zijn als je Subversion of Perforce repositories converteert naar Git. Omdat je niet de hele geschiedenis download in die systemen, zal dit soort toevoeging een paar consequenties met zich meebrengen. Als je een import vanuit een ander systeem deed, of om een andere reden vindt dat je repository veel groter is dan het zou moeten zijn, kun je hier zien hoe je grote objecten kunt vinden en verwijderen. -Let op: deze techniek is verwoestend voor je commit geschiedenis. Het herschrijft ieder commit object stroomafwaarts vanaf de eerste boom die je moet aanpassen om een referentie naar een groot bestand te verwijderen. Als je dit meteen na een import doet, voordat iemand werk is gaan baseren op de commit, dan is er niets aan de hand – anders moet je alle bijdragers waarschuwen dat ze hun werk op je nieuwe commits moeten rebasen. +Let op: deze techniek is destructief voor je commit geschiedenis. Het herschrijft ieder commit object stroomafwaarts vanaf de eerste tree die je moet aanpassen om een referentie naar een groot bestand te verwijderen. Als je dit meteen na een import doet, voordat iemand werk is gaan baseren op de commit, dan is er niets aan de hand; anders moet je alle bijdragers waarschuwen dat ze hun werk op je nieuwe commits moeten rebasen. -Om het te demonstreren, voeg je een groot bestand in je test repository toe, verwijderd het in de volgende commit, vindt het, en verwijderd het permanent uit het repository. Als eerste, voeg je een groot object toe aan je geschiedenis: +Om het te demonstreren, voeg je een groot bestand in je test repository toe, verwijdert het in de volgende commit, vindt het, en verwijdert het daarna permanent uit de repository. Als eerste, voeg je een groot object toe aan je geschiedenis: $ curl http://kernel.org/pub/software/scm/git/git-1.6.3.1.tar.bz2 > git.tbz2 $ git add git.tbz2 @@ -887,7 +887,7 @@ Om het te demonstreren, voeg je een groot bestand in je test repository toe, ver 1 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 git.tbz2 -Oops — je wou geen enorme tarball toevoegen aan je project. Laten we er snel vanaf zien te komen: +Oeps — je wilde geen enorme tarball toevoegen aan je project. Laten we het maar snel verwijderen: $ git rm git.tbz2 rm 'git.tbz2' @@ -916,27 +916,27 @@ Je kunt het `count-objects` commando gebruiken om snel te zien hoeveel ruimte je prune-packable: 0 garbage: 0 -Op de `size-pack` regel staat de grootte van je packfiles in kilobytes, dus je gebruikt 2Mb. Voor de laatste commit gebruikte je bijna 2K – dus het is duidelijk dat het verwijderen van het bestand uit de vorige commit, het niet uit je geschiedenis verwijderd heeft. Iedere keer als iemand dit repository kloont, zullen ze de volle 2Mb moeten klonen alleen maar om dit kleine project te krijgen, omdat jij per ongeluk een groot bestand toegevoegd hebt. Laten we het kwijtraken. +Op de `size-pack` regel staat de grootte van je packfiles in kilobytes, dus je gebruikt 2Mb. Voor de laatste commit gebruikte je bijna 2K; het is duidelijk dat het verwijderen van het bestand uit de vorige commit, het niet uit je geschiedenis verwijderd heeft. Iedere keer als iemand dit repository kloont, zullen ze de volle 2Mb moeten klonen alleen maar om dit kleine project te krijgen, omdat jij per ongeluk een groot bestand toegevoegd hebt. Laten we het kwijtraken. -Eerst moet je het vinden. In dit geval weet je al welk bestand het is. Maar stel dat je het niet wist; hoe zou je kunnen vinden welk bestand of bestanden zoveel ruimte in beslag nemen? Als je `git gc` uitvoert zitten alle objecten in een packfile; je kunt de grote bestanden identificeren door een ander sanitaire voorzieningen commando genaamd `git verify-pack` uit te voeren en te sorteren op het derde veld in de uitvoer, wat de bestandsgrootte is. Je kunt het ook door het `tail` commando leiden omdat je alleen geïnteresseerd bent in het laatste paar grote bestanden. +Eerst moet je het vinden. In dit geval weet je al welk bestand het is. Maar stel dat je het niet wist; hoe zou je kunnen vinden welk bestand of bestanden zoveel ruimte in beslag nemen? Als je `git gc` uitvoert zitten alle objecten in een packfile; je kunt de grote bestanden identificeren door een ander plumbing commando genaamd `git verify-pack` uit te voeren en te sorteren op het derde veld in de uitvoer, wat de bestandsgrootte is. Je kunt het ook door het `tail` commando leiden omdat je alleen geïnteresseerd bent in het laatste paar grote bestanden. $ git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3 e3f094f522629ae358806b17daf78246c27c007b blob 1486 734 4667 05408d195263d853f09dca71d55116663690c27c blob 12908 3478 1189 7a9eb2fba2b1811321254ac360970fc169ba2330 blob 2056716 2056872 5401 -Het grote object staat aan het einde: 2 Mb. Om uit te vinden welk bestand het is, zul je het `rev-list` commando gebruiken, wat je kort gebruikt hebt in Hoofdstuk 7. Als je `--objects` meegeeft aan `ref-list`, toont het alle commit SHA's en ook de blob SHA's met de bestandspaden die er aan geassocieerd zijn. Je kunt dit gebruiken om de naam van je blob te vinden: +Het grote object staat aan het einde: 2 Mb. Om uit te vinden welk bestand het is, zul je het `rev-list` commando gebruiken, wat je eventjes gebruikt hebt in Hoofdstuk 7. Als je `--objects` meegeeft aan `ref-list`, toont het alle commit SHA's en ook de blob SHA's met de bestandspaden die er mee geassocieerd zijn. Je kunt dit gebruiken om de naam van je blob te vinden: $ git rev-list --objects --all | grep 7a9eb2fb 7a9eb2fba2b1811321254ac360970fc169ba2330 git.tbz2 -Nu moet je dit bestand verwijderen van alle bomen in je verleden. Je kunt eenvoudig zien welke commits dit bestand aangepast hebben: +Nu moet je dit bestand verwijderen uit alle trees in je verleden. Je kunt eenvoudig zien welke commits dit bestand aangepast hebben: $ git log --pretty=oneline --branches -- git.tbz2 da3f30d019005479c99eb4c3406225613985a1db oops - removed large tarball 6df764092f3e7c8f5f94cbe08ee5cf42e92a0289 added git tarball -Je moet alle commits die stroomafwaarts van `6df76` liggen om dit bestand volledig uit je Git geschiedenis te verwijderen. Omdat te doen gebuik je `filter-branch`, wat je in Hoofdstuk 6 gebruikt hebt: +Je moet alle commits die stroomafwaarts van `6df76` liggen herschrijven om dit bestand volledig uit je Git geschiedenis te verwijderen. Omdat te doen gebuik je `filter-branch`, wat je in Hoofdstuk 6 gebruikt hebt: $ git filter-branch --index-filter \ 'git rm --cached --ignore-unmatch git.tbz2' -- 6df7640^.. @@ -944,9 +944,9 @@ Je moet alle commits die stroomafwaarts van `6df76` liggen om dit bestand volled Rewrite da3f30d019005479c99eb4c3406225613985a1db (2/2) Ref 'refs/heads/master' was rewritten -De `--index-filter` optie is vergelijkbaar met de `--tree-filter` optie, die gebruikt is in Hoofdstuk 6, behalve dan dat in plaats van het doorgeven van een commando dat bestanden aanpast die uitgechecked staan op je schijf, pas je je staging gebied of index iedere keer aan. In plaats van een specifiek bestand steeds te verwijderen met zoiets als `rm file`, moet je het met `git rm --cached` verwijderen – je moet het uit de index verwijderen, niet van de schijf. Reden om het zo te doen is snelheid – omdat Git niet iedere versie hoeft uit te checken op je schijf voordat het je filter uitvoert, kan het proces vele, vele malen sneller gaan. Je kunt dezelfde taak uitvoeren met `--tree-filter` als je dat wil. De `--ignore-unmatch` optie op `git rm` verteld het niet te stoppen op een fout als het patroon dat je probeert te verwijderen niet aanwezig is. Als laatste zul je `filter-branch` vragen om je geschiedenis alleen vanaf de `6df7640` commit te herschrijven, omdat je weet dat dat de plaats is waar het probleem begon. Anders start het vanaf het begin en duurt het onnodig langer. +De `--index-filter` optie is vergelijkbaar met de `--tree-filter` optie, die gebruikt is in Hoofdstuk 6, met het verschil dat in plaats van het doorgeven van een commando dat bestanden aanpast die uitgechecked staan op je schijf, je het staging area of index iedere keer aanpast. In plaats van een specifiek bestand steeds te verwijderen met zoiets als `rm file`, moet je het met `git rm --cached` verwijderen; je moet het uit de index verwijderen, niet van de schijf. Reden om het zo te doen is snelheid: omdat Git niet iedere versie hoeft uit te checken op je schijf voordat het je filter uitvoert, kan het proces vele, vele malen sneller gaan. Je kunt dezelfde taak uitvoeren met `--tree-filter` als je dat wilt. De `--ignore-unmatch` optie op `git rm` vertelt het niet te stoppen op een fout als het patroon dat je probeert te verwijderen niet aanwezig is. Als laatste zal je `filter-branch` vragen om je geschiedenis alleen vanaf de `6df7640` commit te herschrijven, omdat je weet dat dat de plaats is waar het probleem begon. Anders start het vanaf het begin en duurt het onnodig langer. -Je geschiedenis zal niet langer een referentie bevatten naar dat bestand. Maar, je reflog en een nieuwe set refs die Git toevoegde toen je de `filter-branch` deed onder `.git/refs/original` bevatten het nog steeds, dus je moet die ook verwijderen en je gegevensbank opnieuw inpakken. Je moet alles dat een pointer naar die oude commits bevat kwijtraken voordat je opnieuw inpakt: +Je geschiedenis zal niet langer een referentie bevatten naar dat bestand. Maar, je reflog en een nieuwe set refs die Git toevoegde toen je de `filter-branch` deed onder `.git/refs/original` bevatten het nog steeds, dus je moet die ook verwijderen en je gegevensbank opnieuw inpakken. Je moet alles wat een pointer naar die oude commits bevat kwijtraken voordat je opnieuw inpakt: $ rm -Rf .git/refs/original $ rm -Rf .git/logs/ @@ -968,10 +968,10 @@ Laten we eens zien hoeveel ruimte je bespaard hebt. prune-packable: 0 garbage: 0 -De grootte van je ingepakte repository is omlaag gegaan naar 7 K, wat veel beter is dan 2 Mb. Je kunt aan de waarde van size zien dat het grootte object nog steeds in je losse bestanden staat, dus het is niet weg; maar het zal niet meer overgedragen worden bij een push of opvolgende kloon, wat het belangrijkste is. Als je het echt zou willen, kun je het object volledig verwijderen door `git prune --expire` uit te voeren. +De grootte van je ingepakte repository is omlaag gegaan naar 7 K, wat veel beter is dan 2 Mb. Je kunt aan de waarde van size zien dat het grote object nog steeds in je losse bestanden staat, dus het is niet weg; maar het zal niet meer overgedragen worden bij een push of opvolgende kloon, wat het belangrijkste is. Als je het echt zou willen, kun je het object volledig verwijderen door `git prune --expire` uit te voeren. ## Samenvatting ## -Je moet een goed begrip hebben van wat Git op de achtergrond doet en, tot een bepaalde hoogte, hoe het in elkaar gezet is. Dit hoofdstuk heeft een aantal sanitaire voorzieningen commando's beslagen – commando's die op een lager niveau zitten en eenvoudige zijn dan de porselein commando's waarover je in de rest van het boek geleerd hebt. Begrijpen hoe Git op een lager niveau werkt zou het makkelijker moeten maken om te begrijpen waarom het doet wat het doet en ook om je eigen applicaties te schrijven en hulp scripts om jouw specifieke werkwijze voor je te laten werken. +Je moet een goed begrip hebben van wat Git op de achtergrond doet en, tot een bepaalde hoogte, hoe het in elkaar gezet is. Dit hoofdstuk heeft een aantal plumbing commando's besproken – commando's die op een lager niveau zitten en eenvoudige zijn dan de porcelain commando's waarover je in de rest van het boek geleerd hebt. Begrijpen hoe Git op een lager niveau werkt zou het makkelijker moeten maken om te begrijpen waarom het doet wat het doet en ook om je eigen applicaties te schrijven en hulp scripts om jouw specifieke werkwijze voor je te laten werken. -Git is als een inhouds-toegankelijk bestandssysteem een zeer krachtig tool dat je eenvoudig als meer dan alleen een VCS kunt gebruiken. Ik hoop dat je je nieuwe kennis van de werking van Git kunt gebruiken om je eigen coole applicatie te bouwen met deze technologie en je op je gemak voelt bij het gebruik van Git op meer geavanceerde manieren. +Git is als een inhouds-toegankelijk bestandssysteem een zeer krachtig tool dat je eenvoudig als meer dan alleen een VCS kunt gebruiken. Ik hoop dat je deze nieuwe kennis van de werking van Git kunt gebruiken om je eigen coole applicatie te bouwen met deze technologie en dat je je prettig voelt bij het gebruik van Git op meer geavanceerde manieren.