-
1. Ćvod
-
2. ZƔklady prƔce se systƩmem Git
-
3. VÄtve v systĆ©mu Git
- 3.1 VÄtve v kostce
- 3.2 ZĆ”klady vÄtvenĆ a sluÄovĆ”nĆ
- 3.3 SprĆ”va vÄtvĆ
- 3.4 Postupy pÅi prĆ”ci s vÄtvemi
- 3.5 VzdĆ”lenĆ© vÄtve
- 3.6 PÅesklĆ”dĆ”nĆ
- 3.7 ShrnutĆ
-
4. Git na serveru
- 4.1 Protokoly
- 4.2 ZprovoznÄnĆ Gitu na serveru
- 4.3 GenerovĆ”nĆ veÅejnĆ©ho klĆÄe SSH
- 4.4 NastavenĆ serveru
- 4.5 DƩmon Git
- 4.6 Chytrý HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Možnosti hostovĆ”nĆ u tÅetĆ strany
- 4.10 ShrnutĆ
-
5. Distribuovaný Git
-
6. GitHub
-
7. Git Tools
- 7.1 Revision Selection
- 7.2 Interactive Staging
- 7.3 Stashing and Cleaning
- 7.4 Signing Your Work
- 7.5 Searching
- 7.6 Rewriting History
- 7.7 Reset Demystified
- 7.8 Advanced Merging
- 7.9 Rerere
- 7.10 LadÄnĆ v systĆ©mu Git
- 7.11 Submodules
- 7.12 Bundling
- 7.13 Replace
- 7.14 Credential Storage
- 7.15 ShrnutĆ
-
8. Customizing Git
- 8.1 Git Configuration
- 8.2 Atributy Git
- 8.3 Git Hooks
- 8.4 An Example Git-Enforced Policy
- 8.5 ShrnutĆ
-
9. Git a ostatnà systémy
- 9.1 Git as a Client
- 9.2 Migrating to Git
- 9.3 ShrnutĆ
-
10. Git Internals
- 10.1 Plumbing and Porcelain
- 10.2 Git Objects
- 10.3 Git References
- 10.4 BalĆÄkovĆ© soubory
- 10.5 The Refspec
- 10.6 PÅenosovĆ© protokoly
- 10.7 SprƔva a obnova dat
- 10.8 Environment Variables
- 10.9 ShrnutĆ
-
A1. Appendix A: Git in Other Environments
- A1.1 Graphical Interfaces
- A1.2 Git in Visual Studio
- A1.3 Git in Eclipse
- A1.4 Git in Bash
- A1.5 Git in Zsh
- A1.6 Git in Powershell
- A1.7 ShrnutĆ
-
A2. Appendix B: Embedding Git in your Applications
- A2.1 Command-line Git
- A2.2 Libgit2
- A2.3 JGit
-
A3. Appendix C: Git Commands
- A3.1 Setup and Config
- A3.2 Getting and Creating Projects
- A3.3 Basic Snapshotting
- A3.4 Branching and Merging
- A3.5 Sharing and Updating Projects
- A3.6 Inspection and Comparison
- A3.7 Debugging
- A3.8 Patching
- A3.9 Email
- A3.10 External Systems
- A3.11 Administration
- A3.12 Plumbing Commands
10.2 Git Internals - Git Objects
Git Objects
Git je obsahovÄ adresovatelný systĆ©m souborÅÆ.
VýbornÄ.
A co to znamenĆ”?
ZnamenĆ” to, že v jĆ”dru systĆ©mu Git se nachĆ”zĆ jednoduchĆ© ĆŗložiÅ”tÄ dat, ke kterĆ©mu lze pÅistupovat pomocĆ klĆÄÅÆ.
Můžete do nÄj vložit jakýkoli obsah a na oplĆ”tku dostanete klĆÄ, který můžete kdykoli v budoucnu použĆt k vyzvednutĆ obsahu.
Abychom to pÅedvedli, můžete použĆt nĆzkoĆŗrovÅový pÅĆkaz hash-object
, který vezme urÄitĆ” data, uložà je v adresĆ”Åi .git
a vrĆ”tĆ vĆ”m klĆÄ, pod nĆmž jsou tato data uložena.
VytvoÅme nejprve nový repozitÔŠGit. Můžeme se pÅesvÄdÄit, že je adresÔŠobjects
prÔzdný:
$ git init test
Initialized empty Git repository in /tmp/test/.git/
$ cd test
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
$ find .git/objects -type f
Git inicializoval adresÔŠobjects
a vytvoÅil v nÄm podadresĆ”Åe pack
a info
, nenajdeme tu vÅ”ak žÔdnĆ© skuteÄnĆ© soubory.
Nynà můžete uložit kousek textu do databÔze Git:
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4
Parametr -w
sdÄluje pÅĆkazu hash-object
, aby objekt uložil. Bez parametru by vĆ”m pÅĆkaz jen sdÄlil, jaký klĆÄ by byl pÅidÄlen.
--stdin
tells the command to read the content from stdin; if you donāt specify this, hash-object
expects a file path at the end.
Výstupem pÅĆkazu je 40znakový otisk kontrolnĆho souÄtu (checksum hash).
This is the SHA-1 hash ā a checksum of the content youāre storing plus a header, which youāll learn about in a bit.
NynĆ se můžete podĆvat, jak Git vaÅ”e data uložil:
$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
VidĆte, že v adresĆ”Åi objects
pÅibyl nový soubor.
This is how Git stores the content initially ā as a single file per piece of content, named with the SHA-1 checksum of the content and its header.
The subdirectory is named with the first 2 characters of the SHA-1, and the filename is the remaining 38 characters.
Obsah můžete ze systĆ©mu Git zase vytĆ”hnout, k tomu sloužà pÅĆkaz cat-file
.
Tento pÅĆkaz je nÄco jako Å”výcarský nůž k prohlĆženĆ objektÅÆ Git.
PÅidĆ”te-li k pÅĆkazu cat-file
parametr -p
, ÅĆkĆ”te mu, aby zjistil typ obsahu a pÅehlednÄ vĆ”m ho zobrazil:
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content
NynĆ tedy umĆte vložit do systĆ©mu Git urÄitý obsah a ten potĆ© zase vytĆ”hnout. Totéž můžete udÄlat takĆ© s obsahem v souborech. Na souboru můžete napÅĆklad provĆ”dÄt jednoduchĆ© verzovĆ”nĆ. VytvoÅte nový soubor a uložte jeho obsah do svĆ© databĆ”ze:
$ echo 'version 1' > test.txt
$ git hash-object -w test.txt
83baae61804e65cc73a7201a7252750c76066a30
Poté do souboru zapiŔte nový obsah a znovu ho uložte:
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
VaÅ”e databĆ”ze obsahuje dvÄ novĆ© verze souboru a poÄĆ”teÄnĆ obsah, který jste do nĆ vložili:
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
Soubor nynà můžete vrÔtit do prvnà verze:
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
$ cat test.txt
version 1
Nebo do druhƩ verze:
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
$ cat test.txt
version 2
But remembering the SHA-1 key for each version of your file isnāt practical; plus, you arenāt storing the filename in your system ā just the content.
Tento typ objektu se nazývÔ blob.
ZadĆ”te-li pÅĆkaz cat-file -t
v kombinaci s klĆÄem SHA-1 objektu, Git vĆ”m sdÄlĆ jeho typ, aÅ„ se jednĆ” o jakýkoli objekt Git.
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
blob
Tree Objects
The next type weāll look at is the tree, which solves the problem of storing the filename and also allows you to store a group of files together. Git uklĆ”dĆ” obsah podobným zpÅÆsobem jako systĆ©m souborÅÆ UNIX, jen trochu jednoduÅ”eji. VeÅ”kerý obsah se uklĆ”dĆ” v podobÄ objektÅÆ typu strom a blob. Stromy odpovĆdajĆ položkĆ”m v adresĆ”Åi UNIX a bloby vĆcemĆ©nÄ odpovĆdajĆ i-uzlÅÆm nebo obsahÅÆm souborÅÆ. Jeden objekt stromu obsahuje jednu nebo vĆce položek stromu, z nichž každĆ” obsahuje ukazatel SHA-1 na blob nebo podstrom s asociovaným režimem, typem a nĆ”zvem souboru. For example, the most recent tree in a project may look something like this:
$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
Syntaxe master^{tree}
urÄuje objekt stromu, na nÄjž ukazuje poslednĆ revize vÄtve master
.
Notice that the lib
subdirectory isnāt a blob but a pointer to another tree:
$ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb
Conceptually, the data that Git is storing is something like this:

