-
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.5 Διακλαδώσεις στο Git - Απομακρυσμένοι κλάδοι
Απομακρυσμένοι κλάδοι
Οι απομακρυσμένες αναφορές είναι αναφορές (δείκτες) στα απομακρυσμένα αποθετήρια, συμπεριλαμβανομένων των κλάδων, των ετικετών και ούτω καθεξής.
Μπορούμε να πάρουμε μία πλήρη λίστα των απομακρυσμένων αναφορών με την εντολή git ls-remote <απομακρυσμένο_αποθετήριο>
, or git remote show <απομακρυσμένο_αποθετήριο>
για απομακρυσμένους κλάδους καθώς και άλλες πληροφορίες.
Παρόλα αυτά, ένας πιο συνηθισμένος τρόπος είναι να εκμεταλλευτούμε τους κλάδους τηλεπαρακολούθησης.
Οι κλάδοι τηλεπαρακολούθησης είναι αναφορές στην κατάσταση απομακρυσμένων κλάδων. Είναι τοπικές αναφορές τις οποίες δεν μπορούμε να μετακινήσουμε· μετακινούνται αυτόματα όποτε υπάρχει κάποια δικτυακή επικοινωνία. Οι κλάδοι τηλεπαρακολούθησης λειτουργούν σαν σελιδοδείκτες που μας θυμίζουν πού βρίσκονταν οι κλάδοι στα απομακρυσμένα αποθετήριά μας την τελευταία φορά που είχαμε συνδεθεί σε αυτά.
Έχουν τη μορφή <απομακρυσμένο_αποθετήριο>/<κλάδος>
.
Για παράδειγμα, αν θέλουμε να δούμε σε ποια κατάσταση ήταν ο κλάδος master
στο απομακρυσμένο αποθετήριό μας origin
την τελευταία φορά που επικοινωνήσαμε μαζί του, θα πρέπει να μεταβούμε στον κλάδο origin/master
.
Αν δουλεύαμε σε ένα θέμα με κάποιον συνεργάτη και αυτός είχε ωθήσει έναν κλάδο iss53
, τότε θα είχαμε κι εμείς έναν τοπικό κλάδο iss53
· αλλά ο κλάδος στον διακομιστή θα έδειχνε στην υποβολή του origin/iss53
.
Ας τα ξεμπερδέψουμε όλα αυτά με ένα παράδειγμα.
Ας υποθέσουμε ότι έχουμε έναν διακομιστή Git στο δίκτυό μας στη διεύθυνση git.ourcompany.com
.
Αν τον κλωνοποιήσουμε, η εντολή clone
του Git θα τον ονομάσει origin
, θα έλξει όλα τα δεδομένα και θα δημιουργήσει έναν δείκτη που δείχνει εκεί όπου βρίσκεται ο κλάδος του master
και θα τον ονομάσει τοπικά origin/master
.
Το Git επίσης μας δίνει τον δικό μας τοπικό κλάδο master
που ξεκινά από το ίδιο σημείο από όπου ξεκινά και ο κλάδος master
του αποθετηρίου origin
, ώστε να έχουμε κάτι πάνω στο οποίο να δουλέψουμε.
Note
|
Το αποθετήριο
origin δεν είναι κάτι ιδιαίτεροΑκριβώς όπως το όνομα |

Αν κάνουμε λίγη δουλίτσα στον τοπικό κύριο κλάδο μας και στο μεταξύ κάποιος άλλος ωθήσει στο git.ourcompany.com
και ενημερώσει τον κλάδο master
, τότε τα ιστορικά θα προχωρήσουν διαφορετικά.
Ακόμα, για όσο χρονικό διάστημε δεν είμαστε συνδεδεμένοι με τον διακομιστή origin
, ο δείκτης μας origin/master
δεν μετακινείται.

