-
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 Αποθέματα και Καθαρισμός
- 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 στο Visual Studio Code
- A1.4 Git στο IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git στο Sublime Text
- A1.6 Το Git στο Bash
- A1.7 Το Git στο Zsh
- A1.8 Το Git στο Powershell
- A1.9 Ανακεφαλαίωση
-
A2. Appendix B: Ενσωμάτωση του Git στις εφαρμογές μας
- A2.1 Γραμμή εντολών Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
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 αποθηκεύει ένα αντικείμενο υποβολής που περιέχει έναν δείκτη προς το στιγμιότυπο του περιεχομένου που έχει υποβληθεί. Αυτό το αντικείμενο περιέχει επίσης το όνομα και e-mail του συγγραφέα, το μήνυμα που έχουμε πληκτρολογήσει καθώς και δείκτες προς την υποβολή ή τις υποβολές που προηγήθηκαν ακριβώς πριν από αυτή την υποβολή (δηλαδή, τον γονέα ή τους γονείς της): όταν ένα αρχείο υποβάλλεται για πρώτη φορά, τότε δεν έχει κανέναν γονέα· μία συνηθισμένη υποβολή έχει έναν γονέα, ενώ μία υποβολή που προέκυψε από τη συγχώνευση δύο ή περισσότερων κλάδων έχει περισσότερους από έναν γονέα.
Για να το οπτικοποιήσουμε λίγο, ας υποθέσουμε ότι έχουμε έναν κατάλογο που περιέχει τρία αρχεία, τα οποία έχουμε προσθέσει στο στάδιο καταχώρησης και στη συνέχεια υποβάλλουμε (commit). Κατά την προσθήκη των αρχείων στο στάδιο καταχώρησης υπολογίζονται τα αθροίσματα ελέγχου (checksums) των αρχείων (με τον αλγόριθμο SHA-1, που αναφέρθηκε στην ενότητα Τι είναι το Git;), αποθηκεύονται οι συγκεκριμένες εκδόσεις των αρχείων στο αποθετήριο Git (το Git ονομάζει αυτές τις εκδόσεις blobs) και προσθέτει τα αθροίσματα ελέγχου στο στάδιο καταχώρησης.
$ git add README test.rb LICENSE
$ git commit -m 'Initial commit'
Όταν κάνουμε την υποβολή, τρέχοντας την εντολή git commit, το Git υπολογίζει ένα άθροισμα ελέγχου για καθέναν υποκατάλογο (στη συγκεκριμένη περίπτωση μόνο για τον βασικό κατάλογο του έργου) και τους αποθηκεύει ως αντικείμενα δομής δένδρου στο αποθετήριο Git.
Στη συνέχεια το Git δημιουργεί ένα αντικείμενο υποβολής που περιέχει τα μεταδεδομένα και έναν δείκτη στη βάση του δένδρου του έργου, ώστε να μπορεί να επαναδημιουργήσει το στιγμιότυπο, όταν χρειαστεί.
Πλέον το αποθετήριό μας περιέχει πέντε αντικείμενα: τρία blob για τα περιεχόμενα των αρχείων (ένα blob για κάθε αρχείο), μία δομή δένδρου που καταγράφει τα περιεχόμενα του καταλόγου και προσδιορίζει ποιο αρχείο αντιστοιχίζεται σε ποιο blob και ένα αντικείμενο commit που περιέχει τον δείκτη στον βασικό κατάλογο και όλα τα μεταδεδομένα της υποβολής.
Αν κάνουμε μερικές αλλαγές και τις υποβάλλουμε, η επόμενη υποβολή αποθηκεύει έναν δείκτη στην ακριβώς προηγούμενη υποβολή.
Οι κλάδοι του Git είναι απλά μετακινήσιμοι δείκτες σε υποβολές.
Το προεπιλεγμένο όνομα κλάδου στο Git είναι master (κύριος κλάδος).
Όταν ξεκινάμε να κάνουμε υποβολές, μας δίνεται ένας κλάδος master που δείχνει στην τελευταία υποβολή που κάναμε.
Κάθε φορά που υποβάλλουμε, ο κλάδος master προχωρά αυτόματα.
|
Note
|
Ο κλάδος “master” στο Git δεν είναι κάποιος ειδικός κλάδος.
Είναι ακριβώς το ίδιο με οποιονδήποτε άλλο κλάδο.
Ο μόνος λόγος για τον οποίο σχεδόν κάθε αποθετήριο έχει έναν κλάδο |
Δημιουργία νέου κλάδου
Τι γίνεται όταν δημιουργούμε έναν νέο κλάδο;
Αυτό που συμβαίνει είναι ότι δημιουργείται ένα νέος δείκτης τον οποίο μπορούμε να μετακινούμε από δω κι από κει.
Ας πούμε ότι δημιουργούμε έναν νέο κλάδο που ονομάζεται 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 Fix bug #1328 - stack overflow under certain conditions
98ca9 Initial commit
Βλέπουμε τους κλάδους “master” και “testing” που βρίσκονται δίπλα στην υποβολή f30ab.
Μετάβαση σε άλλο κλάδο
Για να μεταβούμε σε έναν ήδη υπάρχοντα κλάδο, τρέχουμε την εντολή git checkout.
Ας μεταβούμε στον νέο κλάδο testing:
$ git checkout testing
Η εντολή αυτή μετατοπίζει τον δείκτη HEAD ώστε να δείχνει στον κλάδο testing.
HEAD δείχνει στον τρέχοντα κλάδο.Ποια είναι η σημασία αυτού του πράγματος; Ας κάνουμε ακόμα μία υποβολή:
$ vim test.rb
$ git commit -a -m 'Make a change'
HEAD μετακινείται ότι γίνεται μία υποβολήΑυτό είναι ενδιαφέρον, διότι τώρα ο νέος μας κλάδος testing έχει προχωρήσει, αλλά ο κλάδος master ακόμα δείχνει στην υποβολή που βρισκόμασταν όταν είχαμε τρέξει την εντολή git checkout για να αλλάξουμε κλάδο.
Ας επιστρέψουμε στον κλάδο master:
$ git checkout master
|
Note
|
Η εντολή
git log δεν δείχνει όλους τους κλάδους πάντα
Αν εκτελούσατε Ο κλάδος δεν έχει εξαφανιστεί· το Git δεν γνωρίζει ότι ενδιαφέροσαστε για αυτόν τον κλάδο και προσπαθεί να σας δείξει μόνο αυτό για το οποίο νομίζει ότι σας ενδιαφέρει.
Με άλλα λόγια, εξ ορισμού, η Για να δείτε όλο το ιστορικό υποβολών για τον κλάδο που θέλουμε, πρέπει να το πούμε ρητά: |
HEAD μετακινείται όταν εκτελούμε checkoutΑυτή η εντολή έκανε δύο πράγματα:
Μετατόπισε τον δείκτη HEAD ώστε να ξαναδείχνει στον κλάδο master και επανέφερε τα αρχεία στον τρέχοντα κατάλογο στο στιγμιότυπο που δείχνει ο κλάδος master'.
Αυτό σημαίνει επίσης ότι όποιες αλλαγές κάνουμε από αυτό το σημείο και μετά θα αποκλίνουν από μια παλιότερη έκδοση του έργου.
Ουσιαστικά αναιρεί όποιες αλλαγές έχουμε κάνει στον κλάδο `testing ώστε να μπορέσουμε να κινηθούμε σε μία διαφορετική κατεύθυνση.
|
Note
|
Η μετάβαση από έναν κλάδο σε άλλον αλλάζει τα αρχεία στον κατάλογο εργασίας
===
Είναι σημαντικό να τονιστεί ότι όταν μετακινείστε από έναν κλάδο σε άλλο στο Git, τα αρχεία στον τρέχοντα κατάλογο αλλάζουν.
Αν μεταβείτε σε κάποιον παλιότερο κλάδο, ο τρέχων κατάλογος θα επαναφερθεί στην κατάσταση στην οποία βρισκόταν την τελευταία φορά που είχατε κάνει κάποια υποβολή σε αυτό τον κλάδο.
Αν το Git δεν μπορεί να το κάνει χωρίς προβλήματα, δεν θα σας επιτρέψει να μεταβείτε σε αυτό τον κλάδο.
===
|
Ας κάνουμε μερικές ακόμα αλλαγές και να τις υποβάλλουμε:
$ vim test.rb
$ git commit -a -m 'Make other changes'
Τώρα το ιστορικό του έργου έχει αποκλίνει (βλ. Αποκλίνον ιστορικό).
Δημιουργήσαμε έναν κλάδο, μεταβήκαμε σε αυτόν, κάναμε κάποιες αλλαγές και μετά επιστρέψαμε στον κύριο κλάδο μας και κάναμε κάποιες άλλες αλλαγές.
Οι αλλαγές αυτές είναι απομονωμένες σε διαφορετικούς κλάδους: μπορούμε να μεταπηδούμε από τον έναν κλάδο στον άλλο και να τους συγχωνεύσουμε όταν είμαστε έτοιμοι.
Και όλα αυτά τα καταφέρνουμε με απλές εντολές branch, checkout και commit.
Αυτό μπορούμε επίσης να το δούμε εύκολα με την εντολή git log.
Αν εκτελέσουμε την εντολή git log --oneline --decorate --graph --all θα εκτυπωθεί το ιστορικό των υποβολών στο οποίο θα φαίνεται πού βρίσκονται οι δείκτες των κλάδων μας και με ποιον τρόπο έχει αποκλίνει το ιστορικό.
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) Make other changes
| * 87ab2 (testing) Make a change
|/
* f30ab Add feature #32 - ability to add new formats to the central interface
* 34ac2 Fix bug #1328 - stack overflow under certain conditions
* 98ca9 Initial commit of my project
Επειδή ένας κλάδος στο Git είναι στην πραγματικότητα ένα αρχείο που περιέχει τους 40 χαρακτήρες του αθροίσματος ελέγχου SHA-1 της υποβολής στην οποία δείχνει, η δημιουργία και καταστροφή κλάδων είναι μία φθηνή διαδικασία. Η δημιουργία ενός κλάδου είναι τόσο γρήγορη και απλή όσο το να γράφονται 41 byte σε ένα αρχείο (40 αλφαριθμητικοί χαρακτήρες και ένας χαρακτήρας αλλαγής γραμμής).
Αυτή είναι μία σημαντική διαφορά σε σχέση με τον τρόπο με τον οποίο τα περισσότερα παλιότερα VCS δημιουργούν κλάδους, που περιλαμβάνει την αντιγραφή όλων των αρχείων του έργου σε έναν άλλο κατάλογο. Αυτό μπορεί να διαρκέσει αρκετά δευτερόλεπτα ή ακόμα και λεπτά, ανάλογα με το μέγεθος του έργου, ενώ στο Git η διαδικασία είναι σχεδόν στιγμιαία. Επιπλέον, επειδή σε κάθε υποβολή καταγράφονται οι γονείς της, η εύρεση μίας κατάλληλης βάσης για συγχώνευση γίνεται αυτόματα και γενικά πολύ εύκολα. Αυτά τα χαρακτηριστικά ενθαρρύνουν τους προγραμματιστές να δημιουργούν και να χρησιμοποιούν κλάδους συχνά.
Ας δούμε γιατί πρέπει να το κάνουμε αυτό.
|
Note
|
Δημιουργία κλάδου και μετάβαση σε αυτόν με τη μία
Είναι σύνηθες όταν δημιουργείτε έναν κλάδο να θέλετε να μεταβείτε σε αυτόν άμεσα — αυτό μπορεί να γίνει με την εκτέλεση μίας μόνο εντολής, της |
|
Note
|
Από την έκδοση 2.23 του Git και μετά, μπορείτε να χρησιμοποιήσετε την
|