You can fairly easily create your own tree.
Git normally creates a tree by taking the state of your staging area or index and writing a series of tree objects from it.
Proto chcete-li vytvoÅit objekt stromu, musĆte ze vÅ”eho nejdÅĆve pÅipravit soubory k zapsĆ”nĆ, a vytvoÅit tak index.
To create an index with a single entry ā the first version of your test.txt
file ā you can use the plumbing command update-index
.
You use this command to artificially add the earlier version of the test.txt
file to a new staging area.
You must pass it the --add
option because the file doesnāt yet exist in your staging area (you donāt even have a staging area set up yet) and --cacheinfo
because the file youāre adding isnāt in your directory but is in your database.
K tomu vÅ”emu pÅidĆ”te režim, SHA-1 a nĆ”zev souboru:
$ git update-index --add --cacheinfo 100644 \
83baae61804e65cc73a7201a7252750c76066a30 test.txt
In this case, youāre specifying a mode of 100644
, which means itās a normal file.
Other options are 100755
, which means itās an executable file; and 120000
, which specifies a symbolic link.
The mode is taken from normal UNIX modes but is much less flexible ā these three modes are the only ones that are valid for files (blobs) in Git (although other modes are used for directories and submodules).
NynĆ můžete použĆt pÅĆkaz write-tree
, jĆmž zapĆÅ”ete stav oblasti pÅipravovaných zmÄn neboli indexu do objektu stromu.
No -w
option is needed ā calling write-tree
automatically creates a tree object from the state of the index if that tree doesnāt yet exist:
$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt
Můžete si takĆ© ovÄÅit, že jde skuteÄnÄ o objekt stromu:
$ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
tree
Youāll now create a new tree with the second version of test.txt
and a new file as well:
$ echo 'new file' > new.txt
$ git update-index test.txt
$ git update-index --add new.txt
Your staging area now has the new version of test.txt
as well as the new file new.txt
.
Uložte tento strom (zaznamenĆ”nĆm stavu oblasti pÅipravených zmÄn neboli indexu do objektu stromu) a prohlĆ©dnÄte si výsledek:
$ git write-tree
0155eb4229851634a0f03eb265b69f5a2d56f341
$ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
Notice that this tree has both file entries and also that the test.txt
SHA-1 is the āversion 2ā SHA-1 from earlier (1f7a7a
).
Just for fun, youāll add the first tree as a subdirectory into this one.
Stromy můžete do oblasti pÅipravených zmÄn naÄĆst pÅĆkazem read-tree
.
V tomto pÅĆpadÄ můžete naÄĆst existujĆcĆ strom jako podstrom do oblasti pÅipravených zmÄn pomocĆ parametru --prefix
, který zadĆ”te k pÅĆkazu read-tree
:
$ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git write-tree
3c4e9cd789d88d8d89c1073707c3585e41b0e614
$ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614
040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
If you created a working directory from the new tree you just wrote, you would get the two files in the top level of the working directory and a subdirectory named bak
that contained the first version of the test.txt
file.
You can think of the data that Git contains for these structures as being like this:

