first quick and dirty translation from german translation using omegat
[gitmagic.git] / szl / secrets.txt
blobd6da30d096552ade65d71c892b764304bae2cbe0
1 == Uchylenie tajemnicy ==
3 Rzućmy spojrzenie pod maskę silnika i wytłumaczymy w jaki sposób Git realizuje swoje cuda. Nie będę wchodził w szczegóły. Dla pogłębienia tematu odsyłam na http://www.kernel.org/pub/software/scm/git/docs/user-manual.html[anielskojęzychny podręcznik użytkownika].
5 === Niewidzialność ===
7 Jak to możliwe, że Git jest taki niepostrzeżony? Zapominając na chwilę o sporadycznych 'commits' i 'merges', możesz pracować w sposób, jakby kontrola wersji w ogóle nie istniała. To znaczy - do czasu aż będzie ci potrzebna. A oto chodzi, byś był zadowolony z tego, że Git cały czas czuwa nad twoją pracą
9 Inne systemy kontroli wersji ciągle zmuszają cię do ciągłego borykania się z zagadnieniem samej kontroli i związanej z tym biurokracji.  Pliki mogą być zabezpieczone przed zapisem, aż do momentu gdy uda ci się poinformować centralny serwer o tym, że chciałabyś nad nimi popracować. Przy wzroście liczby użytkowników nawet najprostsze polecenia stają się wolne jak ślimak. Gdy tylko zniknie sieć lub centralny serwer praca staje.
11 W przeciwieństwie do tego, Git posiada kronikę całej swojej historii w podkatalogu .git twojego katalogu roboczego. Jest to twoja własna kopie całej historii, z którą mogłabyś pracować offline, aż do momentu gdy zechcesz wymienić dane z innymi. Posiadasz absolutną kontrolę nad losem twoich danych, ponieważ Git potrafi dla ciebie w każdej chwili odtworzyć zapamiętany poprzednio stan z właśnie podkatalogu .git.
13 === Integralność ===
15 Z kryptografią przez większość ludzi łączona jest poufność informacji, jednak równie ważnym jej celem jest zabezpieczenie danych. Właściwe zastosowanie kryptograficznych funkcji hashujących (funkcji skrótu) może uchronić przed nieumyślnym lub celowym zniszczeniem danych. 
17 Klucz hashujący SHA1 mogłabyś wyobrazić sobie jako składający się ze 160 bitów numer identyfikacyjny jednoznacznie opisujący dowolny łańcuch znaków, i który spotkasz w sowim życiu jeden jedyny raz. Nawet i więcej niż to: wszystkie łańcuchy znaków, jakie ludzkość przez wiele generacji stworzyła.
19 Sam klucz SHA1 też jest łańcuchem znaków w formie bajtów. Możemy generować klucze SHA1 z łańcuchów samych zawierających klucze SHA1. Ta prosta obserwacja okazała się niesamowicie pożyteczna: jeśli cię to zainteresowało poszukaj informacji na temat 'hash chains'. Zobaczymy później w jaki sposób wykorzystuje je Git dla zapewnienia produktywności i integralności danych.
21 Krótko mówiąc, Git przechowuje twoje dane w podkatalogu `.git/objects`, gdzie zamiast nazw plików znajdziesz numery identyfikacyjne.  Poprzez wykorzystanie tych numerów identyfikacyjnych jako nazwy plików razem z kilkoma innymi trikami związanymi z plikami blokującymi i znacznikami czasu, Git zamienia twój prosty system plików na produktywną i solidną bazę danych. 
23 === Inteligencja ===
25 Skąd Git wie o tym, że zmieniłaś nazwę jakiegoś pliku, jeśli nigdy go o tym wyraźnie nie poinformowałaś? Oczywiście, być może użyłaś polecenia *git mv*, jest to jednak to samo jakbyś użyła *git rm*, a następnie *git add*.
27 Git poszukuje heurystycznie zmian nazw w następujących po sobie wersjach kopii. Dodatkowo potrafi czasami nawet znaleźć całe bloki z kodem przenoszonym tam i z powrotem między plikami! Mimo iż wykonuje kawał dobrej roboty, a ta właściwość staje się coraz lepsza, nie potrafi niestety jeszcze poradzić sobie z wszystkimi możliwymi przypadkami. Jeśli to u ciebie nie działa, spróbuj poszukać opcji rozszerzonego rozpoznawania kopii, aktualizacja samego Gita, też może pomóc.
29 === Indeksowanie ===
31 Dla każdego kontrolowanego pliku, Git zapamiętuje informacje o jego wielkości, czasie utworzenia i czasie ostatniej edycji w pliku znanym nam jako index. By ustalić, czy nastąpiła jakaś zmiana, Git porównuje stan aktualny ze stanem zapamiętanym w indeksie. Jeśli dane te nie różnią się, Git może pominąć czytanie zawartości pliku.
33 Ponieważ sprawdzenie statusu pliku trwa dużo krócej niż jego całkowite wczytanie, to jeśli dokonałaś zmian tylko na kilku plikach Git zaktualizuje swój stan w mgnieniu oka. 
35 Stwierdziliśmy już wcześniej, że indeks jest przechowalnią (ang. staging area). Jak to możliwe, że stos informacji o statusie danych może być przechowalnią? Ponieważ polecenie 'add' transportuje pliki do bazy danych Git i aktualizuje informacje o ich statusie, podczas gdy polecenie 'commit' (bez opcji) tworzy commit tylko wyłącznie na podstawie informacji o statusie plików, ponieważ pliki te już się w tej bazie znajdują.
37 === Korzenie Git ===
39 Ten http://lkml.org/lkml/2005/4/6/121['Linux Kernel Mailing List' post] opisuje cały łańcuch zdarzeń, które inicjowały powstanie Git.  Cały post jest archeologicznie fascynującą stroną dla historyków zajmujących się Gitem.
41 === Obiektowa baza danych ===
43 Każda wersja twoich danych jest przechowywana w obiektowej bazie danych, która znajduje się w podkatalogu `.git/objects`. Inne miejsca w `.git/` posiadają mniej ważne dane, jak indeks, nazwy gałęzi ('branch'), tagi, logi,konfigurację, aktualną pozycję HEAD i tak dalej. Obiektowa baza danych jest prosta, mimo to jednak elegancka i jest źródłem siły Gita.
45 Każdy plik w `.git/objects` jest obiektem. Istnieją trzy rodzaje obiektów, które nas interesują:  'blob', 'tree' i 'commit'.
47 === Bloby ===
49 Na początek magiczna sztuczka. Wymyśl jakąś nazwę pliku, jakąkolwiek. W pustym katalogu:
52  $ echo sweet > TWOJA_NAZWA 
53  $ git init 
54  $ git add . 
55  $ find .git/objects -type f 
56  $ find .git/objects -type f 
58 Zobaczysz coś takiego: +.git/objects/aa/823728ea7d592acc69b36875a482cdf3fd5c8d+.
60 Skąd mogłem to wiedzieć, mimo iż nie znałem nazwy pliku? Ponieważ wartość klucza SHA1 dla:
62  "blob" SP "6" NUL "sweet" LF 
64 wynosi właśnie: aa823728ea7d592acc69b36875a482cdf3fd5c8d.  Przy czym SP to spacja, NUL - to bajt zerowy, a LF to znak nowej linii ('newline').  Możesz to skontrolować wpisując:
66  $ printf "blob 6\000sweet\n" | sha1sum 
68 Git pracuje asocjacyjnie (skojarzeniowo): dane nie są zapamiętywane na podstawie ich nazwy, tylko wartości ich własnego klucza SHA1 w pliku, który określamy mianem obiektu 'blob'. Klucz SHA1 możemy sobie wyobrazić jako niepowtarzalny numer identyfikacyjny zawartości pliku, co oznacza, że pliki adresowane są na podstawie ich zawartości. Początkowe `blob 6`, to jedynie adnotacja, która określa jedynie rodzaj obiektu i jego wielkość w bajtach, pozwala to na uproszczenie zarządzania wewnętrznego.
70 Przez to właśnie mogłem 'przepowiedzieć' wynik. Nazwa pliku nie ma znaczenia, jedynie jego zawartość służy do utworzenia obiektu 'blob'.
72 Pytasz się, a co w przypadku identycznych plików? Spróbuj dodać kopie twojej danej pod jakąkolwiek nazwą. Zawartość +.git/objects+ nie zmieni się, niezależnie ile kopii dodałaś. Git zapamięta zawartość pliku wyłącznie jeden raz.
74 Na marginesie, dane w +.git/objects+ są spakowane poprzez 'zlib', nie powinieneś otwierać ich bezpośrednio. Przefiltruj je najpierw przez http://www.zlib.net/zpipe.c[zpipe -d], albo wpisz: 
76  $ git cat-file -p aa823728ea7d592acc69b36875a482cdf3fd5c8d 
78 polecenie to pokaże ci zawartość obiektu jako tekst.
80 === 'Trees'  ===
82 Gdzie są więc nazwy plików? Przecież muszą być gdzieś zapisane. Podczas wykonywania 'commit' Git troszczy się o nazwy plików:
84  $ git commit # dodaj jakiś opis. 
85  $ find .git/objects -type f 
86  $ find .git/objects -type f 
88 Powinieneś ujrzeć teraz 3 obiekty. Tym razem nie jestem w stanie powiedzieć, jak nazywają się te dwa nowe pliki, ponieważ częściowo są zależne od nazwy jaką nadałeś plikom. Pójdźmy dalej, zakładając, że jedną z tych danych nazwałeś ``rose''. Jeśli nie, możesz zmienić opis, by wyglądał jakby był twój:
90  $ git filter-branch --tree-filter 'mv TWOJA_NAZWA rose' 
91  $ find .git/objects -type f
93 Powinnaś zobaczyć teraz plik +.git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9+, ponieważ jest to klucz SHA1 jego zawartości.
95 "tree" SP "32" NUL "100644 rose" NUL 0xaa823728ea7d592acc69b36875a482cdf3fd5c8d 
97 Sprawdź, czy plik na prawdę odpowiada powyższej zawartości przez polecenie:
99  $ echo 05b217bb859794d08bb9e4f7f04cbda4b207fbe9 | git cat-file --batch 
101 Za pomocą 'zpipe' łatwo sprawdzić klucz SHA1:
104  $ zpipe -d < .git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9 | sha1sum 
106 Sprawdzanie za pomocą 'cat-file' jest troszeczkę kłopotliwe, bo jego 'output' zawiera więcej niż tylko nieskomprymowany obiekt pliku.
108 Nasz plik to tak zwany obiekt 'tree': lista wyrażeń, na którą składają się rodzaj pliku, jego nazwa i jego klucz SHA1. W naszym przykładzie typ pliku to 100644, co oznacza, że `rose` jest plikiem zwykłym, natomiast klucz SHA1 odpowiada kluczowi SHA1 obiektu 'blob' zawierającego zawartość `rose`. Inne możliwe rodzaje plików to programy, linki symboliczne i katalogi. W ostatnim przypadku klucz SHA1 wskazuje na obiekt 'tree'.
110 Jeśli użyjesz polecenia 'filter-branch', otrzymasz stare objekty, które nie są już używane. Mimo iż automatycznie zostaną usunięte po upłynięciu okresu łaski, chcemy się ich pozbyć od zaraz, aby lepiej prześledzić następne przykłady.
112  $ rm -r .git/refs/original 
113  $ git reflog expire --expire=now --all 
114  $ git prune 
116 W prawdziwych projektach powinnaś unikać takich komend, ponieważ zniszczą zabezpieczone dane. Jeśli chcesz posiadać czyste repozytorium, to najlepiej załóż  nowy klon. Bądź też ostrożna przy bezpośredniej manipulacji +.git+: gdy równocześnie wykonywane jest polecenie Git i zgaśnie światło? Generalnie do kasowania referencji powinnaś używać *git update-ref -d*, nawet gdy ręczne usunięcie +ref/original+ jest dość bezpieczne.
118 === 'Commits' ===
120 Wytłumaczyliśmy dwa z trzech obiektów. Ten trzeci to obiekt 'commit' Jego zawartość jest zależna od opisu 'commit' jak i czasu jego wykonania. By wszystko do naszego przykładu pasowało, musimy trochę pokombinować.
122  $ git commit --amend -m Shakespeare # Zmień ten opis. 
123  $ git filter-branch --env-filter 'export GIT_AUTHOR_DATE="Fri 13 Feb 2009 15:31:30 -0800" GIT_AUTHOR_NAME="Alice" GIT_AUTHOR_EMAIL="alice@example.com" GIT_COMMITTER_DATE="Fri, 13 Feb 2009 15:31:30 -0800" GIT_COMMITTER_NAME="Bob" GIT_COMMITTER_EMAIL="bob@example.com"' # Zmanipuluj znacznik czasowy i nazwę autora. 
124  $ find .git/objects -type f 
125  $ find .git/objects -type f 
127 Powinieneś znaleźć +.git/objects/49/993fe130c4b3bf24857a15d7969c396b7bc187+, co odpowiada kluczowi SHA1 jego zawartości: 
129 "commit 158" NUL "tree 05b217bb859794d08bb9e4f7f04cbda4b207fbe9" LF "author Alice <alice@example.com> 1234567890 -0800" LF "committer Bob <bob@example.com> 1234567890 -0800" LF LF "Shakespeare" LF 
131 Jak i w poprzednich przykładach możesz użyć 'zpipe' albo 'cat-file' by to sprawdzić.
133 To jest pierwszy 'commit', przez to nie posiada matczynych 'commits'. Następujące 'commits' będą zawsze zawierać przynajmniej jedną linikę identyfikującą rodzica.
135 === Nie do odróżnienia od magii ===
137 Tajemnice Gita wydają się być proste. Wygląda to jak połączenie kilku skryptów, troszeczkę kodu C i w przeciągu kilku godzin jesteśmy gotowi: zmiksowanie podstawowych operacji na systemie danych obliczenia SHA1, przyprawione danymi blokującymy i synchronizacją dla stabilności. W sumie można by tak opisać najwcześniejsze wersje Gita. Tym niemniej, abstrahując od udanych trików pakujących, by oszczędnie odnosić się z pamięcią i udanych trików indeksujących by zaoszczędzić czas, wiemy jak Git sprawnie przemienia system danych i bazę danych, co jest optymalne dla kontroli wersji.
139 Przyjmijmy, gdy jakikolwiek plik w obiektowej bazie danych ulegnie zniszczeniu poprzez błąd nośnika, to jego SHA1 nie będzie zgadzać się z jego zawartością, co od razu wskaże nam problem. Poprzez tworzenie kluczy SHA1 z kluczy SHA1 innych objektów, osiągniemy integralność danych na wszystkich poziomach. 'Commits' są elementarne, do znaczy, 'commit' nie potrafi zapamiętać jedynie części zmian: klucz SHA1 'commit' możemy obliczyć i zapamiętać dopiero po tym gdy zapamiętane zostały wszystkie obiekty 'tree', 'blob' i rodziców 'commit'. Obiektowa baza dynch jest odporna na nieoczekiwane przerwy, jak na przykład przerwanie dostawy prądu.
141 Możemy przetrwać nawet podstępnego przeciwnika. Wyobraź sobie, ktoś ma zamiar zmienić treść jakiegoś pliku, która leży w jakiejś starszej wersji projektu. By sprawić pozory, że baza danych wygląda nienaruszona musiałby zmienić klucze SHA1 korespondujących obiektów, ponieważ plik zawiera teraz zmieniony sznur znaków.  To znaczy również, że musiałabyś zmienić każdy klucz obiektu 'tree', które ją referują oraz w wyniku tego wszystkie klucze 'commits' zawierające obiekty 'tree' dodatkowo do pochodnych tych 'commits'. Oznacza to również, że klucz oficjalnego HEAD różni się od klucza HEAD manipulowanego repozytorium. Wystarczy teraz prześledzić ścieżkę różniących się kluczy SHA1, odnaleźć okaleczony plik, jak i 'commit' w którym po raz pierwszy wystąpił.
143 Krótko mówiąc, dopuki reprezentujące ostatni commit 20 bajtów są zabezpieczone, sfałszowanie repozytorium Gita nie jest możliwe.
145 A co ze sławnymi możliwościami Gita? 
146 'Branching'?  'Merging'?  'Tags'?  To szczegół. Aktualny HEAD przetrzymywany jest w pliku +.git/HEAD+, która posiada klucz SHA1 ostatniego 'commit'. Klucz SHA1 zostaje aktualizowany podczas wykonania 'commit', tak samo jak i przy wielu innych poleceniach. 'branches' to prawie to samo, są plikami zapamiętanymi w +.git/refs/heads+. 'Tags' również, znajdziemy je w +.git/refs/tags+, są one jednak aktualizowane poprzez serię innych poleceń.