Git est l'un des systèmes de gestion de version. Qu'est-ce qu'un système de gestion de version?
C'est un système avec des fonctions telles que. Ici, "l'historique des modifications" est
Désigne une série d'informations enregistrées par ordre chronologique.
En plus de Git, il existe CVS et Subversion comme systèmes de gestion de version, mais les fonctionnalités de Git sont les suivantes.
Tout d'abord, voyons comment git fonctionne en tant que coffre-fort de contenu. Tout d'abord, créez un dépôt git vide
% mkdir repo1
% cd repo1
% git init
Initialized empty Git repository in repo1/.git/
Créez un fichier appelé readme.txt, stockez son contenu dans le référentiel, écrasez le fichier avec d'autres contenus et stockez-le dans le référentiel.
% echo aaa > readme.txt
% git hash-object -w readme.txt
72943a16fb2c8f38f9dde202b7a70ccc19c52f34
% echo bbb > readme.txt
% git hash-object -w readme.txt
f761ec192d9f0dca3329044b96ebdb12839dbff6
% rm -f readme.txt
Le contenu du fichier stocké peut être récupéré à l'aide de la chaîne de caractères affichée lorsque la commande d'objet de hachage est exécutée en tant que clé.
% git cat-file -p 72943a16fb2c8f38f9dde202b7a70ccc19c52f34 > readme.txt
% cat readme.txt
aaa
% git cat-file -p f761ec192d9f0dca3329044b96ebdb12839dbff6 > readme.txt
% cat readme.txt
bbb
Ce qu'il faut noter
C'est. Lorsque la partie inachevée devient possible, il devient possible de conserver l'historique des modifications, mais avant de le regarder, "quelque chose que je ne comprends pas" est la valeur de hachage SHA1 du contenu du fichier (+ α). Assurons-nous qu'il y en a.
hash-object.py
import hashlib
import sys
if len(sys.argv) != 2:
print("usage: %s file" % sys.argv[0])
sys.exit(-1)
try:
f = open(sys.argv[1])
except Exception:
print("open %s failed" % sys.argv[1])
sys.exit(-1)
data = f.read()
sha1 = hashlib.sha1("blob %d" % len(data) + "\0" + data).hexdigest()
print(sha1)
Ce programme Python
Calcule la valeur de hachage SHA1 de la concaténation de et génère sa représentation hexadécimale. Quand je l'utilise réellement pour les deux contenus ci-dessus,
% echo aaa | python hash-object.py /dev/stdin
72943a16fb2c8f38f9dde202b7a70ccc19c52f34
% echo bbb | python hash-object.py /dev/stdin
f761ec192d9f0dca3329044b96ebdb12839dbff6
Et vous pouvez voir que le résultat du calcul correspond à la clé utilisée pour stocker le contenu précédemment (le contenu est stocké en utilisant la valeur de hachage SHA1 du contenu du fichier + α comme clé). À propos, la destination de stockage dans le référentiel de contenu est
% find .git/objects -type f
.git/objects/72/943a16fb2c8f38f9dde202b7a70ccc19c52f34
.git/objects/f7/61ec192d9f0dca3329044b96ebdb12839dbff6
La valeur de hachage SHA1 est la concaténation du nom du répertoire et du nom du fichier. Si vous prenez la valeur SHA1 de ces fichiers eux-mêmes
% sha1sum `find .git/objects -type f`
cf6e4f80cfae36e20ae7eb1a90919ca48f59514b .git/objects/72/943a16fb2c8f38f9dde202b7a70ccc19c52f34
cdb05607e2e073287a81a908564d9d901ccdd687 .git/objects/f7/61ec192d9f0dca3329044b96ebdb12839dbff6
Et la valeur est différente. C'est parce que le contenu est compressé et stocké, par exemple.
decompress_sha1.py
import hashlib
import sys
import zlib
if len(sys.argv) != 2:
print("usage: %s git_object_file" % sys.argv[0])
sys.exit(-1)
path = sys.argv[1]
try:
f = open(path)
except Exception:
print("open %s failed" % path)
sys.exit(-1)
data = zlib.decompress(f.read())
sha1 = hashlib.sha1(data).hexdigest()
print("%s: %s" % (path, sha1))
Si vous calculez la valeur de hachage après la décompression à l'aide du programme
% for i in `find .git/objects -type f`; do python ../decompress_sha1.py $i; done
.git/objects/72/943a16fb2c8f38f9dde202b7a70ccc19c52f34: 72943a16fb2c8f38f9dde202b7a70ccc19c52f34
.git/objects/f7/61ec192d9f0dca3329044b96ebdb12839dbff6: f761ec192d9f0dca3329044b96ebdb12839dbff6
Vous pouvez voir qu'ils correspondent correctement (puisque les valeurs de hachage correspondent, on s'attend à ce que le contenu corresponde également).
J'ai vu comment stocker le contenu d'un fichier sous .git / objects /. Git stocke également les noms de fichiers et les informations de message de journal de validation dans un fichier sous .git / objects / appelé un objet Git.
Au moment de la création du référentiel, aucun objet n'est stocké.
% mkdir repo2
% cd repo2
% git init
Initialized empty Git repository in repo2/.git/
% ls .git
HEAD config hooks/ objects/
branches/ description info/ refs/
% find .git/objects -type f
Ajoutons un fichier à la zone de préparation avec git add.
% echo aaa > readme.txt
% git add readme.txt
% find .git/objects -type f
.git/objects/72/943a16fb2c8f38f9dde202b7a70ccc19c52f34
% ls .git
HEAD config hooks/ info/ refs/
branches/ description index objects/
Un objet a été ajouté et un fichier appelé index a été créé. Vous pouvez vérifier le contenu de l'objet Git avec git cat-file.
% git cat-file -t 729
fatal: Not a valid object name 729
% git cat-file -t 7294
blob
% git cat-file -s 7294
4
% wc -c readme.txt
4 readme.txt
% git cat-file -p 7294
aaa
% cat readme.txt
aaa
Comme moyen d'utiliser cat-file
-t
, c'est un objet blob qui stocke le contenu du fichier comme nous l'avons vu dans la section précédente.-s
et du contenu avec -p
, cela correspondait au contenu du fichier réel.Ensuite, écrivons les informations contenues dans l'index sous forme d'objet.
% git write-tree
580c73c39691399d09ad01152ad0a691ce80bccf
% find .git/objects -type f
.git/objects/58/0c73c39691399d09ad01152ad0a691ce80bccf
.git/objects/72/943a16fb2c8f38f9dde202b7a70ccc19c52f34
% git cat-file -t 580c
tree
% git cat-file -p 580c
100644 blob 72943a16fb2c8f38f9dde202b7a70ccc19c52f34 readme.txt
En ce moment,
580c
, a été stocké.Je comprends ça.
Ensuite, créez un répertoire et un fichier sous celui-ci et essayez git add.
% mkdir tmp
% echo bbb > tmp/bbb.txt
% git add tmp/bbb.txt
% find .git/objects -type f
.git/objects/58/0c73c39691399d09ad01152ad0a691ce80bccf
.git/objects/72/943a16fb2c8f38f9dde202b7a70ccc19c52f34
.git/objects/f7/61ec192d9f0dca3329044b96ebdb12839dbff6
% git cat-file -t f761
blob
% git cat-file -p f761
bbb
L'objet nouvellement ajouté est un objet blob qui contient le contenu de bbb.txt. Si vous écrivez à nouveau l'index en tant qu'objet dans cet état
% git write-tree
6434b2415497a42647800c7e828038a2fb6fbbaf
% find .git/objects -type f
.git/objects/58/0c73c39691399d09ad01152ad0a691ce80bccf
.git/objects/5c/40d98927de9cdb27df5b3a7bd4f7ee95dbfc85
.git/objects/64/34b2415497a42647800c7e828038a2fb6fbbaf
.git/objects/72/943a16fb2c8f38f9dde202b7a70ccc19c52f34
.git/objects/f7/61ec192d9f0dca3329044b96ebdb12839dbff6
% git cat-file -t 6434
tree
% git cat-file -p 6434
100644 blob 72943a16fb2c8f38f9dde202b7a70ccc19c52f34 readme.txt
040000 tree 5c40d98927de9cdb27df5b3a7bd4f7ee95dbfc85 tmp
% git cat-file -t 5c40
tree
% git cat-file -p 5c40
100644 blob f761ec192d9f0dca3329044b96ebdb12839dbff6 bbb.txt
ici,
580c
que nous avons vu précédemment reste intact580c
ou 6434
), vous pouvez identifier l'ensemble de fichiers à un certain moment.Tu peux voir ça.
J'ai écrit un analyseur d'arbre parce que c'était un gros problème.
parse_tree.py
import hashlib
import sys
import zlib
if len(sys.argv) != 2:
print("usage: %s git_object_file" % sys.argv[0])
sys.exit(-1)
try:
f = open(sys.argv[1])
except Exception:
print("open %s failed" % sys.argv[1])
sys.exit(-1)
data = zlib.decompress(f.read())
sha1 = hashlib.sha1(data).hexdigest()
eoh = data.find("\0")
if eoh < 0:
print("no end of header")
sys.exit(-1)
header = data[:eoh]
t, n = header.split(" ")
if len(data) - eoh - 1 != int(n):
print("size mismatch %d,%d" % (len(data) - eoh - 1, int(n)))
sys.exit(-1)
if t != "tree":
print("not tree: %s" % t)
sys.exit(-1)
dsize = hashlib.sha1().digest_size
ptr = eoh + 1
while ptr < len(data):
eorh = data.find("\0", ptr)
if eorh < 0:
print("no end of reference header")
sys.exit(-1)
mode, name = data[ptr:eorh].split(" ")
sha1_ = "".join(map(lambda x: "%02x" % ord(x), data[eorh+1:eorh+1+dsize]))
print("%s (%6s) %s" % (sha1_, mode, name))
ptr = eorh + 1 + dsize
% python parse_tree.py .git/objects/64/34b2415497a42647800c7e828038a2fb6fbbaf
72943a16fb2c8f38f9dde202b7a70ccc19c52f34 (100644) readme.txt
5c40d98927de9cdb27df5b3a7bd4f7ee95dbfc85 ( 40000) tmp
La structure de données de l'objet d'arborescence est en données compressées zlib (similaire à blob).
La partie contenu est
C'est une répétition de.
Maintenant que nous avons vu deux types d'objets, blob et tree, regardons l'objet de validation à la fin.
Créons un commit qui fait référence à l'objet d'arborescence 580c
.
% git commit-tree -m "initial commit" 580c
7a5c786478f17fd96b385c725c95d10fa74e4576
% ls .git/objects/7a/5c786478f17fd96b385c725c95d10fa74e4576
.git/objects/7a/5c786478f17fd96b385c725c95d10fa74e4576
% git cat-file -t 7a5c
commit
% git cat-file -p 7a5c
tree 580c73c39691399d09ad01152ad0a691ce80bccf
author Yoichi Nakayama <[email protected]> 1447772602 +0900
committer Yoichi Nakayama <[email protected]> 1447772602 +0900
initial commit
Ensuite, créons un commit qui fait référence à l'objet d'arborescence 6434
, avec cet objet de commit 7a5c
comme parent.
% git commit-tree -p 7a5c -m "second commit" 6434
88470d975c1875e2e03a46877c13dde9ed2fd1ea
% ls .git/objects/88/470d975c1875e2e03a46877c13dde9ed2fd1ea
.git/objects/88/470d975c1875e2e03a46877c13dde9ed2fd1ea
% git cat-file -t 8847
commit
% git cat-file -p 8847
tree 6434b2415497a42647800c7e828038a2fb6fbbaf
parent 7a5c786478f17fd96b385c725c95d10fa74e4576
author Yoichi Nakayama <[email protected]> 1447772754 +0900
committer Yoichi Nakayama <[email protected]> 1447772754 +0900
second commit
Si vous entrez la valeur de hachage de cet objet de validation dans le maître référencé par HEAD, Vous pouvez voir l'historique avec git log.
% cat .git/HEAD
ref: refs/heads/master
% echo 88470d975c1875e2e03a46877c13dde9ed2fd1ea > .git/refs/heads/master
% git log
commit 88470d975c1875e2e03a46877c13dde9ed2fd1ea
Author: Yoichi Nakayama <[email protected]>
Date: Wed Nov 18 00:05:54 2015 +0900
second commit
commit 7a5c786478f17fd96b385c725c95d10fa74e4576
Author: Yoichi Nakayama <[email protected]>
Date: Wed Nov 18 00:03:22 2015 +0900
initial commit
Vous pouvez maintenant voir l'historique que vous voyez normalement après git commit. Vous pouvez également donner à git diff la valeur de hachage de l'objet de validation cible pour voir la différence.
% git diff 7a5c 8847
diff --git a/tmp/bbb.txt b/tmp/bbb.txt
new file mode 100644
index 0000000..f761ec1
--- /dev/null
+++ b/tmp/bbb.txt
@@ -0,0 +1 @@
+bbb
La structure de données de l'objet de validation est la même que celle de l'objet blob, sauf qu'il commence par "commit", comme contenu.
Comprend.
Recommended Posts