Commit Objects
MĆ”te vytvoÅeny tÅi stromy oznaÄujĆcĆ rÅÆznĆ© snĆmky vaÅ”eho projektu, jež chcete sledovat. PÅÆvodnĆho problĆ©mu jsme se vÅ”ak stĆ”le nezbavili: musĆte si pamatovat vÅ”echny tÅi hodnoty SHA-1, abyste mohli snĆmky znovu vyvolat. You also donāt have any information about who saved the snapshots, when they were saved, or why they were saved. Toto jsou zĆ”kladnĆ informace, kterĆ© obsahuje objekt revize.
Pro vytvoÅenĆ objektu revize zavolejte pÅĆkaz commit-tree
a zadejte jeden SHA-1 stromu a eventuĆ”lnĆ objekty revize, kterĆ© mu bezprostÅednÄ pÅedchĆ”zely.
ZaÄnÄte prvnĆm stromem, který jste zapsali:
$ echo 'first commit' | git commit-tree d8329f
fdf4fc3344e67ab068f836878b6c4951e3b15f3d
You will get a different hash value because of different creation time and author data.
Replace commit and tag hashes with your own checksums further in this chapter.
NynĆ se můžete podĆvat na novÄ vytvoÅený objekt revize. Použijte pÅĆkaz cat-file
:
$ git cat-file -p fdf4fc3
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700
first commit
The format for a commit object is simple: it specifies the top-level tree for the snapshot of the project at that point; the author/committer information (which uses your user.name
and user.email
configuration settings and a timestamp); a blank line, and then the commit message.
Next, youāll write the other two commit objects, each referencing the commit that came directly before it:
$ echo 'second commit' | git commit-tree 0155eb -p fdf4fc3
cac0cab538b970a37ea1e769cbbde608743bc96d
$ echo 'third commit' | git commit-tree 3c4e9c -p cac0cab
1a410efbd13591db07496601ebc7a059dd55cfe9
VÅ”echny tÅi tyto objekty revizĆ ukazujĆ na jeden ze tÅĆ stromÅÆ snĆmku, který jste vytvoÅili.
Může se to zdĆ”t zvlÔŔtnĆ, ale nynĆ mĆ”te vytvoÅenu skuteÄnou historii revizĆ Git, kterou lze zobrazit pÅĆkazem git log
spuÅ”tÄným pro hodnotu SHA-1 poslednĆ revize:
$ git log --stat 1a410e
commit 1a410efbd13591db07496601ebc7a059dd55cfe9
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:15:24 2009 -0700
third commit
bak/test.txt | 1 +
1 file changed, 1 insertion(+)
commit cac0cab538b970a37ea1e769cbbde608743bc96d
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:14:29 2009 -0700
second commit
new.txt | 1 +
test.txt | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:09:34 2009 -0700
first commit
test.txt | 1 +
1 file changed, 1 insertion(+)
ƞasnƩ!
Youāve just done the low-level operations to build up a Git history without using any of the front end commands.
This is essentially what Git does when you run the git add
and git commit
commands ā it stores blobs for the files that have changed, updates the index, writes out trees, and writes commit objects that reference the top-level trees and the commits that came immediately before them.
These three main Git objects ā the blob, the tree, and the commit ā are initially stored as separate files in your .git/objects
directory.
Toto jsou vÅ”echny objekty v ukĆ”zkovĆ©m adresĆ”Åi spolu s komentĆ”Åem k tomu co obsahujĆ:
$ find .git/objects -type f
.git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2
.git/objects/1a/410efbd13591db07496601ebc7a059dd55cfe9 # commit 3
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a # test.txt v2
.git/objects/3c/4e9cd789d88d8d89c1073707c3585e41b0e614 # tree 3
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt v1
.git/objects/ca/c0cab538b970a37ea1e769cbbde608743bc96d # commit 2
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # 'test content'
.git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # tree 1
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt
.git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1
If you follow all the internal pointers, you get an object graph something like this:

