./git/internals/objects-cntaddressing.txt

download original
From: Olaf Klischat <olaf.klischat@googlemail.com>
To: .....

Wir hatten doch neulich theoretisiert, dass beim Kopieren eines großen 
Verzeichnisses innerhalb eines Git-Repos (z.B. Verzeichnis "SITScope" 
bei uns) die Größe des Repos stark steigen (im Extremfall sich fast 
verdoppeln) müsste.

Ist aber nicht so.

$ git init objtest
Initialized empty Git repository in 
/home/olaf/doc/mydocs/git/test/objects/objtest/.git/
$ cd objtest/
objtest$ mkdir foo
objtest$ echo hello >foo/hello.txt
objtest$ echo world >foo/world.txt
objtest$ git add foo/
objtest$ git commit -m 'foo'
[master (root-commit) be1280a] foo
  2 files changed, 2 insertions(+), 0 deletions(-)
  create mode 100644 foo/hello.txt
  create mode 100644 foo/world.txt
objtest$
objtest$ git log
commit be1280ae26fac555ecf7f42bdff57fd17c111512
Author: Olaf Klischat <olaf.klischat@googlemail.com>
Date:   Fri Feb 24 03:07:46 2012 +0100

     foo
objtest$
objtest$ git rev-list --objects --all  #alle Objekte listen (commits, trees, blobs)
be1280ae26fac555ecf7f42bdff57fd17c111512
c699fe52a73816fcf2212911e0cd56c73202561a
88e38705fdbd3608cddbe904b67c731f3234c45b foo
ce013625030ba8dba906f756967f9e9ca394464a foo/hello.txt
cc628ccd10742baea8241c5924df992b5c019f71 foo/world.txt
objtest$
objtest$ git ls-tree 88e38705fdbd3608cddbe904b67c731f3234c45b 
#Spezialkommando zum Anzeigen von Tree-Objekten
100644 blob ce013625030ba8dba906f756967f9e9ca394464a	hello.txt
100644 blob cc628ccd10742baea8241c5924df992b5c019f71	world.txt
objtest$
objtest$ git show c699fe52a73816fcf2212911e0cd56c73202561a  #der Root-Tree
tree c699fe52a73816fcf2212911e0cd56c73202561a

foo/
objtest$ ##### Jetzt: Kopieren
objtest$ cp -rf foo foo2
objtest$ git add foo2
objtest$ git commit -m foo2
[master 8e88abc] foo2
  2 files changed, 2 insertions(+), 0 deletions(-)
  create mode 100644 foo2/hello.txt
  create mode 100644 foo2/world.txt
objtest$
objtest$ git rev-list --objects --all
8e88abc83ae71dbd48f5b0e8b71293cf4528de5e
be1280ae26fac555ecf7f42bdff57fd17c111512
e08505e42efa85422bf844b695a8c70d1ee6b8b1       #<- der neue Root-Tree (hieß oben noch c699fe52a7..)
88e38705fdbd3608cddbe904b67c731f3234c45b foo
ce013625030ba8dba906f756967f9e9ca394464a foo/hello.txt
cc628ccd10742baea8241c5924df992b5c019f71 foo/world.txt
c699fe52a73816fcf2212911e0cd56c73202561a
objtest$
objtest$ git ls-tree e08505e42efa85422bf844b695a8c70d1ee6b8b1
040000 tree 88e38705fdbd3608cddbe904b67c731f3234c45b	foo
040000 tree 88e38705fdbd3608cddbe904b67c731f3234c45b	foo2   #identische Kopie -> einfach im Tree 2 mal referenziert
objtest$
objtest$ #### foo2 ändern
objtest$
objtest$ echo blabla >foo2/quux.txt
objtest$ git add foo2/quux.txt
objtest$ git commit -m quux
[master a268e09] quux
  1 files changed, 1 insertions(+), 0 deletions(-)
  create mode 100644 foo2/quux.txt
