Chapters ▾ 2nd Edition

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

Τα refspec

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

$ 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 origin, το 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 για ανάκτηση στο αρχείο ρυθμίσεων. Αν θέλουμε πάντα να ανακτούμε τους master και experiment κλάδους από το απομακρυσμένο (origin) αποθετήριο, προσθέτουμε αυτές τις δύο γραμμές:

[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

Από την έκδοση Git 2.6.0 μπορούμε να χρησιμοποιήσουμε μερικώς globs για να ταιριάξουμε πολλαπλούς κλάδους, οπότε το επόμενο είναι έγκυρη έκφραση:

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

Πάντως, μπορούμε να χρησιμοποιήσουμε ονοματοχώρους (ή καταλόγους) για να πετύχουμε κάτι τέτοιο με καλύτερη δομή. Εάν έχουμε μια ομάδα QA που ωθεί μια σειρά από κλάδους και θέλουμε να πάρουμε το master κλάδο και οποιοδήποτε από τους κλάδους της ομάδας 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 εκ προεπιλογής.

Note

Δεν μπορούμε να χρησιμοποιήσουμε το refspec για να έλξουμε από ένα αποθετήριο και να ωθήσουμε σε ένα άλλο. Για παράδειγμα, μεταβείτε στο Διατήρησε το δημόσιο Github αποθετήριο ενημερωμένο.

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

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

$ git push origin :topic

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

Ή μπορούμε να χρησιμοποιήσουμε την νέα σύνταξη (διαθέσιμη από Git v1.7.0):

$ git push origin --delete topic