Για να συγχρονίσουμε τη δουλειά μας, τρέχουμε μία εντολή git fetch origin
.
Αυτή η εντολή αναζητά ποιος διακομιστής είναι ο origin
(στη συγκεκριμένη περίπτωση είναι ο git.ourcompany.com
), ανακτά (fetch) από αυτόν ό,τι δεδομένα δεν έχουμε ακόμα, ενημερώνει την τοπική βάση δεδομένων μας, μετακινεί τον δείκτη origin/master
στη νέα του πιο ενημερωμένη θέση.

git fetch
ενημερώνει τις απομακρυσμένες αναφορές.Για να δείξουμε τι συμβαίνει όταν έχουμε πολλαπλούς απομακρυσμένους διακομιστές και με τι μοιάζουν οι απομακρυσμένοι κλάδοι των απομακρυσμένων έργων, ας υποθέσουμε ότι έχουμε ένα άλλο εσωτερικό διακομιστή Git που χρησιμοποιείται μόνον για ανάπτυξη κώδικα από μία συγκεκριμένη ομάδα.
Αυτός ο διακομιστής βρίσκεται στη διεύθυνση git.team1.ourcompany.com
.
Μπορούμε να τον προσθέσουμε στο έργο στο οποίο δουλεύουμε τώρα ως μία νέα απομακρυσμένη αναφορά τρέχοντας την εντολή git remote add
όπως εξηγήσαμε στο κεφάλαιο [ch02-git-basics].
Ονομάζουμε αυτόν το απομακρυσμένο διακομιστή teamone
και αυτό θα είναι ένα σύντομο όνομα για όλο το παραπάνω URL.

Τώρα μπορούμε να τρέξουμε την εντολή git fetch teamone
για να ανακτήσουμε ο,τιδήποτε ο απομακρυσμένος διακομιστής teamone
έχει που δεν το έχουμε εμείς ακόμα.
Επειδή ο διακομιστής έχει ένα υποσύνολο από τα δεδομένα που έχει ο διακομιστής μας origin
αυτήν τη στιγμή, το Git δεν ανακτά δεδομάνα, αλλά τοποθετεί έναν κλάδο τηλεπαρακολούθησης με όνομα teamone/master
να δείχνει στην υποβολή που έχει ο teamone
στον κύριο κλάδο του master
.