objtest$
objtest$
objtest$ git rev-list --objects --all
a268e09da5baa2971942b2f112c350145b9a7060
8e88abc83ae71dbd48f5b0e8b71293cf4528de5e
be1280ae26fac555ecf7f42bdff57fd17c111512
575b2490cbfb0b9089671957e751166b9fc3eab8
88e38705fdbd3608cddbe904b67c731f3234c45b foo
ce013625030ba8dba906f756967f9e9ca394464a foo/hello.txt
cc628ccd10742baea8241c5924df992b5c019f71 foo/world.txt
c8aa6953028e7ecdb173ab9388e9f8f8709f865c foo2
d35e62fcf6d62331a2cd9ccc43ff200254959420 foo2/quux.txt
e08505e42efa85422bf844b695a8c70d1ee6b8b1
c699fe52a73816fcf2212911e0cd56c73202561a
objtest$
objtest$ git ls-tree 575b2490cbfb0b9089671957e751166b9fc3eab8 # neuer 
Root-Tree
040000 tree 88e38705fdbd3608cddbe904b67c731f3234c45b	foo     # jetzt 2 unterschiedliche Subtrees...
040000 tree c8aa6953028e7ecdb173ab9388e9f8f8709f865c	foo2
objtest$
objtest$ #beide Subtrees:
objtest$ git ls-tree 88e38705fdbd3608cddbe904b67c731f3234c45b
100644 blob ce013625030ba8dba906f756967f9e9ca394464a	hello.txt
100644 blob cc628ccd10742baea8241c5924df992b5c019f71	world.txt
objtest$
objtest$ git ls-tree c8aa6953028e7ecdb173ab9388e9f8f8709f865c
100644 blob ce013625030ba8dba906f756967f9e9ca394464a	hello.txt  #...aber hello.txt und world.txt immer noch geshared.
100644 blob d35e62fcf6d62331a2cd9ccc43ff200254959420	quux.txt
100644 blob cc628ccd10742baea8241c5924df992b5c019f71	world.txt
objtest$

objtest$ ## zu hello.txt binaer inhaltsgleiche Datei anlegen
objtest$
objtest$ echo hello >foo2/nochwas.txt
objtest$ git add foo2/nochwas.txt
objtest$
objtest$
objtest$ git commit -m 'nochwas'
[master bdba8f6] nochwas
  1 files changed, 1 insertions(+), 0 deletions(-)
  create mode 100644 foo2/nochwas.txt
objtest$
objtest$
objtest$ git rev-list --objects --all
bdba8f62d065e001db96ecbd43a53f551c5c738e
a268e09da5baa2971942b2f112c350145b9a7060
8e88abc83ae71dbd48f5b0e8b71293cf4528de5e
be1280ae26fac555ecf7f42bdff57fd17c111512
1057d9f535e2b028e0161aaf0c3d9c38db531625
88e38705fdbd3608cddbe904b67c731f3234c45b foo
ce013625030ba8dba906f756967f9e9ca394464a foo/hello.txt
cc628ccd10742baea8241c5924df992b5c019f71 foo/world.txt
4364b665637df1132fd5af153c8cc2d983899491 foo2
d35e62fcf6d62331a2cd9ccc43ff200254959420 foo2/quux.txt
575b2490cbfb0b9089671957e751166b9fc3eab8
c8aa6953028e7ecdb173ab9388e9f8f8709f865c foo2
e08505e42efa85422bf844b695a8c70d1ee6b8b1
c699fe52a73816fcf2212911e0cd56c73202561a
objtest$
objtest$ git ls-tree 88e38705fdbd3608cddbe904b67c731f3234c45b
100644 blob ce013625030ba8dba906f756967f9e9ca394464a	hello.txt
100644 blob cc628ccd10742baea8241c5924df992b5c019f71	world.txt
objtest$ git ls-tree 4364b665637df1132fd5af153c8cc2d983899491
100644 blob ce013625030ba8dba906f756967f9e9ca394464a	hello.txt
100644 blob ce013625030ba8dba906f756967f9e9ca394464a	nochwas.txt 100644 
blob d35e62fcf6d62331a2cd9ccc43ff200254959420	quux.txt
100644 blob cc628ccd10742baea8241c5924df992b5c019f71	world.txt
objtest$ #=>Inhalt nur einmal gespeichert.

D.h. das ganze ist so quasi content-adressed. Eine Datei (Blob) wird als 
Hash über ihren Inhalt (und nur den Inhalt -- Dateiname/Pfad stehen in 
übergeordneten Tree-Objekten) adressiert. Solange sich der Inhalt nicht 
ändert, wird intern kein neues Objekt angelegt.

  
back to internals

(C) 1998-2017 Olaf Klischat <olaf.klischat@gmail.com>