-
1. Ξεκινώντας με το Git
-
2. Τα θεμελιώδη στοιχεία του Git
-
3. Διακλαδώσεις στο Git
-
4. Το Git στον διακομιστή
- 4.1 Τα πρωτόκολλα
- 4.2 Εγκατάσταση του Git σε διακομιστή
- 4.3 Δημιουργία δημόσιου κλειδιού SSH
- 4.4 Στήσιμο του διακομιστή
- 4.5 Δαίμονες του Git
- 4.6 Έξυπνο HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Επιλογές φιλοξενίας από τρίτους
- 4.10 Ανακεφαλαίωση
-
5. Κατανεμημένο Git
-
6. GitHub
-
7. Εργαλεία του Git
- 7.1 Επιλογή αναθεώρησης
- 7.2 Διαδραστική εργασία με το στάδιο καταχώρισης
- 7.3 stash και clean
- 7.4 Υπογραφή της δουλειάς μας
- 7.5 Αναζήτηση
- 7.6 Η ιστορία ξαναγράφεται
- 7.7 Απομυθοποίηση της reset
- 7.8 Συγχωνεύσεις για προχωρημένους
- 7.9 Rerere
- 7.10 Αποσφαλμάτωση με το Git
- 7.11 Λειτουργικές υπομονάδες
- 7.12 Δεμάτιασμα δεδομένων
- 7.13 Replace
- 7.14 Αποθήκευση διαπιστευτηρίων
- 7.15 Ανακεφαλαίωση
-
8. Εξατομίκευση του Git
-
9. Το Git και άλλα συστήματα
- 9.1 Το Git ως πελάτης
- 9.2 Μετανάστευση στο Git
- 9.3 Ανακεφαλαίωση
-
10. Εσωτερική λειτουργία του Git
- 10.1 Διοχετεύσεις και πορσελάνες
- 10.2 Αντικείμενα του Git
- 10.3 Αναφορές του Git
- 10.4 Πακετάρισμα αρχείων
- 10.5 Τα refspec
- 10.6 Πρωτόκολλα μεταφοράς
- 10.7 Διατήρηση και ανάκτηση δεδομένων
- 10.8 Μεταβλητές περιβάλλοντος
- 10.9 Ανακεφαλαίωση
-
A1. Appendix A: Το Git σε άλλα περιβάλλοντα
- A1.1 Γραφικές διεπαφές
- A1.2 Το Git στο Visual Studio
- A1.3 Git στο Eclipse
- A1.4 Το Git στο Bash
- A1.5 Το Git στο Zsh
- A1.6 Το Git στο Powershell
- A1.7 Ανακεφαλαίωση
-
A2. Appendix B: Ενσωμάτωση του Git στις εφαρμογές μας
- A2.1 Γραμμή εντολών Git
- A2.2 Libgit2
- A2.3 JGit
-
A3. Appendix C: Εντολές Git
- A3.1 Ρύθμιση και διαμόρφωση
- A3.2 Λήψη και δημιουργία έργων
- A3.3 Βασική λήψη στιγμιοτύπων
- A3.4 Διακλάδωση και συγχώνευση
- A3.5 Κοινή χρήση και ενημέρωση έργων
- A3.6 Επιθεώρηση και σύγκριση
- A3.7 Αποσφαλμάτωση
- A3.8 Επιθέματα
- A3.9 Ηλεκτρονικό ταχυδρομείο
- A3.10 Εξωτερικά Συστήματα
- A3.11 Διοίκηση
- A3.12 Εντολές διοχέτευσης
3.1 Διακλαδώσεις στο Git - Οι κλάδοι με λίγα λόγια
Σχεδόν κάθε VCS διαθέτει κάποιας μορφής υποστήριξη για διακλάδωση. Διακλάδωση ονομάζεται η απόκλιση από την κύρια γραμμή ανάπτυξης ώστε να μπορούμε να συνεχίσουμε την εργασία μας χωρίς να παρεμβαίνουμε στην κύρια γραμμή ανάπτυξης. Σε πολλά εργαλεία VCS, η διακλάδωση είναι μία σχετικά ακριβή διαδικασία με την έννοια ότι συχνά απαιτεί τη δημιουργία αντιγράφου του φακέλου στον οποίο βρίσκεται ο πηγαίος κώδικας, κάτι που μπορεί να είναι χρονοβόρο για μεγάλα έργα.
Κάποιοι θεωρούν ότι το μοντέλο διακλάδωσης του Git είναι το μεγαλύτερο προτέρημά του και πάντως είναι σίγουρα κάτι που κάνει το Git να ξεχωρίζει στην κοινότητα των VCS. Γιατί είναι τόσο ξεχωριστό; Ο τρόπος με τον οποίο το Git δημιουργεί διακλαδώσεις είναι απίστευτα ελαφρύς, κάτι που καθιστά τις εργασίες διακλάδωσης σχεδόν στιγμιαίες και τη μετάβαση από τον έναν κλάδο στον άλλο εξίσου γρήγορη. Σε αντίθεση με πολλά άλλα VCS, το Git ενθαρρύνει έναν τρόπο εργασίας κατά τον οποίο διακλαδώσεις και συγχωνεύσεις γίνονται συχνά, ακόμα και πολλές φορές μέσα σε μία ημέρα. Η κατανόηση και ευχέρεια στη χρήση αυτού του χαρακτηριστικού θα μας εφοδιάσει με ένα ισχυρό και μοναδικό εργαλείο, που μπορεί να αλλάξει ολοκληρωτικά τον τρόπο με τον οποίο αναπτύσσουμε εφαρμογές.
Οι κλάδοι με λίγα λόγια
Για να κατανοήσουμε πραγματικά τον τρόπο με τον οποίο το Git υλοποιεί τις διακλαδώσεις, πρέπει πρώτα να εξετάσουμε τον τρόπο με τον οποίο το Git αποθηκεύει τα δεδομένα.
Όπως έχει ήδη αναφερθεί στην ενότητα Ξεκινώντας με το Git, το Git δεν αποθηκεύει τα δεδομένα ως μία ακολουθία αλλαγών ή διαφορών αλλά ως μία ακολουθία στιγμιότυπων (snapshots).
Όταν κάνουμε κάνουμε μία υποβολή (commit), το Git αποθηκεύει ένα αντικείμενο υποβολής που περιέχει έναν δείκτη προς το στιγμιότυπο του περιεχομένου που έχει υποβληθεί. Αυτό το αντικείμενο περιέχει επίσης το όνομα και email του συγγραφέα, το μήνυμα που έχουμε πληκτρολογήσει καθώς και δείκτες προς την υποβολή ή τις υποβολές που προηγήθηκαν ακριβώς πριν από αυτήν την υποβολή (δηλαδή, τον γονιό ή τους γονείς): όταν ένα αρχείο υποβάλλεται για πρώτη φορά, τότε δεν έχει κανέναν γονιό· μία συνηθισμένη υποβολή έχει έναν γονιό, ενώ μία υποβολή που προέκυψε από τη συγχώνευση δύο ή περισσότερων κλάδων έχει περισσότερους από έναν γονιό.
Για να το συγκεριμενοποιήσουμε λίγο, ας υποθέσουμε ότι έχουμε έναν κατάλογο που περιέχει τρία αρχεία, τα οποία έχουμε προσθέσει στο στάδιο καταχώρισης και επιτελούμε υποβολή. Κατά την προσθήκη των αρχείων στο στάδιο καταχώρισης υπολογίζονται τα αθροίσματα ελέγχου (checksums) των αρχείων (με τον αλγόριθμο SHA-1, που αναφέρθηκε στην ενότητα Ξεκινώντας με το Git), αποθηκεύονται οι συγκεκριμένες εκδόσεις των αρχείων στο αποθετήριο Git (το Git ονομάζει αυτές τις εκδόσεις blobs [1] και προσθέτει τα αθροίσματα ελέγχου στην ενδιαμέση περιοχή.
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'
Όταν επιτελούμε την υποβολή, τρέχοντας την εντολή git commit
, το Git υπολογίζει ένα άθροισμα ελέγχου για καθέναν υποκατάλογο (στη συγκεκριμένη περίπτωση μόνο για τον βασικό κατάλογο του έργου) και αποθηκεύει αυτά τα αντικείμενα δενδροειδούς δομής στο αποθετήριο Git.
Στη συνέχεια το Git δημιουργεί ένα αντικείμενο υποβολής που περιέχει τα μεταδεδομένα και έναν δείκτη στη βάση του δένδρου του έργου, ώστε να μπορεί να επαναδημιουργήσει το στιγμιότυπο, όταν χρειαστεί.
Σε αυτό το στάδιο, το αποθετήριό μας περιέχει πέντε αντικείμενα: τρία blob για τα περιεχόμενα των αρχείων (ένα blob για κάθε αρχείο), μία δενδροειδή δομή που καταγράφει τα περιεχόμενα του καταλόγου και προσδιορίζει ποιο αρχείο αντιστοιχίζεται σε ποιο blob και ένα αντικείμενο commit που περιέχει τον δείκτη στον βασικό κατάλογο και όλα τα μεταδεδομένα της υποβολής.

Αν κάνουμε μερικές αλλαγές και επιτελέσουμε άλλη μία υποβολή, η επόμενη υποβολή αποθηκεύει έναν δείκτη στην ακριβώς προηγούμενη υποβολή.

Ένας κλάδος στο Git είναι απλά ένας δείκτης σε μία από αυτές τις υποβολές.
Το προεπιλεγμένο όνομα κλάδου στο Git είναι master
(κύριος κλάδος).
Όσο επιτελούμε υποβολές, δημιουργούμε έναν κύριο κλάδο που δείχνει στην τελευταία υποβολή που κάναμε. Κάθε φορά που υποβάλλουμε, ο κύριος κλάδος μετατοπίζεται αυτόματα.
Note
|
Ο “κύριος” κλάδος ( |

Δημιουργία νέου κλάδου
Τι γίνεται όταν δημιουργούμε έναν νέο κλάδο; Αυτό που συμβαίνει είναι ότι δημιουργείται ένα νέος δείκτης τον οποίο μπορούμε να μετακινούμε κατά βούληση.
Ας πούμε ότι δημιουργούμε έναν νέο κλάδο που ονομάζεται testing
.
Αυτό γίνεται με την εντολή git branch
:
$ git branch testing
Αυτή η εντολή δημιουργεί έναν νέο δείκτη στην ίδια υποβολή στην οποία βρισκόμαστε τώρα.

Πώς όμως γνωρίζει το Git σε ποιον κλάδο βρισκόμαστε τώρα;
Το γνωρίζει επειδή διατηρεί έναν ειδικό δείκτη που ονομάζεται HEAD
.
Ας σημειωθεί ότι αυτός ο δείκτης HEAD
είναι πολύ διαφορετικός από την έννοια του HEAD
με την οποία είστε ενδεχομένως εξοικειωμένοι σε άλλα VCS, όπως το Subversion ή το CVS.
Στο Git, αυτός είναι ένας δείκτης στον τοπικό κλάδο στον οποίο στον οποίο βρισκόμαστε αυτήν τη στιγμή.
Στη συγκεκριμένη περίπτωση, βρισκόμαστε ακόμα στον κλάδο master
.
Η εντολή git branch
απλά δημιούργησε έναν νέο κλάδο —δεν μετέβη σε αυτόν τον κλάδο.

Αυτό μπορούμε να το διαπιστώσουμε εύκολα τρέχοντας απλά την εντολή git log
με την επιλογή --decorate
, που παραθέτει πού δείχνουν οι δείκτες των κλάδων.
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) add feature #32 - ability to add new formats to the central interface
34ac2 Fixed bug #1328 - stack overflow under certain conditions
98ca9 The initial commit of my project
Βλέπουμε τους κλάδους master
και testing
που βρίσκονται δίπλα στην υποβολή f30ab
.
Μετάβαση από κλάδο σε κλάδο
Για να μεταβούμε σε έναν ήδη υπάρχοντα κλάδο, τρέχουμε την εντολή git checkout
.
Ας μεταβούμε στον νέο κλάδο testing
:
$ git checkout testing
Η εντολή αυτή μετατοπίζει τον δείκτη HEAD
ώστε να δείχνει στον κλάδο testing
.

HEAD
δείχνει στον τρέχοντα κλάδοΠοια είναι η σημασία αυτού του πράγματος; Ας κάνουμε ακόμα μία υποβολή:
$ vim test.rb
$ git commit -a -m 'made a change'

HEAD
μετακινείται ότι γίνεται μία υποβολήΑυτό είναι ενδιαφέρον, διότι τώρα ο νέος μας κλάδος testing
έχει προχωρήσει, αλλά ο κλάδος master
ακόμα δείχνει στην υποβολή που βρισκόμασταν όταν είχαμε τρέξει την εντολή git checkout
για να αλλάξουμε κλάδο. Ας επιστρέψουμε στον κλάδο master
:
$ git checkout master

HEAD
μετακινείται όταν εκτελούμε checkout
.Αυτή η εντολή έκανε δύο πράγματα:
Μετατόπισε τον δείκτη HEAD
ώστε να ξαναδείχνει στον κλάδο master
και επανέφερε τα αρχεία στον τρέχοντα κατάλογο στο στιγμιότυπο που δείχνει ο κλάδος master'.
Αυτό σημαίνει επίσης ότι όποιες αλλαγές κάνουμε από αυτό το σημείο και μετά θα αποκλίνουν από την προηγούμενη έκδοση του έργου.
Ουσιαστικά αναιρεί όποιες αλλαγές έχουμε κάνει στον κλάδο `testing
ώστε να μπορέσουμε να κινηθούμε σε μία διαφορετική κατεύθυνση.
Note
|
Η μετάβαση από έναν κλάδο σε άλλον αλλάζει τα αρχεία στον κατάλογο εργασίας.
Είναι σημαντικό να τονίσουμε ότι στο Git όταν μετακινούμαστε από έναν κλάδο σε άλλο, τα αρχεία στον τρέχοντα κατάλογο αλλάζουν.
Αν μεταβούμε σε κάποιον παλιότερο κλάδο, ο τρέχων κατάλογος θα επαναφερθεί στην κατάσταση στην οποία βρισκόταν την τελευταία φορά που είχαμε κάνει κάποια υποβολή σε αυτόν τον κλάδο.
Αν το Git δεν μπορεί να το κάνει χωρίς συγκρούσεις, δεν θα μας επιτρέψει να μεταβούμε σε αυτόν τον κλάδο.
|
Ας κάνουμε μερικές ακόμα αλλαγές και ας τις υποβάλλουμε:
$ vim test.rb
$ git commit -a -m 'made other changes'
Τώρα το ιστορικό του έργου έχει αποκλίνει (βλ. Αποκλίνον ιστορικό).
Δημιουργήσαμε έναν κλάδο, μεταβήκαμε σε αυτόν, κάναμε κάποιες αλλαγές και μετά επιστρέψαμε στον κλάδο main' και κάναμε κάποιες άλλες αλλαγές.
Οι αλλαγές αυτές είναι απομονωμένες σε διαφορετικούς κλάδους: μπορούμε να μεταπηδούμε από τον έναν κλάδο στον άλλο και να τους συγχωνεύσουμε όταν είμαστε έτοιμοι να κάνουμε κάτι τέτοιο.
Και όλα αυτά τα καταφέρνουμε με απλές εντολές `branch
, checkout
και commit
.

Αυτό μπορούμε επίσης να το δούμε εύκολα με την εντολή git log
.
Αν τρέξουμε την εντολή git log --oneline --decorate --graph --all
θα εκτυπωθεί το ιστορικό των υποβολών στο οποίο θα φαίνεται πού βρίσκονται οι δείκτες των κλάδων μας και με ποιον τρόπο έχει αποκλίνει το ιστορικό.
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project
Επειδή ένας κλάδος στο Git είναι στην πραγματικότητα ένα αρχείο που περιέχει τους 40 χαρακτήρες του αθροίσματος ελέγχου SHA-1 της υποβολής στην οποία δείχνει, η δημιουργία και καταστροφή κλάδων είναι μία φθηνή διαδικασία. Η δημιουργία ενός κλάδου είναι τόσο γρήγορη και απλή όσο το να γράφονται 41 byte σε ένα αρχείο (40 αλφαριθμητικοί χαρακτήρες και ένας χαρακτήρας αλλαγής γραμμής).
Αυτή είναι μία σημαντική διαφορά σε σχέση με τον τρόπο με τον οποίο τα περισσότερα παλιότερα VCS δημιουργούν κλάδους, που περιλαμβάνει την αντιγραφή όλων των αρχείων του έργου σε έναν άλλο κατάλογο. Αυτό μπορεί να διαρκέσει αρκετά δευτερόλεπτα ή ακόμα και λεπτά, ανάλογα με το μέγεθος του έργου, ενώ στο στο Git, η διαδικασία είναι σχεδόν στιγμιαία. Επιπλέον, επειδή καταγράφονται οι γονείς όταν κάνουμε υποβολές commit, η εύρεση μίας κατάλληλης βάσης για συγχώνευση γίνεται αυτόματα και γενικά γίνεται πολύ εύκολα. Αυτά τα χαρακτηριστικά ενθαρρύνουν τους προγραμματιστές να δημιουργούν και να χρησιμοποιούν κλάδους συχνά.
Ας δούμε γιατί πρέπει να το κάνουμε αυτό.