Git
Chapters ▾ 2nd Edition

10.5 Εσωτερική λειτουργία του Git - Τα refspec

Τα refspec

Σε αυτό το βιβλίο, χρησιμοποιήσαμε απλές απεικονίσεις από απομακρυσμένους κλάδους σε τοπικές αναφορές, αλλά οι απεικονίσεις είναι δυνατό να είναι πιο σύνθετες. Ας υποθέσουμε ότι προσθέτουμε ένα απομακρυσμένο σύστημα όπως αυτό:

$ git remote add origin https://github.com/schacon/simplegit-progit

Η παραπάνω προσθέτει μια ενότητα στο αρχείο .git/config, καθορίζοντας το όνομα του απομακρυσμένου αποθετηρίου (origin), τη διεύθυνση URL του και το refspec για την ανάκτηση:

[remote "origin"]
	url = https://github.com/schacon/simplegit-progit
	fetch = +refs/heads/*:refs/remotes/origin/*

Η μορφή του refspec είναι ένα προαιρετικό +, ακολουθούμενο από <src>:<dst>, όπου <src> είναι το πρότυπο για αναφορές στην απομακρυσμένη πλευρά και <dst> είναι πού θα γραφούν οι αναφορές αυτές τοπικά. Το + λέει στο Git να ενημερώσει την αναφορά ακόμα κι αν δεν πρόκειται για ταχυπροώθηση.

Στην προεπιλεγμένη περίπτωση που γράφεται αυτόματα από μια εντολή git remote add, το Git συγκεντρώνει όλες τις αναφορές κάτω από τον refs/heads/ του διακομιστή και τις γράφει στον refs/remotes/origin/ τοπικά. Επομένως, εάν υπάρχει ένας κλάδος master στον διακομιστή, μπορούμε να έχουμε πρόσβαση στο μητρώο αυτού του κλάδου τοπικά μέσω

$ git log origin/master
$ git log remotes/origin/master
$ git log refs/remotes/origin/master

Όλες είναι ισοδύναμες, διότι το Git επεκτείνει το καθένα σε refs/remotes/origin/master.

Εάν θέλουμε το Git αντί να έλκει μόνο τον κλάδο master κάθε φορά και όχι κάθε άλλο κλάδο από τον απομακρυσμένο διακομιστή, μπορούμε να αλλάξουμε τη γραμμή παραλαβής σε

fetch = +refs/heads/master:refs/remotes/origin/master

Αυτό είναι μόνο το προεπιλεγμένο refspec για την git fetch για αυτό το απομακρυσμένο αποθετήριο. Αν θέλουμε να κάνουμε κάτι μία φορά, μπορούμε να καθορίσουμε το refspec στη γραμμή εντολών. Για να έλξουμε τον κλάδο master του απομακρυσμένου αποθετηρίου στον τοπικό origin/mymaster, μπορούμε να τρέξουμε

$ git fetch origin master:refs/remotes/origin/mymaster

Μπορούμε επίσης να ορίσουμε πολλά refspecs. Στη γραμμή εντολών, μπορούμε να έλξουμε αρκετούς κλάδους ως εξής:

$ git fetch origin master:refs/remotes/origin/mymaster \
	 topic:refs/remotes/origin/topic
From git@github.com:schacon/simplegit
 ! [rejected]        master     -> origin/mymaster  (non fast forward)
 * [new branch]      topic      -> origin/topic

Σε αυτήν την περίπτωση, η έλξη του κλάδου master απορρίφθηκε επειδή δεν ήταν αναφορά ταχυπροώθησης. Μπορούμε να παρακάμψουμε αυτήν τη συμπεριφορά βάζοντας το + μπροστά από το refspec.

Μπορούμε επίσης να ορίσουμε πολλά refspec για ανάκτηση στο αρχείο ρυθμίσεων. Αν θέλουμε πάντα να ανακτούμε τους κύριους και πειραματικούς κλάδους προσθέτουμε αυτές τις δύο γραμμές:

[remote "origin"]
	url = https://github.com/schacon/simplegit-progit
	fetch = +refs/heads/master:refs/remotes/origin/master
	fetch = +refs/heads/experiment:refs/remotes/origin/experiment

Δεν μπορούμε να χρησιμοποιήσουμε χαρακτήρες μπαλαντές στο μοτίβο, επομένως το παρακάτω δεν είναι έγκυρη έκφραση:

fetch = +refs/heads/qa*:refs/remotes/origin/qa*

Πάντως, μπορούμε να χρησιμοποιήσουμε ονοματοχώρους (ή καταλόγους) για να πετύχουμε κάτι τέτοιο. Εάν έχουμε μια ομάδα QA που ωθεί μια σειρά από κλάδους και θέλουμε να πάρουμε το κύριο κλάδο και οποιοδήποτε από τους κλάδους της ομάδας QA αλλά τίποτα άλλο, μπορούμε να χρησιμοποιήσουμε μια ενότητα config όπως αυτή:

[remote "origin"]
	url = https://github.com/schacon/simplegit-progit
	fetch = +refs/heads/master:refs/remotes/origin/master
	fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*

Εάν έχουμε μια πολύπλοκη ροή εργασίας που διαθέτει μια ομάδα QA που ωθεί κλάδους, προγραμματιστές που ωθούν κλάδους και ομάδες ενσωμάτωσης που ωθούν και συνεργάζονται σε απομακρυσμένα κλάδους, μπορούμε να τους χωρίσουμε σε ονοματοχώρους με αυτό τον τρόπο.

Ώθηση refspecs

Είναι ωραίο ότι μπορούμε να ανακτήσουμε αναφορές εντός ονοματοχώρων με αυτόν τον τρόπο, αλλά πώς μπόρεσε η ομάδα QA να βάλει όλους τους κλάδους της σε έναν ονοματοχώρο qa/; Αυτό το πετυχαίνουμε χρησιμοποιώντας refspec για να ωθήσουμε.

Εάν η ομάδα QA θέλει να ωθήσει τον κλάδο master στον qa/master στον απομακρυσμένο διακομιστή, μπορεί να τρέξει

$ git push origin master:refs/heads/qa/master

Αν θέλουν να το κάνει το Git αυτόματα κάθε φορά που τρέχουν την git push origin, μπορούν να προσθέσουν μια τιμή push στο αρχείο config:

[remote "origin"]
	url = https://github.com/schacon/simplegit-progit
	fetch = +refs/heads/*:refs/remotes/origin/*
	push = refs/heads/master:refs/heads/qa/master

Και πάλι, αυτό θα προκαλέσει μια git push origin να ωθήσει τον τοπικό κλάδο master στον απομακρυσμένο κλάδο qa/master εκ προεπιλογής.

Διαγραφή αναφορών

Μπορούμε επίσης να χρησιμοποιήσουμε το refspec για να διαγράψουμε αναφορές από τον απομακρυσμένο διακομιστή εκτελώντας κάτι σαν αυτό:

$ git push origin :topic

Επειδή το refspec είναι <src>:<dst>, αν αφήσουμε το τμήμα <src>, αυτό ουσιαστικά λέει “κάνε τον θεματικό κλάδο στο απομακρυσμένο αποθετήριο, τίποτα”, οπότε το διαγράφει.