UklÔdÔnà objektů
We mentioned earlier that a header is stored with the content. Letās take a minute to look at how Git stores its objects. Youāll see how to store a blob object ā in this case, the string āwhat is up, doc?ā ā interactively in the Ruby scripting language.
InteraktivnĆ režim Ruby spustĆte pÅĆkazem irb
:
$ irb
>> content = "what is up, doc?"
=> "what is up, doc?"
Git vytvoÅĆ zĆ”hlavĆ, kterĆ© bude zaÄĆnat typem objektu, jĆmž je v naÅ”em pÅĆpadÄ blob. PotĆ© vložà mezeru, za nĆž bude nĆ”sledovat velikost obsahu a na konec nulový byte:
>> header = "blob #{content.length}\0"
=> "blob 16\u0000"
Git vytvoÅĆ ÅetÄzec ze zĆ”hlavĆ a pÅÆvodnĆho obsahu a vypoÄĆtĆ” kontrolnĆ souÄet SHA-1 tohoto novĆ©ho obsahu.
V Ruby můžete hodnotu SHA-1 danĆ©ho ÅetÄzce spoÄĆtat tak, že pÅĆkazem require
pÅipojĆte knihovnu pro poÄĆtĆ”nĆ SHA1 a zavolĆ”te Digest::SHA1.hexdigest()
s daným ÅetÄzcem:
>> store = header + content
=> "blob 16\u0000what is up, doc?"
>> require 'digest/sha1'
=> true
>> sha1 = Digest::SHA1.hexdigest(store)
=> "bd9dbf5aae1a3862dd1526723246b20206e5fc37"
Git zkomprimuje nový obsah metodou zlib, kterĆ” je obsažena v knihovnÄ zlib.
Nejprve je tÅeba vyžÔdat si knihovnu a potĆ© na obsah spustit pÅĆkaz Zlib::Deflate.deflate()
:
>> require 'zlib'
=> true
>> zlib_content = Zlib::Deflate.deflate(store)
=> "x\x9CK\xCA\xC9OR04c(\xCFH,Q\xC8,V(-\xD0QH\xC9O\xB6\a\x00_\x1C\a\x9D"
Finally, youāll write your zlib-deflated content to an object on disk.
Youāll determine the path of the object you want to write out (the first two characters of the SHA-1 value being the subdirectory name, and the last 38 characters being the filename within that directory).
In Ruby, you can use the FileUtils.mkdir_p()
function to create the subdirectory if it doesnāt exist.
PotƩ zadejte File.open()
pro otevÅenĆ souboru a volĆ”nĆm write()
na vzniklý identifikĆ”tor souboru zapiÅ”te do souboru prĆ”vÄ zkomprimovaný (zlib) obsah:
>> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
=> ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37"
>> require 'fileutils'
=> true
>> FileUtils.mkdir_p(File.dirname(path))
=> ".git/objects/bd"
>> File.open(path, 'w') { |f| f.write zlib_content }
=> 32
Thatās it ā youāve created a valid Git blob object. All Git objects are stored the same way, just with different types ā instead of the string blob, the header will begin with commit or tree. A navĆc, zatĆmco obsahem blobu může být tĆ©mÄÅ cokoliv, obsah revize nebo stromu mĆ” velmi specifický formĆ”t.