teamone/master
.Ωθήσεις
Όταν θέλουμε να μοιραστούμε έναν κλάδο με τον υπόλοιπο κόσμο, πρέπει να τον ωθήσουμε σε έναν απομακρυσμένο διακομιστή στον οποίο έχουμε δικαίωμα εγγραφής (write access). Οι τοπικοί μας κλάδοι δεν συγχρονίζονται αυτόματα με τους απομακρυσμένους διακομιστές στους οποίους έχουμε δικαίωμα να αποθηκεύουμε —πρέπει να χειροκίνητα να ωθήσουμε τους κλάδους που θέλουμε να μοιραστούμε. Με αυτόν τον τρόπο, μπορούμε να χρησιμοποιούμε ιδιωτικούς κλάδους για δουλειά που δεν θέλουμε να μοιραστούμε με άλλους και να ωθούμε μόνον τους θεματικούς κλάδους στους οποίους θέλουμε να συνεργαστούμε.
Αν έχουμε έναν κλάδο με όνομα serverfix
στον οποίο θέλουμε να δουλέψουμε με άλλους, μπορούμε να τον ωθήσουμε με τον ίδιο τρόπο που ωθήσαμε τον πρώτο μας κλάδο.
Τρέχουμε την εντολή git push <απομακρυσμένο_αποθετήριο> <κλάδος>
:
$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
* [new branch] serverfix -> serverfix
Στην πραγματικότητα αυτή η εντολή είναι μία συντόμευση.
Το Git αυτόματα αναπτύσσει το όνομα κλάδου serverfix
σε refs/heads/serverfix:refs/heads/serverfix
, που σημαίνει “Πάρε τον τοπικό μου κλάδο serverfix
και ώθησέ τον ώστε να ενημερωθεί ο αντίστοιχος κλάδος serverfix
του απομακρυσμένου διακομιστή”.
Θα δούμε πιο λεπτομερώς το κομμάτι refs/heads/
στην ενότητα [ch10-git-internals], αλλά προς το παρόν μπορούμε να το αγνοήσουμε.
Επίσης μπορούμε να τρέξουμε την εντολή git push origin serverfix:serverfix
, που κάνει ακριβώς το ίδιο πράγμα —λέει, “Πάρε το δικό μου serverfix
και κάντο το serverfix
του απομακρυσμένου διακομιστή”.
Αυτήν τη μορφή της εντολής τη χρησιμοποιούμε για να ωθήσουμε έναν τοπικό κλάδο σε έναν απομακρυσμένο που έχει διαφορετικό όνομα.
Αν δεν θέλαμε να ονομάζεται serverfix
στο απομακρυσμένο αποθετήριο, τότε μπορούμε να τρέξουμε την εντολή git push origin serverfix:awesomebranch
ώστε να ωθήσουμε τον τοπικό μας κλάδο serverfix
στον κλάδο με όνομα awesomebranch
στο απομακρυσμένο αποθετήριο.
Note
|
Δεν χρειάζεται να γράφουμε τον κωδικό μας κάθε φορά.
Αν θέλουμε να ωθήσουμε κάτι σε ένα URL με HTTPS, ο διακομιστής Git θα μας ζητήσει το όνομα χρήστη και τον κωδικό μας για ταυτοποίηση. Η προεπιλεγμένη ρύθμιση είναι να μας ζητήσει αυτήν την πληροφορία στο τερματικό, ώστε ο διακομιστής να αποφανθεί αν έχουμε το δικαίωμα να ωθήσουμε αλλαγές. Αν δεν θέλουμε να πλκτρολογούμε τον κωδικό μας κάθε φορά που ωθούμε κάτι, μπορούμε να ορίσουμε μία “προσωρινή μνήμη διαπιστευτηρίων”.
Ο πιο απλός τρόπος είναι να παραμένουν στη μνήμη για μερικά λεπτά, κάτι που μπορεί να οριστεί εύκολα με την εντολή Περισσότερες πληροφορίες σχετικά με τις διάφορες επιλογές προσωρινής αποθήκευσης διαπιστευτηρίων βλ. Αποθήκευση διαπιστευτηρίων. |
Την επόμενη φορά που κάποιος από τους συνεργάτες μας ανακτά από τον διακομιστή, θα πάρει μία αναφορά που θα δείχνει εκεί όπου βρίσκεται ο κλάδος serverfix
του διακομιστή, δηλαδή κάτω από τον απομακρυσμένο κλάδο origin/serverfix
:
$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
* [new branch] serverfix -> origin/serverfix
Είναι σημαντικό να σημειώσουμε πως όταν εκτελούμε μία εντολή git fetch
, αυτή φέρνει νέους κλάδους τηλεπαρακολούθησης, δεν έχουμε αυτόματα τοπικά επεξεργάσιμα αρχεία. Με άλλα λόγια σε αυτήν την περίπτωση δεν έχουμε έναν νέο κλάδο serverfix
—έχουμε μόνον έναν δείκτη στον origin/serverfix
που δεν μπορούμε να τροποποιήσουμε.
Για να συγχωνεύσουμε αυτήν τη δουλειά στον τρέχοντα κλάδο εργασίας μας, μπορούμε να τρέξουμε την εντολή git merge origin/serverfix
.
Αν θέλουμε τον δικό μας κλάδο serverfix
στον οποίο μπορούμε να εργαστούμε, μπορούμε να τον αποκολλήσουμε από τον κλάδο τηλεπαρακολούθησης:
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
Η παραπάνω εντολή μας δίνει έναν τοπικό κλάδο στον οποίο μπορούμε να δουλέψουμε και που ξεκινά από εκείνο το σημείου στο οποίο βρίσκεται ο κλάδος origin/serverfix
.
Παρακολούθηση κλάδων
Όταν μεταβαίνουμε σε έναν τοπικό κλάδο από έναν τηλεπαρακολουθούμενο κλάδο αυτόματα δημιουργείται ένας “κλάδος παρακολούθησης” (και ο κλάδος που παρακολουθεί ονομάζεται “κλάδος upstream”).
Οι κλάδοι παρακολούθησης είναι τοπικοί κλάδοι που έχουν άμεση σχέση με έναν απομακρυσμένο κλάδο.
Αν είμαστε σε έναν κλάδο παρακολούθησης και πληκτρολογήσουμε git pull
, το Git αυτόματα γνωρίζει από ποιον διακομιστή να ανακτήσει και σε ποιον κλάδο να συγχωνεύσει.
Όταν κλωνοποιούμε ένα αποθετήριο, αυτό δημιουργεί αυτόματα έναν κλάδο master
που παρακολουθεί τον κλάδο origin/master
.
Όμως μπορούμε να ορίσουμε και άλλους κλάδους παρακολούθησης, αν θέλουμε —κλάδους που παρακολουθούν κλάδους σε άλλα απομακρυσμένα αποθετήρια ή δεν παρακολουθούν τον κλάδο master
.
Η πιο απλή περίπτωση είναι αυτή που μόλις είδαμε, η εντολή git checkout -b <κλάδος> <απομακρυσμένο_αποθετήριο>/<κλάδος>
.
Αυτή η περίπτωση είναι τόσο συνηθισμένη που το Git μάς παρέχει την επιλογή --track
:
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
Για την ακρίβεια είναι τόσο συνηθισμένη που υπάρχει συντόμευση για την παραπάνω επιλογή. Αν το όνομα του κλάδου στον οποίο προσπαθούμε να μεταβούμε (α) δεν υπάρχει και (β) έχει ακριβώς το ίδιο όνομα με έναν απομακρυσμένο, το Git θα δημιουργήσει αυτόματα έναν κλάδο παρακολούθησης.
$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
Για να ορίσουμε έναν τοπικό κλάδο με διαφορετικό όνομα από αυτό του απομακρυσμένου κλάδου, μπορούμε εύκολα να χρησιμοποιήσουμε την πρώτη εκδοχή με διαφορετικό όνομα τοπικού κλάδου:
$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'
Τώρα ο τοπικός μας κλάδος sf
θα έλξει αυτόματα από τον κλάδο origin/serverfix
.
Αν έχουμε ήδη έναν τοπικό κλάδο και θέλουμε να τον συνδέσουμε με έναν απομακρυσμένο κλάδο που μόλις έλξαμε ή θέλουμε να αλλάξουμε τον ανοδικό κλάδο που παρακολουθούμε, μπορούμε να χρησιμοποιήσουμε την επιλογή -u
ή --set-upstream-to
με την εντολή git branch
ώστε να τον συνδέσουμε οποιαδήποτε στιγμή.
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Note
|
Συντόμευση Upstream
Όταν έχουμε ορίσει έναν κλάδο παρακολούθησης, μπορούμε να αναφερθούμε σε αυτόν ως |
Αν θέλουμε να δούμε ποιους κλάδους παρακολούθησης έχουμε ορίσε, μπορούμε να χρησιμοποιήσουμε την επιλογή -vv
στην εντολή git branch
.
Αυτή θα καταγράψει όλους τους τοπικούς κλάδους με περισσότερες πληροφορίες συμπεριλαμβανομένων των ποιον κλάδο παρακολουθεί κάθε κλάδος και αν ο τοπικός μας κλάδος είναι προηγείται του απομακρυσμένου, ή υστερεί ή και τα δύο.
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
Εδώ μπορούμε να δούμε ότι ο κλάδος μας iss53
παρακολουθεί τον origin/iss53
και προηγείται (ahead) κατά δύο, δηλαδή ότι έχουμε κάνει δύο υποβολές τοπικά που δεν έχουν ωθηθεί στον διακομιστή.
Επίσης μπορούμε να δούμε ότι ο τοπικός μας κλάδος master
παρακολουθεί τον origin/master
και είναι ενημερωμένος.
Στη συνέχεια βλέπουμε ότι ο κλάδος μας serverfix
παρακολουθεί τον κλάδο server-fix-good
στον διακομιστή teamone
και προηγείται κατά τρία και υστερεί κατά ένα, που σημαίνει ότι υπάρχει μία υποβολή στον διακομιστή που δεν την έχουμε συγχωνεύσει ακόμη και τρεις τοπικές υποβολές που δεν έχουμε ωθήσει ακόμη.
Τέλος, βλέπουμε ότι ο κλάδος μας testing
δεν παρακολουθεί κανέναν απομακρυσμένο κλάδο.
Είναι σημαντικό να παρατηρήσουμε ότι αυτοί οι αριθμοί είναι οι υποβολές από την τελευταία φορά που ανακτήσαμε (fetch) από τον κάθε διακομιστή.
Αυτή η εντολή δεν ρωτά τους διακομιστές, απλά μας λέει τι έχει ήδη αποθηκευμένο τοπικά από τους διακομιστές.
Αν θέλουμε εντελώς ενημερωμένους αριθμούς υποβολών με τις οποίες προηγείται και υστερεί ο κλάδος μας, πρέπει να τρέξουμε μία εντολή fetch
προς όλους τους απομακρυσμένους πριν τρέξουμε την παραπάνω εντολή.
Αυτό μπορούμε να το κάνουμε ως εξής:
$ git fetch --all; git branch -vv
Έλξη
Ενώ η εντολή git fetch
θα ανακτήσει όλες τις αλλαγές που δεν έχουμε ήδη από τον διακομιστή, δεν θα αλλάξει τον κατάλογο εργασίας μας καθόλου.
Απλά θα πάρει τα δεδομένα και θα μας αφήσει να τα συγχωνεύσουμε μόνοι μας.
Πάντως, υπάρχει η εντολή git pull
η οποία ουσιαστικά στις περισσότερες περιπτώσεις είναι μία git fetch
που ακολουθείται από μία git merge
.
Αν έχουμε ορίσει κάποιον κλάδο παρακολούθησης όπως αναφέρθηκε στην προηγούμενη ενότητα, είτε με ρητό ορισμό είτε επειδή τον έχουμε δημιουργήσει με την εντολή clone
ή checkout
, η git pull
θα αναζητήσει τον διακομιστή και κλάδο τον οποίο παρακολουθεί ο τρέχων κλάδος μας, θα ανακτήσει από τον διακομιστή και θα προσπαθήσει να συγχωνεύσει σε αυτόν τον απομακρυσμένο κλάδο.
Γενικά είναι καλύτερα να χρησιμοποιούμε τις εντολές fetch
και merge
ξεχωριστά διότι τα μαγικά που κάνει η git pull
μπορεί να μας μπερδέψουν.
Διαγραφή απομακρυσμένων κλάδων
Ας υποθέσουμε ότι τελειώσαμε με τον απομακρυσμένο κλάδο —π.χ. οι συνεργάτες μας και εμείς τελειώσαμε με ένα χαρακτηριστικό και το έχουμε συγχωνεύσει στον κλάδο master
του απομακρυσμένου αποθετηρίου (ή τέλος πάντων σε οποιονδήποτε κλάδο υπάρχει η ευσταθής έκδοσή του έργου μας).
Μπορούμε να διαγράψουμε τον απομακρυσμένο κλάδο χρησιμοποιώντας την επιλογή --delete
στην εντολή git push
.
Αν θέλουμε να διαγράψουμε τον κλάδο serverfix
από τον διακομιστή, τρέχουμε τα παρακάτω:
$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
- [deleted] serverfix
Βασικά αυτό που κάνει αυτή η εντολή είναι να απομακρύνει τον δείκτη από τον διακομιστή. Ο διακομιστής Git γενικά θα διατηρήσει τα δεδομένα εκεί για λίγο καιρό, μέχρι να τρέξει μία διαδικασία συλλογής σκουπιδιών (garbage collection) ώστε αν ο κλάδος διαγράφηκε κατά λάθος, να είναι εύκολο να αποκατασταθεί.