Εκτός από το να γνωρίζετε πώς να συμβάλλετε αποτελεσματικά σε ένα έργο, πιθανότατα θα χρειαστεί να ξέρετε πώς να διαχειρίζεστε ένα αποθετήριο.
Αυτό μπορεί να συνίσταται στην αποδοχή και εφαρμογή των επιθεμάτων που δημιουργούνται με το format-patch
και στέλνονται με e-mail σε εσάς ή στην ενσωμάτωση αλλαγών σε απομακρυσμένους κλάδους για αποθετήρια που έχετε προσθέσει ως απομακρυσμένα στο έργο σας.
Είτε διαχειρίζεστε ένα τυπικό αποθετήριο είτε θέλετε να βοηθήσετε επαληθεύοντας ή εγκρίνοντας επιθέματα, πρέπει να ξέρετε πώς να δέχεστε την εργασία με τρόπο που είναι κατά το δυνατό ξεκάθαρος στους άλλους συνεργάτες και βιώσιμος από εσάς μακροπρόθεσμα.
Όταν σκέφτεστε να ενσωματώσετε νέα δουλειά, είναι γενικά καλή ιδέα να το δοκιμάσετε σε έναν θεματικό κλάδο — έναν προσωρινό κλάδο ειδικά σχεδιασμένο για να δοκιμάσετε αυτή την εργασία.
Με αυτόν τον τρόπο, είναι εύκολο να τροποποιήσετε ένα επίθεμα ξεχωριστά και να το παρατήσετε αν δεν λειτουργεί μέχρι να έχετε χρόνο να ξανασχοληθείτε μαζί του.
Αν δημιουργήσετε ένα απλό όνομα κλάδου με βάση το θέμα της εργασίας που πρόκειται να δοκιμάσετε, όπως ruby_client
ή κάτι παρόμοια περιγραφικό, μπορείτε εύκολα να το θυμάστε, ακόμα κι αν χρειαστεί να το εγκαταλείψετε για αρκετό καιρό και να επιστρέψετε σε αυτό αργότερα.
Οι διαχειριστές έργων Git συνηθίζουν επίσης να οργανώνουν αυτούς τους κλάδους σε ονοματοχώρους (namespaces) — όπως sc/ruby_client
, όπου το sc
είναι συντομογραφία για τον προγραμματιστή που συνεισέφερε την εργασία.
Όπως ίσως θυμάστε, μπορείτε να δημιουργήσετε τον κλάδο να διακλαδίζεται από τον κύριο κλάδο σας ως εξής:
$ git branch sc/ruby_client master
Εναλλακτικά, αν θέλετε να μεταβείτε σε αυτόν αμέσως, μπορείτε να χρησιμοποιήσετε την επιλογή -b
:
$ git checkout -b sc/ruby_client master
Τώρα είστε έτοιμοι να προσθέσετε τη συνεισφορά σας σε αυτόν τον θεματικό κλάδο και να προσδιορίσετε αν θέλετε να τον συγχωνεύσετε στους μακροβιότερους κλάδους σας.
Αν λάβετε επίθεμα μέσω e-mail και πρέπει να το ενσωματώσετε στο έργο σας, πρέπει να το εφαρμόσετε στον θεματικό κλάδο για να το αξιολογήσετε.
Υπάρχουν δύο τρόποι για να εφαρμόσετε ένα επίθεμα που λάβατε με e-mail: με git apply
ή με git am
.
Εάν λάβατε το επίθεμα από κάποιον που το δημιούργησε με την εντολή git diff
ή diff
του Unix (κάτι που δεν συνιστάται, όπως δείτε στην επόμενη ενότητα), μπορείτε να το εφαρμόσετε με την εντολή git apply
.
Αν υποθέσουμε ότι έχετε αποθηκεύσει το επίθεμα στον φάκελο /tmp/patch-ruby-client.patch
, μπορείτε να το εφαρμόσετε ως εξής:
$ git apply /tmp/patch-ruby-client.patch
Αυτή η εντολή τροποποιεί τα αρχεία στον κατάλογο εργασίας σας.
Είναι σχεδόν πανομοιότυπη με την εκτέλεση της εντολής patch -p1
για την εφαρμογή του επιθέματος, αν και είναι πιο παρανοϊκή και δέχεται λιγότερες ασαφείς αντιστοιχίσεις από ότι η patch
.
Επίσης, διαχειρίζεται προσθήκες, διαγραφές και μετονομασίες αρχείων εφόσον περιγράφονται στη μορφή git diff
, κάτι που δεν κάνει η patch
.
Τέλος, η git apply
είναι ένα μοντέλο “όλα ή τίποτα” (“apply all or abort all”) όπου είτε όλες οι αλλαγές εφαρμόζονται είτε καμία, ενώ η patch
μπορεί να εφαρμόσει μερικώς επιθέματα αφήνοντας τον κατάλογο εργασίας σας σε μία περίεργη κατάσταση.
Η git apply
είναι γενικά πολύ πιο συντηρητική από την patch
.
Δεν θα δημιουργήσει αυτόματα κάποια υποβολή για σας — μετά την εκτέλεσή της, θα πρέπει να βάλετε τις αλλαγές στον προθάλαμο και να τις υποβάλετε οι ίδιοι.
Μπορείτε επίσης να χρησιμοποιήσετε την git apply
για να διαπιστώσετε αν επίθεμα εφαρμόζεται καθαρά πριν δοκιμάσετε την εφαρμογή του — μπορείτε να εκτελέσετε το git apply --check
με το επίθεμα:
$ git apply --check 0001-see-if-this-helps-the-gem.patch
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Εάν δεν τυπωθεί κάτι, τότε το επίθεμα θα πρέπει εφαρμοστεί χωρίς προβλήματα. Αυτή η εντολή επίσης τερματίζει με μη-μηδενική κατάσταση αν ο έλεγχος αποτύχει, οπότε μπορείτε να τη χρησιμοποιήσετε σε script, αν χρειαστεί.
Εάν ο συνεισφέρων είναι χρήστης του Git και ήταν αρκετά καλός ώστε να χρησιμοποιήσει την εντολή format-patch
για να δημιουργήσει το επίθεμα, τότε η εργασία σας είναι ευκολότερη διότι το επίθεμα περιέχει πληροφορίες για τον συγγραφέα και ένα μήνυμα υποβολής για εσάς.
Αν είναι δυνατό, καλό είναι να ενθαρρύνετε τους συνεργάτες σας να χρησιμοποιούν την format-patch
αντί για την diff
για να δημιουργούν επιθέματα για σας.
Θα πρέπει να χρησιμοποιείτε την git apply
μόνον για επιθέματα παλιού τύπου (legacy).
Για να εφαρμόσετε ένα επίθεμα που δημιουργείται με την format-patch
, χρησιμοποιείτε την git am
.
Από τεχνικής άποψης, η git am
έχει φτιαχτεί για να διαβάζει ένα αρχείο mbox, που είναι μία απλή μορφή αρχείου κειμένου για την αποθήκευση ενός ή περισσοτέρων μηνυμάτων e-mail σε ένα αρχείο κειμένου.
Μοιάζει με κάτι τέτοιο:
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <[email protected]>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] add limit to log function
Limit log functionality to the first 20
Αυτή είναι η αρχή της εξόδου της εντολής format-patch
που είδαμε στην προηγούμενη ενότητα.
Είναι επίσης μια έγκυρη μορφή ηλεκτρονικού μηνύματος mbox.
Εάν κάποιος σας έχει στείλει ηλεκτρονικά το επίθεμα χρησιμοποιώντας την git send-email
και το κατεβάσετε σε μορφή mbox, τότε μπορείτε να κατευθύνετε την git am
στο αρχείο mbox και αυτό θα αρχίσει να εφαρμόζει όλα τα επιθέματα που βλέπει.
Εάν τρέχετε ένα πρόγραμμα-πελάτη e-mail που μπορεί να αποθηκεύσει πολλά μηνύματα e-mail σε μορφή mbox, μπορείτε να αποθηκεύσετε ολόκληρες σειρές επιθεμάτων σε ένα αρχείο και στη συνέχεια να χρησιμοποιήσετε την git am
για να εφαρμόσετε το καθένα ξεχωριστά.
Ωστόσο, αν κάποιος χρήστης ανέβασε ένα επίθεμα που δημιουργήθηκε με την format-patch
σε ένα σύστημα εισιτηρίων ή κάτι παρόμοιο, μπορείτε να αποθηκεύσετε το αρχείο τοπικά και να περάσετε το αρχείο που αποθηκεύσατε στην git am
για να το εφαρμόσετε:
$ git am 0001-limit-log-function.patch
Applying: Add limit to log function
Μπορείτε να δείτε ότι το επίθεμα εφαρμόστηκε καθαρά και η νέα υποβολή δημιουργήθηκε για σας αυτόματα.
Οι πληροφορίες του συγγραφέα λαμβάνονται από τις κεφαλίδες From:
και Date:
του e-mail και το μήνυμα της υποβολής λαμβάνεται από το Subject:
και το σώμα (πριν από το επίθεμα) του μηνύματος.
Για παράδειγμα, εάν αυτή η ενημερωμένη έκδοση κώδικα εφαρμόστηκε από το παραπάνω παράδειγμα mbox, η υποβολή που θα δημιουργούνταν θα φαινόταν κάπως έτσι:
$ git log --pretty=fuller -1 commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0 Author: Jessica Smith <[email protected]> AuthorDate: Sun Apr 6 10:17:23 2008 -0700 Commit: Scott Chacon <[email protected]> CommitDate: Thu Apr 9 09:19:06 2009 -0700 Add limit to log function Limit log functionality to the first 20
Οι πληροφορίες στο πεδίο Commit
υποδεικνύουν το άτομο που εφάρμοσε το επίθεμα και την ώρα που έγινε η εφαρμογή αυτή.
Οι πληροφορίες στο πεδίο Author
υποδεικνύουν το άτομο που αρχικά δημιούργησε το επίθεμα και πότε δημιουργήθηκε για πρώτη φορά.
Αλλά είναι πιθανό ότι το επίθεμα δεν θα εφαρμοστεί καθαρά.
Ίσως ο κύριος κλάδος σας έχει αποκλίνει πολύ από τον κλάδο από τον οποίο είχε διακλαδωθεί αυτό το επίθεμα ή το επίθεμα εξαρτάται από ένα άλλο επίθεμα που δεν έχετε εφαρμόσει ακόμα.
Σε αυτή την περίπτωση, η διαδικασία με την git am
θα αποτύχει και θα σας ρωτήσει τι θέλετε να κάνετε:
$ git am 0001-see-if-this-helps-the-gem.patch
Applying: See if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Patch failed at 0001.
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".
Αυτή η εντολή τοποθετεί σημάνσεις σύγκρουσης σε όλα τα αρχεία με τα οποία αντιμετωπίζει προβλήματα, όπως μια σύγκρουση συγχώνευσης ή αλλαγής βάσης.
Μπορείτε να επιλύσετε αυτό το πρόβλημα λίγο-πολύ με τον ίδιο τρόπο — επεξεργάζεστε το αρχείο για να επιλύσετε τη σύγκρουση, τοποθετείτε το νέο αρχείο στον προθάλαμο και στη συνέχεια εκτελείτε την εντολή git am --resolved
για να συνεχίσετε στο επόμενο επίθεμα:
$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Applying: See if this helps the gem
Εάν θέλετε το Git να δοκιμάσει να επιλύσει τη σύγκρουση με λίγο πιο έξυπνο τρόπο, μπορείτε να περάσετε την επιλογή -3
στην git am
, η οποία θα κάνει το Git να επιχειρήσει μια τριμερή συγχώνευση.
Αυτή η επιλογή δεν είναι ενεργοποιημένη εξ ορισμού, επειδή δεν λειτουργεί εφόσον η υποβολή στην οποία λέει το επίθεμα ότι βασίζεται δεν βρίσκεται στο αποθετήριό σας.
Αν έχετε αυτή την υποβολή — για παράδειγμα αν το επίθεμα βασίστηκε σε δημόσια υποβολή — τότε η επιλογή -3
είναι γενικά πολύ πιο έξυπνη όσον αφορά στην εφαρμογή ενός συγκρουόμενου επιθέματος λογισμικού:
$ git am -3 0001-see-if-this-helps-the-gem.patch
Applying: See if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Σε αυτή την περίπτωση, χωρίς την επιλογή -3
, το επίθεμα θα θεωρούνταν σύγκρουση.
Αφού χρησιμοποιήθηκε η επιλογή -3
, το επίθεμα εφαρμόστηκε καθαρά.
Αν εφαρμόζετε μια σειρά από επιθέματα από ένα mbox, μπορείτε επίσης να εκτελέσετε την εντολή am
σε διαδραστική (interactive) λειτουργία, η οποία σταματά σε κάθε επίθεμα που βρίσκει και ρωτά αν θέλετε να το εφαρμόσετε:
$ git am -3 -i mbox
Commit Body is:
--------------------------
See if this helps the gem
--------------------------
Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all
Αυτό είναι βολικό όταν έχετε αποθηκεύσει μερικά επιθέματα, επειδή μπορείτε να τα δείτε πρώτα ή να μην τα εφαρμόσετε εάν το έχετε κάνει ήδη.
Όταν όλα τα επιθέματα για το θέμα σας εφαρμοστούν και υποβληθούν στον κλάδο σας, μπορείτε να επιλέξετε εάν και πώς θα τα ενσωματώσετε σε έναν μακροβιότερο κλάδο.
Εάν η συνεισφορά προήλθε από έναν χρήστη Git που δημιούργησε το δικό του αποθετήριο, ώθησε μερικές αλλαγές σε αυτό και έπειτα σάς έστειλε τη διεύθυνση URL του αποθετηρίου και το όνομα του απομακρυσμένου κλάδου στον οποίο έγιναν οι αλλαγές, μπορείτε να το προσθέσετε ως απομακρυσμένο και να κάνετε συγχωνεύσεις τοπικά.
Για παράδειγμα, εάν η Τζέσικα σας στείλει ένα e-mail που λέει ότι έχει μία εξαιρετική νέα λειτουργικότητα στον κλάδο ruby-client
του αποθετηρίου της, μπορείτε να τη δοκιμάσετε προσθέτοντας το αποθετήριο ως απομακρυσμένο και κάνοντας check out τον κλάδο τοπικά:
$ git remote add jessica git://github.com./jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client
Εάν η Τζέσικα ξαναστείλει e-mail αργότερα με κάποιον άλλο κλάδο που περιέχει άλλο ένα εξαιρετικό χαρακτηριστικό, μπορείτε να κάνετε απευθείας fetch
και checkout
τοπικά διότι έχετε ήδη το απομακρυσμένο αποθετήριο εγκατεστημένο.
Αυτό είναι ιδιαίτερα χρήσιμο αν συνεργάζεστε με ένα άτομο με συχνά. Εάν κάποιος συνεισφέρει ένα επίθεμα μόνο μία στις τόσες, τότε η αποδοχή του μέσω e-mail είναι ενδεχομένως λιγότερο χρονοβόρα από το να πρέπει όλοι να τρέχουν το δικό τους διακομιστή και να προσθαφαιρούν απομακρυσμένους διακομιστές συνεχώς για να πάρουν μιά χούφτα επιθέματα. Επίσης, είναι μάλλον απίθανο να θέλετε να έχετε εκατοντάδες απομακρυσμένους διακομιστές, έναν για καθένα που συνεισφέρει καναδυό επιθέματα μια στις τόσες. Ωστόσο, script και φιλοξενούμενες υπηρεσίες μπορεί να σας διευκολύνουν — αυτό εξαρτάται σε μεγάλο βαθμό από τον τρόπο με τον οποίο εσείς και οι συνεισφέροντες αναπτύσσετε τον κώδικά σας.
Το άλλο πλεονέκτημα αυτής της προσέγγισης είναι ότι έχετε και το ιστορικό των υποβολών.
Παρόλο που ίσως έχετε ζητήματα συγχώνευσης, γνωρίζετε πού βρίσκεται η σχετική εργασία τους στο ιστορικό σας· μια κατάλληλη τριμερής συγχώνευση είναι η προτιμότερη επιλογή από τη χρήση της επιλογής -3
με την ελπίδα ότι το επίθεμα δημιουργήθηκε από μια δημόσια υποβολή στην οποία έχετε πρόσβαση.
Εάν δεν συνεργάζεστε συχνά με ένα άτομο, αλλά εξακολουθείτε να θέλετε να ελκύσετε από αυτόν με αυτόν τον τρόπο, μπορείτε να δώσετε τη διεύθυνση URL του απομακρυσμένου αποθετηρίου στην εντολή git pull
.
Αυτό κάνει ένα και μοναδικό ελκυσμό και δεν αποθηκεύει τη διεύθυνση URL ως απομακρυσμένη αναφορά:
$ git pull https://github.com./onetimeguy/project
From https://github.com./onetimeguy/project
* branch HEAD -> FETCH_HEAD
Merge made by the 'recursive' strategy.
Τώρα έχετε έναν θεματικό κλάδο που περιέχει συνεισφορές. Σε αυτό το σημείο, μπορείτε να αποφασίσετε τι θα θέλατε να κάνετε με αυτόν. Αυτή η ενότητα επανεξετάζει μερικές εντολές, ώστε να μπορείτε να δείτε πώς μπορείτε να τις χρησιμοποιήσετε για να ελέγξετε τι ακριβώς θα εισάγετε αν συγχωνεύσετε αυτόν τον θεματικό κλάδο στον κύριο κλάδο σας.
Συχνά είναι χρήσιμο να πάρετε μια ανασκόπηση όλων των υποβολών που βρίσκονται σε αυτόν τον κλάδο, αλλά δεν βρίσκονται στον master
σας.
Μπορείτε να αποκλείσετε υποβολές στον master
σας προσθέτοντας την επιλογή --not
πριν από το όνομα του κλάδου.
Αυτό είναι το ίδιο με τη μορφή master..contrib
που χρησιμοποιήσαμε νωρίτερα.
Για παράδειγμα, εάν ο συνεισφέρων σάς στείλει δύο επιθέματα και δημιουργήσετε έναν κλάδο με το όνομα contrib
και εφαρμόσετε αυτά τα επιθέματα εκεί, μπορείτε να τρέξετε το εξής:
$ git log contrib --not master
commit 5b6235bd297351589efc4d73316f0a68d484f118
Author: Scott Chacon <[email protected]>
Date: Fri Oct 24 09:53:59 2008 -0700
See if this helps the gem
commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
Author: Scott Chacon <[email protected]>
Date: Mon Oct 22 19:38:36 2008 -0700
Update gemspec to hopefully work better
Για να δείτε τι αλλαγές εισάγει κάθε υποβολή, ας θυμηθείτε ότι μπορείτε να περάσετε την επιλογή -p
στο git log
και θα προσαρτήσει το αποτέλεσμα της diff που εισήχθη σε κάθε υποβολή.
Για να δείτε το πλήρες diff που θα παίρνατε αν συγχωνεύατε αυτόν τον θεματικό κλάδο με ένα άλλο κλάδο, ίσως χρειαστεί να χρησιμοποιήσετε ένα περίεργο τέχνασμα για να έχετε τα σωστά αποτελέσματα. Ίσως σκεφτείτε να εκτελέσετε το εξής:
$ git diff master
Αυτή η εντολή σας δίνει ένα diff, αλλά μπορεί να είναι παραπλανητικό.
Εάν ο κλάδος σας master
έχει προχωρήσει από τότε που δημιουργήσατε αυτόν τον θεματικό κλάδο, τότε θα πάρετε φαινομενικά παράξενα αποτελέσματα.
Αυτό συμβαίνει επειδή το Git συγκρίνει άμεσα το στιγμιότυπο της τελευταίας υποβολής του θεματικού κλάδου στον οποίο βρισκόμαστε με το στιγμιότυπο της τελευταίας υποβολής στον κλάδο master
.
Για παράδειγμα, αν έχετε προσθέσει μια γραμμή σε ένα αρχείο στον κλάδο master
, μια άμεση σύγκριση των στιγμιότυπων θα μοιάζει σαν ο θεματικός κλάδος να πρόκειται να καταργήσει αυτή τη γραμμή.
Αν ο κλάδος master
είναι άμεσος πρόγονος του θεματικού κλάδου σας, αυτό δεν είναι πρόβλημα· αλλά αν τα δύο ιστορικά έχουν αποκλίνει, η διαφορά θα μοιάζει σαν να προσθέτετε όλα τα νέα στοιχεία στον θεματικό κλάδο και να καταργείτε ό,τι υπάρχει μόνον στον κλάδο master
.
Αυτό που πραγματικά θέλετε να δείτε είναι οι αλλαγές που έχουν προστεθεί στον θεματικό κλάδο — την εργασία που θα εισάγετε αν συγχωνεύσετε αυτόν τον κλάδο με τον κύριο κλάδο. Αυτό μπορείτε να το κάνετε βάζοντας το Git να συγκρίνει την τελευταία υποβολή στον θεματικό κλάδο σας με τον πρώτο κοινό πρόγονο που έχει με τον κύριο κλάδο.
Από τεχνικής άποψης, αυτό μπορείτε να το καταφέρετε αν εντοπίσετε τον κοινό πρόγονο και στη συνέχεια τρέξετε τη διαφορά diff σε αυτό:
$ git merge-base contrib master
36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
$ git diff 36c7db
ή πιο συνεκτικά:
$ git diff $(git merge-base contrib master)
Ωστόσο, κανένα από τα δύο δεν είναι ιδιαίτερα βολικό, γι' αυτό το Git παρέχει μια άλλη συντόμευση για να κάνει το ίδιο πράγμα: τη σύνταξη με τις τρεις τελείες.
Στο πλαίσιο της εντολής diff
, μπορείτε να βάλετε τρεις τελείες μετά από ένα άλλο κλάδο για να κάνετε ένα diff
μεταξύ της τελευταίας υποβολής του κλάδου που βρισκόμαστε και του κοινού προγόνου της με έναν άλλο κλάδο:
$ git diff master...contrib
Αυτή η εντολή σας δείχνει μόνο τη δουλειά που έχει εισάγει ο τρέχων θεματικός κλάδος σας από τον κοινό πρόγονο του με τον master
.
Αυτή είναι μια πολύ χρήσιμη σύνταξη που πρέπει να θυμόμαστε.
Όταν όλη δουλειά στον θεματικό κλάδο σας είναι έτοιμη να ενσωματωθεί σε ένα πιο κεντρικό κλάδο, το ερώτημα που ανακύπτει είναι πώς να το κάνετε. Επιπλέον, ποια ροή εργασίας θέλετε να χρησιμοποιήσετε για να συντηρήσετε το έργο σας; Έχετε αρκετές επιλογές και στη συνέχεια θα καλύψουμε μερικές από αυτές.
Μια απλή ροή εργασίας είναι αυτή στην οποία συγχωνεύετε την εργασία σας στον κλάδο master
.
Σε αυτό το σενάριο, έχετε ένα κύριο κλάδο που περιέχει κυρίως ευσταθή κώδικα.
Όταν εργάζεστε σε έναν θεματικό κλάδο που έχετε φτιάξει ή τον οποίο έχει συνεισφέρει κάποιος και έχετε επαληθεύσει, τον συγχωνεύετε στον master
σας, διαγράφετε τον θεματικό κλάδο και στη συνέχεια συνεχίζετε τη διαδικασία.
Εάν έχετε ένα αποθετήριο με εργασία σε δύο κλάδους που ονομάζονται ruby_client
και php_client
, που μοιάζει με το Ιστορικό με θεματικούς κλάδους., και συγχωνεύσετε πρώτα τον ruby_client
και στη συνέχεια τον php_client
, τότε το ιστορικό σας θα καταλήξει να μοιάζει με το Ιστορικό μετά από συγχώνευση θεματικών κλάδων..
Αυτή είναι πιθανότατα η απλούστερη ροή εργασίας, αλλά μπορεί να είναι προβληματική αν έχετε να κάνετε με μεγαλύτερα ή πιο ευσταθή έργα στα οποία θέλετε να είστε πολύ προσεκτικοί σχετικά με το τι εισάγετε.
Αν έχετε ένα πιο σημαντικό έργο, ίσως θέλετε να χρησιμοποιήσετε έναν κύκλο συγχώνευσης δύο φάσεων.
Σε αυτό το σενάριο έχετε δύο μακρόβιους κλάδους, master
και develop
, στους οποίους καθορίζετε ότι ο master
ενημερώνεται μόνο όταν δημιουργείται μία πολύ σταθερή έκδοση και όλος ο νέος κώδικας είναι ενσωματωμένος στον κλάδο develop
.
Ωθείτε και τους δύο αυτούς κλάδους τακτικά σε ένα δημόσιο αποθετήριο.
Κάθε φορά που έχετε έναν νέο θεματικό κλάδο να συγχωνεύσετε (Πριν από τη συγχώνευση θεματικού κλάδου.), τον συγχωνεύετε στον κλάδο develop
(Μετά τη συγχώνευση θεματικού κλάδου.)· τότε, όταν κάνετε tag μια έκδοση (release), μετακινείτε γρήγορα τον master
σε όποιον κλάδο βρίσκεται ο ευσταθής κλάδος develop
(Μετά τη δημοσιοποίηση έκδοσης.).
Με αυτόν τον τρόπο, όταν κάποιος κλωνοποιεί το αποθετήριο του έργου σας, μπορεί είτε να μεταβεί στον κλάδο master
, να χτίσει την πιο πρόσφατη ευσταθή έκδοση και να συμβαδίζει με αυτή εύκολα, είτε να μεταβεί στον κλάδο develop
, που περιέχει τις πιο πρόσφατες εξελίξεις.
Μπορείτε επίσης να επεκτείνετε αυτό το μοντέλο και να έχετε έναν κλάδο ολοκλήρωσης integrate
στο οποίο όλες οι εργασίες συγχωνεύονται.
Στη συνέχεια, όταν το codebase σε αυτόν τον κλάδο είναι ευσταθές και περνάει τα τεστ, μπορείτε να το συγχωνεύσετε σε έναν κλάδο develop
· και όταν και αυτός έχει αποδειχθεί ευσταθής για κάποιο χρονικό διάστημα, τον ταχυπροωθείτε στον κύριο κλάδο σας.
Το έργο Git έχει τέσσερις μακρόβιους κλάδους: τους master
,` next` και seen
(παλιότερα pu
— proposed updates) για νέες εργασίες και τον maint
για συντήρηση backport.
Όταν εισάγονται νέες εργασίες από συνεργάτες, συλλέγονται σε θεματικούς κλάδους στο αποθετήριο του διαχειριστή με τρόπο παρόμοιο με αυτόν που έχουμε περιγράψει (βλ. Διαχείριση περίπλοκης ακολουθίας παράλληλων συνεισφερθέντων θεματικών κλάδων.).
Σε αυτό το σημείο, τα θέματα αξιολογούνται για να διαπιστωθεί αν είναι ασφαλή και έτοιμα προς κατανάλωση ή αν χρειάζονται περισσότερη δουλειά.
Αν είναι ασφαλή, συγχωνεύονται στον κλάδο next
και αυτός ο κλάδος ωθείται, ώστε όλοι να μπορούν να δοκιμάσουν τα θέματα που ενσωματώθηκαν.
Εάν τα θέματα θέλουν ακόμα δουλίτσα, συγχωνεύονται στον seen
.
Όταν διαπιστωθεί ότι είναι τελείως ευσταθή, τα θέματα επανασυγχωνεύονται στον master
και στη συνέχεια οι κλάδοι next
και seen
γίνονται ξανά build από τον κλάδο master
.
Αυτό σημαίνει ότι ο master
προχωρά σχεδόν πάντα, ο next
επανατοποθετείται περιστασιακά και ο seen
επανατοποθετείται ακόμα πιο συχνά:
Όταν ένας θεματικός κλάδος έχει τελικά συγχωνευτεί στον master
, αφαιρείται από το αποθετήριο.
Το έργο Git διαθέτει επίσης έναν κλάδο maint
που αποσχίζεται (forked) από την τελευταία δημοσιευμένη έκδοση (release) ώστε να παρέχει επιθέματα backport για την περίπτωση που απαιτείται έκδοση συντήρησης.
Έτσι, όταν κλωνοποιείτε το αποθετήριο Git, έχετε τέσσερις κλάδους στους οποίους μπορείτε να μεταβείτε για να αξιολογήσετε το έργο σε διαφορετικά στάδια ανάπτυξης, ανάλογα με το πόσο αιχμής θέλετε να είστε ή πώς θέλετε να συνεισφέρετε· και ο συντηρητής έχει μια δομημένη ροή εργασίας για να τους βοηθήσει να ελέγξουν νέες συνεισφορές.
Άλλοι συντηρητές προτιμούν να επανατοποθετούν (rebase) ή να ανθολογούν (cherry-pick) τις συνεισφορές στην κορυφή του κύριου κλάδου τους, αντί να τις συγχωνεύουν, για να διατηρήσουν ένα κυρίως γραμμικό ιστορικό.
Όταν εργάζεστε σε έναν θεματικό κλάδο και έχετε αποφασίσει ότι θέλετε να τον ενσωματώσετε, μεταβαίνετε σε αυτόν και εκτελείτε την εντολή rebase
για να ξαναχτίσετε τις αλλαγές με νέα βάση τον master
σας (ή τον κλάδο develop
κ.ο.κ.).
Αν αυτό λειτουργεί καλά, τότε μπορείτε να ταχυπροωθήσετε τον κύριο κλάδο σας οπότε θα καταλήξετε με ένα γραμμικό ιστορικό έργου.
Ο άλλος τρόπος για να μετακινήσετε εργασία που εισάγεται από τον ένα κλάδο στον άλλο είναι η ανθολόγηση (cherry-pick). Η ανθολόγηση στο Git είναι σαν μια αλλαγή βάσης μίας μόνο υποβολής. Παίρνει το επίθεμα που εισήχθη σε μια υποβολή και προσπαθεί να το ξαναεφαρμόσει στον κλάδο στον οποίο βρισκόμαστε αυτή τη στιγμή. Η ανθολόγηση είναι χρήσιμη εάν έχετε αρκετές υποβολές σε έναν θεματικό κλάδο και θέλετε να ενσωματώσετε μόνο μία από αυτές ή εάν έχετε μόνο μία υποβολή σε έναν θεματικό κλάδο και προτιμάτε να την ανθολογήσετε αντί να αλλάξετε τη βάση της. Για παράδειγμα, ας υποθέσουμε ότι έχετε ένα έργο που μοιάζει με αυτό:
Αν θέλετε να ελκύσετε την υποβολή e43a6
στον master
, μπορείτε να εκτελέσετε:
$ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf
Finished one cherry-pick.
[master]: created a0a41a9: "More friendly message when locking the index fails."
3 files changed, 17 insertions(+), 3 deletions(-)
Αυτή η εντολή τραβά την ίδια αλλαγή με αυτή που εισήχθη στην e43a6
, αλλά παίρνετε μια νέα τιμή SHA-1 για την υποβολή επειδή η ημερομηνία κατά την οποία εφαρμόστηκε είναι διαφορετική.
Τώρα το ιστορικό σας μοιάζει με αυτό:
Πλέον μπορείτε να καταργήσετε τον θεματικό κλάδο και να εγκαταλείψετε τις υποβολές που δεν θέλατε να ελκύσετε.
Εάν κάνετε πολλές συγχωνεύσεις και αλλαγές βάσης ή διατηρείτε ένα μακρόβιο θεματικό κλάδο, το Git διαθέτει μια λειτουργία που λέγεται rerere
και η οποία μπορεί να σας βοηθήσει.
rerere
σημαίνει “reuse recorded resolution” (“επαναχρησιμοποίηση καταγεγραμμένης επίλυσης”) — είναι ένας τρόπος σύντομης αντιμετώπισης της μη-αυτόματης επίλυσης συγκρούσεων.
Όταν η rerere είναι ενεργοποιημένη, το Git θα διατηρήσει ένα σύνολο εικόνων πριν και μετά από επιτυχείς συγχωνεύσεις και αν παρατηρήσει ότι υπάρχει μια σύγκρουση που μοιάζει ακριβώς με μία που έχετε ήδη επιλύσει, θα χρησιμοποιήσει απλώς το επίθεμα από την τελευταία φορά, χωρίς να σας ενοχλήσει.
Αυτό το χαρακτηριστικό αποτελείται από δύο μέρη: μια παραμετροποίηση και μια εντολή.
Η παραμετροποίηση είναι rerere.enabled
και είναι αρκετά βολική ώστε να την έχετε καθολικό σας αρχείο config:
$ git config --global rerere.enabled true
Τώρα, κάθε φορά που κάνετε μια συγχώνευση που επιλύει διενέξεις, η επίλυση θα καταγράφεται στην κρυφή μνήμη για την περίπτωση που τη χρειαστείτε στο μέλλον.
Αν χρειαστεί, μπορείτε να αλληλεπιδράσετε με τη μνήμη cache rerere χρησιμοποιώντας την εντολή git rerere
.
Όταν καλείται χωρίς διακόπτες, το Git ελέγχει τη βάση δεδομένων επιλύσεων και προσπαθεί να βρει μια αντιστοίχιση με τις τρέχουσες συγκρούσεις συγχώνευσης και να τις επιλύσει (αν και αυτό γίνεται αυτόματα αν το rerere.enabled
οριστεί σε true
).
Υπάρχουν επίσης δευτερεύουσες εντολές για να δείτε τι θα εγγραφεί, να διαγράψετε συγκεκριμένη ανάλυση από την προσωρινή μνήμη και να καθαρίσετε ολόκληρη την προσωρινή μνήμη (cache).
Θα καλύψουμε την rerere με περισσότερες λεπτομέρειες στην ενότητα ch07-git-tools.asc.
Όταν αποφασίσετε να δημοσιοποίησετε μια έκδοση, πιθανώς θέλετε να αφήσετε μια ετικέτα ώστε να μπορείτε να δημιουργήσετε εκ νέου αυτή την έκδοση σε οποιοδήποτε σημείο στο μέλλον. Μπορείτε να δημιουργήσετε μια νέα ετικέτα όπως περιγράφεται στην ενότητα ch02-git-basics.asc. Αν αποφασίσετε να υπογράψετε την ετικέτα ως ο συντηρητής, η ετικέτα μπορεί να φαίνεται κάπως έτσι:
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <[email protected]>"
1024-bit DSA key, ID F721C45A, created 2009-02-09
Εάν υπογράφετε τις ετικέτες σας, μπορεί να έχετε πρόβλημα όσον αφορά στη διανομή του δημόσιου κλειδιού PGP που χρησιμοποιείται για την υπογραφή των ετικετών σας.
Ο συντηρητής του έργου Git έχει επιλύσει αυτό το ζήτημα συμπεριλαμβάνοντας το δημόσιο κλειδί του ως ένα blob στο αποθετήριο και στη συνέχεια προσθέτοντας μια ετικέτα που δείχνει κατευθείαν σε αυτό το περιεχόμενο.
Για να το κάνετε αυτό, πρέπει να καταλάβετε ποιο κλειδί θέλετε εκτελώντας την εντολή gpg --list-keys
:
$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
pub 1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
uid Scott Chacon <[email protected]>
sub 2048g/45D02282 2009-02-09 [expires: 2010-02-09]
Στη συνέχεια, μπορείτε να εισάγετε απευθείας το κλειδί στη βάση δεδομένων Git, αν το εξάγετε και το παροχετεύσετε στο git hash-object
, το οποίο γράφει ένα νέο blob με αυτά τα περιεχόμενα στο Git και σας επιστρέφει τον SHA-1 του blob:
$ gpg -a --export F721C45A | git hash-object -w --stdin
659ef797d181633c87ec71ac3f9ba29fe5775b92
Τώρα που έχετε τα περιεχόμενα του κλειδιού σας στο Git, μπορείτε να δημιουργήσετε μια ετικέτα που να δείχνει απευθείας σε αυτό δίνοντας τη νέα τιμή SHA-1 που σας έδωσε η εντολή hash-object
:
$ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92
Εάν εκτελέσετε git push --tags
, η ετικέτα maintainer-pgp-pub
θα κοινοποιηθεί σε όλους.
Αν κάποιος θέλει να επαληθεύσει μια ετικέτα, μπορεί να εισάγει απευθείας το PGP κλειδί σας τραβώντας το blob απευθείας από τη βάση δεδομένων και εισάγοντάς το στο GPG:
$ git show maintainer-pgp-pub | gpg --import
Μπορεί να χρησιμοποιήσει αυτό το κλειδί για να ελέγξει όλες τις ετικέτες που έχετε υπογράψει.
Επίσης, αν συμπεριλάβετε οδηγίες στο μήνυμα της ετικέτας, η λειτουργία git show <ετικέτα>
θα σας επιτρέψει να δώσετε στον τελικό χρήστη πιο συγκεκριμένες οδηγίες σχετικά με την επαλήθευση ετικετών.
Επειδή το Git δεν έχει αύξοντες αριθμούς όπως v123
ή το ισοδύναμο για τις υποβολές, αν θέλετε να έχετε ένα ανθρωπανάγνωστο όνομα για κάθε υποβολή, μπορείτε να εκτελέσετε git describe
σε αυτή την υποβολή.
Το Git σάς δίνει το όνομα της πλησιέστερης χρονικά ετικέτας με τον αριθμό υποβολών στην κορυφή της ετικέτας και τη μερική τιμή SHA-1 της υποβολής που περιγράφετε (με τον χαρακτήρα “g” στην αρχή, που σημαίνει Git):
$ git describe master
v1.6.2-rc1-20-g8c5b85c
Με αυτό τον τρόπο, μπορείτε να εξάγετε ένα στιγμιότυπο ή build και να τα ονομάσετε με κάτι κατανοητό από ανθρώπους και όχι από μηχανήματα.
Μάλιστα, αν δημιουργήσετε το Git από τον πηγαίο κώδικά του, που έχει κλωνοποιηθεί από το αποθετήριο Git, το git --version
σας δίνει κάτι που μοιάζει με αυτό.
Αν περιγράφετε μια υποβολή, στην οποία έχετε προσαρτήσει μια ετικέτα, σας δίνει το όνομα της ετικέτας.
Η εντολή git describe
απαιτεί επισημασμένες ετικέτες (ετικέτες που δημιουργούνται με τις σημαίες -a
ή -s
).
Αν θέλετε να χρησιμοποιήσετε και τις απλές (μη-επισημασμένες) ετικέτες, προσθέστε την επιλογή --tags
στην εντολή.
Μπορείτε επίσης να χρησιμοποιήσετε αυτή τη συμβολοσειρά ως τον στόχο μιας εντολής git checkout
ή git show
αν και βασίζεται στη συντομευμένη τιμή SHA-1 (τα τελευταία ψηφία), οπότε ίσως να μην ισχύει για πάντα.
Για παράδειγμα, ο πυρήνας Linux αυξήθηκε πρόσφατα από 8 σε 10 χαρακτήρες για να εξασφαλίσει τη μοναδικότητα αντικειμένων SHA-1, με αποτέλεσμα τα παλαιότερα ονόματα που δημιουργήθηκαν από την git describe
να μην είναι έγκυρα πλέον.
Τώρα θέλετε να δημοσιεύσετε μία build.
Ένα από τα πράγματα που θα θελήσετε να κάνετε είναι να δημιουργήσετε ένα αρχείο (archive) του τελευταίου στιγμιότυπου του κώδικά σας για τις φτωχές ψυχές που δεν χρησιμοποιούν το Git.
Η εντολή για να γίνει αυτό είναι git archive
:
$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz
Αν κάποιος ανοίξει αυτό το tarball, θα πάρει το τελευταίο στιγμιότυπο του έργου σας μέσα σε έναν κατάλογο με όνομα project
.
Μπορείτε επίσης να δημιουργήσετε ένα αρχείο zip με τον ίδιο τρόπο, αν περάσετε την επιλογή --format = zip
στην git archive
:
$ git archive master --prefix='project/' --format=zip > `git describe master`.zip
Τώρα έχετε ένα ωραιότατο tarball και ένα αρχείο zip της έκδοσης του έργου σας που μπορείτε να ανεβάσετε στον ιστότοπό σας ή να στείλετε με e-mail σε άλλους.
Ήρθε η ώρα να στείλετε e-mail στα μέλη της mailing list που θέλουν να μάθουν τι συμβαίνει στο έργο σας.
Ένας καλός τρόπος να αποκτήσετε γρήγορα ένα είδος μητρώου αλλαγών (changelog) από ό,τι έχει προστεθεί στο έργο σας από την τελευταία έκδοση ή το e-mail σας είναι να χρησιμοποιήσετε την εντολή git shortlog
.
Συνοψίζει όλες τις υποβολές στο εύρος υποβολών που της δίνετε· για παράδειγμα, παρακάτω δίνεται μια περίληψη όλων των υποβολών από την τελευταία έκδοση, εάν η τελευταία έκδοσή σας ονομάστηκε v1.0.1:
$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (6):
Add support for annotated tags to Grit::Tag
Add packed-refs annotated tag support.
Add Grit::Commit#to_patch
Update version and History.txt
Remove stray `puts`
Make ls_tree ignore nils
Tom Preston-Werner (4):
fix dates in history
dynamic version method
Version bump to 1.0.2
Regenerated gemspec for version 1.0.2
Παίρνετε μια καθαρή σύνοψη όλων των υποβολών από την v1.0.1 και μετά, ομαδοποιημένων κατά συγγραφέα, που μπορείτε να στείλετε με e-mail στη λίστα σας.