Ricerca…
repo
Un git repository
è una struttura dati su disco che memorizza i metadati per un insieme di file e directory.
Vive nel file .git/
cartella del tuo progetto. Ogni volta che si impegnano i dati per git, vengono memorizzati qui. Inversamente, .git/
contiene ogni singolo commit.
La sua struttura di base è così:
.git/
objects/
refs/
Oggetti
git
è fondamentalmente un negozio di valore-chiave. Quando aggiungi dati a git
, crea un object
e usa l'hash SHA-1 del contenuto object
come chiave.
Pertanto, qualsiasi contenuto in git
può essere cercato dal suo hash:
git cat-file -p 4bb6f98
Esistono 4 tipi di Object
:
-
blob
-
tree
-
commit
-
tag
Testa rif
HEAD
è una speciale ref
. Punta sempre sull'oggetto corrente.
Puoi vedere dove punta attualmente controllando il file .git/HEAD
.
Normalmente, HEAD
punta a un'altra ref
:
$cat .git/HEAD
ref: refs/heads/mainline
Ma può anche puntare direttamente a un object
:
$ cat .git/HEAD
4bb6f98a223abc9345a0cef9200562333
Questo è ciò che è noto come un "head distaccato" - perché HEAD
non è attaccato al (indicando) qualsiasi ref
, ma piuttosto punta direttamente a un object
.
refs
Un ref
è essenzialmente un puntatore. È un nome che punta a un object
. Per esempio,
"master" --> 1a410e...
Sono memorizzati in `.git / refs / heads / in file di testo semplice.
$ cat .git/refs/heads/mainline
4bb6f98a223abc9345a0cef9200562333
Questo è comunemente ciò che vengono chiamati branches
. Tuttavia, noterai che in git
non esiste una cosa come un branch
: solo un ref
.
Ora, è possibile navigare git
puramente saltando intorno a objects
diversi direttamente dai loro hash. Ma questo sarebbe terribilmente inopportuno. Un ref
ti dà un nome conveniente per riferirsi agli objects
di. È molto più facile chiedere a git
di andare in un posto specifico per nome piuttosto che per hash.
Commit Object
Un commit
è probabilmente il tipo di object
più familiare per gli utenti git
, poiché è ciò che sono abituati a creare con i comandi git commit
.
Tuttavia, il commit
non contiene direttamente alcun file o dato modificato. Piuttosto, contiene principalmente metadati e puntatori ad altri objects
che contengono i contenuti effettivi del commit
.
Un commit
contiene alcune cose:
- hash di un
tree
- hash di un genitore
commit
- nome dell'autore / email, nome del committente / email
- messaggio di commit
Puoi vedere il contenuto di qualsiasi commit come questo:
$ git cat-file commit 5bac93
tree 04d1daef...
parent b7850ef5...
author Geddy Lee <[email protected]>
commiter Neil Peart <[email protected]>
First commit!
Albero
Una nota molto importante è che gli oggetti ad tree
memorizzano OGNI file nel progetto e memorizza interi file non diff. Ciò significa che ogni commit
contiene un'istantanea dell'intero progetto *.
* Tecnicamente, vengono memorizzati solo i file modificati. Ma questo è più un dettaglio di implementazione per l'efficienza. Dal punto di vista del design, un commit
dovrebbe essere considerato come contenente una copia completa del progetto .
Genitore
La linea parent
contiene un hash di un altro oggetto di commit
e può essere pensata come un "indicatore padre" che punta al "commit precedente". Questo forma implicitamente un grafico di commit noto come grafico di commit . In particolare, è un grafico aciclico diretto (o DAG).
Oggetto dell'albero
Un tree
rappresenta fondamentalmente una cartella in un filesystem tradizionale: contenitori nidificati per file o altre cartelle.
Un tree
contiene:
- 0 o più oggetti
blob
- 0 o più oggetti
tree
Proprio come è possibile utilizzare ls
o dir
per elencare il contenuto di una cartella, è possibile elencare il contenuto di un oggetto ad tree
.
$ git cat-file -p 07b1a631
100644 blob b91bba1b .gitignore
100644 blob cc0956f1 Makefile
040000 tree 92e1ca7e src
...
Puoi cercare i file in un commit
trovando prima l'hash tree
nel commit
e poi guardando tree
:
$ git cat-file commit 4bb6f93a
tree 07b1a631
parent ...
author ...
commiter ...
$ git cat-file -p 07b1a631
100644 blob b91bba1b .gitignore
100644 blob cc0956f1 Makefile
040000 tree 92e1ca7e src
...
Oggetto Blob
Un blob
contiene contenuti di file binari arbitrari. Comunemente, sarà un testo grezzo come il codice sorgente o un articolo del blog. Ma potrebbe essere altrettanto facilmente i byte di un file PNG o di qualsiasi altra cosa.
Se hai l'hash di un blob
, puoi guardare i suoi contenuti.
$ git cat-file -p d429810
package com.example.project
class Foo {
...
}
...
Ad esempio, puoi sfogliare un tree
come sopra, e poi guardare uno dei blobs
in esso.
$ git cat-file -p 07b1a631
100644 blob b91bba1b .gitignore
100644 blob cc0956f1 Makefile
040000 tree 92e1ca7e src
100644 blob cae391ff Readme.txt
$ git cat-file -p cae391ff
Welcome to my project! This is the readmefile
...
Creare nuovi commit
Il comando git commit
fa alcune cose:
- Crea
blobs
etrees
per rappresentare la directory del tuo progetto - archiviata in.git/objects
- Crea un nuovo oggetto
commit
con le informazioni dell'autore, il messaggio di commit e l'tree
radice del passaggio 1, anch'esso memorizzato in.git/objects
- Aggiorna
HEAD
ref in.git/HEAD
all'hash delcommit
appena creato
Ciò si traduce in una nuova istantanea del tuo progetto che viene aggiunto a git
che è connesso allo stato precedente.
Moving HEAD
Quando esegui il git checkout
su un commit (specificato da hash o ref) stai dicendo a git
di far apparire la tua directory di lavoro come quando è stata scattata l'istantanea.
- Aggiorna i file nella directory di lavoro in modo che corrispondano
tree
all'interno delcommit
- Aggiorna
HEAD
per puntare all'hash o al ref specificato
Spostando i ref in giro
Esecuzione di git reset --hard
sposta i riferimenti all'hash specificato / rif.
Spostando MyBranch
su b8dc53
:
$ git checkout MyBranch # moves HEAD to MyBranch
$ git reset --hard b8dc53 # makes MyBranch point to b8dc53
Creare nuovi Ref
Eseguire git checkout -b <refname>
creerà un nuovo riferimento che punta al commit
corrente.
$ cat .git/head
1f324a
$ git checkout -b TestBranch
$ cat .git/refs/heads/TestBranch
1f324a