Skip to content

Latest commit

 

History

History
669 lines (551 loc) · 47.2 KB

client-p4.asc

File metadata and controls

669 lines (551 loc) · 47.2 KB

Git and Perforce

Το Perforce είναι ένα πολύ δημοφιλές σύστημα ελέγχου εκδόσεων σε εταιρικά περιβάλλοντα. Κυκλοφορεί από το 1995, γεγονός που το καθιστά το παλαιότερο σύστημα που καλύπτεται σε αυτό το κεφάλαιο. Ως εκ τούτου, έχει σχεδιαστεί με τους περιορισμούς της εποχής του. Υποθέτει ότι είμαστε πάντα συνδεδεμένοι σε έναν κεντρικό διακομιστή και ότι διατηρείται μόνο μία έκδοση στον τοπικό δίσκο. Βεβαίως, οι λειτουργίες και οι περιορισμοί του είναι κατάλληλα για αρκετά συγκεκριμένα προβλήματα, αλλά υπάρχουν πολλά έργα που χρησιμοποιούν το Perforce στα οποία το Git θα λειτουργούσε πραγματικά καλύτερα.

Υπάρχουν δύο επιλογές αν θέλουμε να συνδυάσουμε τη χρήση του Perforce και του Git. Η πρώτη που θα καλύψουμε είναι η γέφυρα ``Git Fusion'' από τους κατασκευαστές του Perforce, που μας επιτρέπει να εκθέτουμε υποδέντρα μίας αποθήκης Perforce ως αποθετήρια Git για ανάγνωση και εγγραφή. Το δεύτερο είναι το git-p4, μια γέφυρα από την πλευρά του πελάτη, που μας επιτρέπει να χρησιμοποιήσουμε το Git ως πελάτη του Perforce, χωρίς να απαιτήσουμε νέα διαμόρφωση του διακομιστή Perforce.

Git Fusion

Το Perforce παρέχει ένα προϊόν που ονομάζεται Git Fusion (διαθέσιμο στη http://www.perforce.com/git-fusion), το οποίο συγχρονίζει έναν διακομιστή Perforce με αποθετήρια Git στην πλευρά του διακομιστή.

Εγκατάσταση

Για τα παραδείγματα μας, θα χρησιμοποιήσουμε την πιο εύκολη μέθοδο εγκατάστασης για το Git Fusion, η οποία είναι να κατεβάσουμε μία εικονική μηχανή (virtual machine) που τρέχει το δαίμονα Perforce και το Git Fusion. Μπορούμε να πάρουμε την εικόνα της εικονικής μηχανής από το http://www.perforce.com/downloads/Perforce/20-User, και μόλις ολοκληρωθεί η λήψη, την εισάγουμε το στο αγαπημένο μας λογισμικό εικονικοποίησης (θα χρησιμοποιήσουμε το VirtualBox).

Με την πρώτη εκκίνηση του μηχανήματος, μάς ζητά να προσαρμόσουμε τον κωδικό πρόσβασης για τρεις χρήστες Linux (root, perforce και git) και να δώσουμε ένα όνομα στιγμιότυπου, το οποίο μπορεί να χρησιμοποιηθεί για να διακρίνει αυτήν την εγκατάσταση από άλλους στο ίδιο δίκτυο. Όταν όλα αυτά ολοκληρωθούν, θα δούμε τα εξής:

Η οθόνη εκκίνησης εικονικής μηχανής Git Fusion.
Figure 1. Η οθόνη εκκίνησης εικονικής μηχανής Git Fusion.

Θα πρέπει να λάβουμε υπόψη τη διεύθυνση IP που εμφανίζεται εδώ, θα τη χρησιμοποιήσουμε αργότερα. Στη συνέχεια, θα δημιουργήσουμε έναν χρήστη Perforce. Επιλέγουμε `Login'' στο κάτω μέρος και πατάμε Enter (ή SSH στο μηχάνημα) και συνδεόμαστεε ως `root. Στη συνέχεια, χρησιμοποιούμε αυτές τις εντολές για να δημιουργήσουμε έναν χρήστη:

$ p4 -p localhost:1666 -u super user -f john
$ p4 -p localhost:1666 -u john passwd
$ exit

H πρώτη θα ανοίξει έναν επεξεργαστή VI για να εξατομικεύσει τον χρήστη, αλλά μπορούμε να αποδεχτούμε τις προεπιλογές πληκτρολογώντας :wq και πατώντας Enter. Η δεύτερη θα μας ζητήσει να εισαγάγουμε έναν κωδικό πρόσβασης δύο φορές. Αυτό είναι όλο που πρέπει να κάνουμε στο κέλυφος, οπότε βγαίνουμε από τη συνεδρία.

Το επόμενο πράγμα που πρέπει να κάνουμε είναι να πούμε στο Git να μην επαληθεύει τα πιστοποιητικά SSL. Η εικόνα Git Fusion έρχεται με πιστοποιητικό, αλλά είναι για έναν domain που δεν ταιριάζει με τη διεύθυνση IP της εικονικής μηχανής μας, οπότε το Git θα απορρίψει τη σύνδεση HTTPS. Εάν πρόκειται να γίνει μόνιμη εγκατάσταση, συμβουλευόμαστε το εγχειρίδιο του Perforce Git Fusion για να εγκαταστήσουμε ένα διαφορετικό πιστοποιητικό· για τον σκοπό των παραδειγμάτων μας, αυτό αρκεί:

$ export GIT_SSL_NO_VERIFY=true

Τώρα μπορούμε να δοκιμάσουμε ότι όλα λειτουργούν.

$ git clone https://10.0.1.254/Talkhouse
Cloning into 'Talkhouse'...
Username for 'https://10.0.1.254': john
Password for 'https://[email protected]':
remote: Counting objects: 630, done.
remote: Compressing objects: 100% (581/581), done.
remote: Total 630 (delta 172), reused 0 (delta 0)
Receiving objects: 100% (630/630), 1.22 MiB | 0 bytes/s, done.
Resolving deltas: 100% (172/172), done.
Checking connectivity... done.

Η εικόνα εικονικής μηχανής έρχεται εξοπλισμένη με ένα παράδείγμα έργου που μπορούμε να κλωνοποιήσουμε. Εδώ κλωνοποιούμε μέσα από το HTTPS, με τον χρήστη john που δημιουργήσαμε παραπάνω. Το Git ζητά διαπιστευτήρια για αυτήν τη σύνδεση, αλλά η προσωρινή μνήμη των διαπιστευτηρίων θα μας επιτρέψει να παραλείψουμε αυτό το βήμα για τυχόν μεταγενέστερα αιτήματα.

Διαμόρφωση του Git Fusion

Μόλις εγκαταστήσουμε το Git Fusion, θα χρειαστεί να τροποποιήσουμε τη διαμόρφωση. Αυτό γίνεται πραγματικά πολύ εύκολα χρησιμοποιώντας οποιονδήποτε πελάτη Perforce· απλά απεικονίζουμε τον κατάλογο //.git-fusion στον διακομιστή Perforce στον χώρο εργασίας μας. Η δομή του αρχείου είναι η εξής:

$ tree
.
├── objects
│   ├── repos
│   │   └── [...]
│   └── trees
│       └── [...]

├── p4gf_config
├── repos
│   └── Talkhouse
│       └── p4gf_config
└── users
    └── p4gf_usermap

498 directories, 287 files

Ο κατάλογος objects χρησιμοποιείται εσωτερικά από το Git Fusion για να απεικονίσει αντικείμενα Perforce στο Git και το αντίστροφο, δεν θα χρειαστεί να κάνουμε τίποτα εκεί. Υπάρχει ένα καθολικό αρχείο p4gf_config σε αυτόν τον κατάλογο, καθώς και ένα για κάθε αποθετήριο —αυτά είναι τα αρχεία διαμόρφωσης που καθορίζουν τον τρόπο συμπεριφοράς του Git Fusion. Ας ρίξουμε μια ματιά στο αρχείο στη ρίζα:

[repo-creation]
charset = utf8

[git-to-perforce]
change-owner = author
enable-git-branch-creation = yes
enable-swarm-reviews = yes
enable-git-merge-commits = yes
enable-git-submodules = yes
preflight-commit = none
ignore-author-permissions = no
read-permission-check = none
git-merge-avoidance-after-change-num = 12107

[perforce-to-git]
http-url = none
ssh-url = none

[@features]
imports = False
chunked-push = False
matrix2 = False
parallel-push = False

[authentication]
email-case-sensitivity = no

Δεν θα εξηγήσουμε τι είναι η κάθε σημαία εδώ, αλλά ας σημειωθεί ότι αυτό είναι απλά ένα αρχείο κειμένου INI, όπως αυτά που χρησιμοποιεί το Git για τη διαμόρφωση. Αυτό το αρχείο καθορίζει τις γενικές επιλογές, οι οποίες μπορούν στη συνέχεια να αντικατασταθούν από συγκεκριμένα αρχεία διαμόρφωσης για κάθε αποθετήριο, όπως repos/Talkhouse/p4gf_config. Εάν ανοίξουμε αυτό το αρχείο, θα δούμε μια ενότητα [@repo] με ορισμένες ρυθμίσεις που διαφέρουν από τις καθολικές προεπιλογές. Θα δούμε επίσης τμήματα που μοιάζουν με αυτά:

[Talkhouse-master]
git-branch-name = master
view = //depot/Talkhouse/main-dev/... ...

Πρόκειται για μία απεικόνιση μεταξύ κλάδου Perforce και κλάδου Git. Η ενότητα μπορεί να ονομαστεί ό,τι θέλουμε, αρκεί το όνομα να είναι μοναδικό. Η git-branch-name μάς επιτρέπει να μετατρέψουμε μια διαδρομή αποθήκης που θα ήταν δύσχρηστη στο Git σε ένα πιο φιλικό όνομα. Η ρύθμιση view ελέγχει τον τρόπο απεικόνισης των αρχείων Perforce στο αποθετήριο Git χρησιμοποιώντας τη σύνταξη απεικόνισης τυπικής προβολής. Είναι δυνατό να καθοριστούν περισσότερες από μία απεικονίσεις, όπως σε αυτό το παράδειγμα:

[multi-project-mapping]
git-branch-name = master
view = //depot/project1/main/... project1/...
       //depot/project2/mainline/... project2/...

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

Το τελευταίο αρχείο που θα συζητήσουμε είναι το users/p4gf_usermap, το οποίο απεικονίζει χρήστες του Perforce σε χρήστες του Git και ίσως δεν χρειάζεται καν. Κατά τη μετατροπή από μια σειρά αλλαγών Perforce σε μια υποβολή Git, η προεπιλεγμένη συμπεριφορά του Git Fusion είναι να αναζητήσει τον χρήστη του Perforce και να χρησιμοποιήσει τη διεύθυνση e-mail και το πλήρες όνομα που έχει αποθηκευτεί εκεί για το πεδίο συγγραφέα/υποβάλλοντος στο Git. Κατά την αντίστροφη μετατροπή, η προεπιλογή είναι να αναζητήσουμε τον χρήστη Perforce με τη διεύθυνση e-mail που είναι αποθηκευμένη στο πεδίο συγγραφέα της υποβολής Git και να υποβάλουμε το σύνολο αλλαγών ως αυτός ο χρήστης (με την εφαρμογή των αντίστοιχων δικαιωμάτων). Στις περισσότερες περιπτώσεις, αυτή η συμπεριφορά θα δουλέψει μια χαρά, αλλά ας εξετάσουμε το ακόλουθο αρχείο απεικόνισης:

john [email protected] "John Doe"
john [email protected] "John Doe"
bob [email protected] "Anon X. Mouse"
joe [email protected] "Anon Y. Mouse"

Κάθε γραμμή έχει τη μορφή <χρήστης> <email> '<πλήρες όνομα>" και δημιουργεί μία μόνο απεικόνιση χρήστη. Οι δύο πρώτες γραμμές αντιστοιχίζονται σε δύο διαφορετικές διευθύνσεις e-mail στον ίδιο λογαριασμό χρήστη Perforce. Αυτό είναι χρήσιμο αν έχουμε δημιουργήσει υποβολές Git κάτω από πολλές διαφορετικές διευθύνσεις e-mail (ή να αλλάξαμε διεύθυνση e-mail), αλλά θέλουμε να αντιστοιχιστούν στον ίδιο χρήστη Perforce. Κατά τη δημιουργία μιας υποβολής Git από ένα σύνολο αλλαγών Perforce, η πρώτη γραμμή που ταιριάζει με τον χρήστη Perforce χρησιμοποιείται για τις πληροφορίες συγγραφέων Git.

Οι τελευταίες δύο γραμμές καλύπτουν τα πραγματικά ονόματα και τις διευθύνσεις e-mail του Bob και του Joe από τις υποβολές του Git που δημιουργούνται. Αυτό είναι ωραίο αν θέλουμε να ανοίξουμε ένα εσωτερικό έργο, αλλά δεν θέλουμε να δημοσιεύσουμε τον κατάλογο των υπαλλήλων μας σε ολόκληρο τον κόσμο. Ας σημειωθεί ότι οι διευθύνσεις e-mail και τα πλήρη ονόματα θα πρέπει να είναι μοναδικά, εκτός αν θέλουμε όλες οι υποβολές του Git να αποδοθούν σε ένα μόνο φανταστικό συγγραφέα.

Ροή εργασίας

Το Perforce Git Fusion είναι μια αμφίδρομη γέφυρα μεταξύ των ελέγχων εκδόσεων Perforce και Git. Ας ρίξουμε μια ματιά στο τι αίσθηση δημιουργείται όταν εργαζόμαστε από την πλευρά του Git. Υποθέτουμε ότι έχουμε απεικονίσει το έργο ``Jam'' χρησιμοποιώντας ένα αρχείο διαμόρφωσης όπως φαίνεται παραπάνω, τον οποίο μπορούμε να κλωνοποιήσουμε ως εξής:

$ git clone https://10.0.1.254/Jam
Cloning into 'Jam'...
Username for 'https://10.0.1.254': john
Password for 'https://[email protected]':
remote: Counting objects: 2070, done.
remote: Compressing objects: 100% (1704/1704), done.
Receiving objects: 100% (2070/2070), 1.21 MiB | 0 bytes/s, done.
remote: Total 2070 (delta 1242), reused 0 (delta 0)
Resolving deltas: 100% (1242/1242), done.
Checking connectivity... done.
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/rel2.1
$ git log --oneline --decorate --graph --all
* 0a38c33 (origin/rel2.1) Create Jam 2.1 release branch.
| * d254865 (HEAD, origin/master, origin/HEAD, master) Upgrade to latest metrowerks on Beos -- the Intel one.
| * bd2f54a Put in fix for jam's NT handle leak.
| * c0f29e7 Fix URL in a jam doc
| * cc644ac Radstone's lynx port.
[...]

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

Όπως μπορούμε να δούμε, το αποθετήριό μας μοιάζει ακριβώς όπως οποιοδήποτε άλλο αποθετήριο Git με το οποίο μπορούμε να εργαστούμε. Υπάρχουν τρεις κλάδοι και το Git δημιούργησε έναν τοπικό κλάδο master που παρακολουθεί τον origin/master. Ας κάνουμε λίγη δουλίτσα και να δημιουργήσουμε μερικές νέες υποβολές:

# ...
$ git log --oneline --decorate --graph --all
* cfd46ab (HEAD, master) Add documentation for new feature
* a730d77 Whitespace
* d254865 (origin/master, origin/HEAD) Upgrade to latest metrowerks on Beos -- the Intel one.
* bd2f54a Put in fix for jam's NT handle leak.
[...]

Έχουμε δύο νέες υποβολές. Τώρα ας ελέγξουμε αν έχει δουλεψει και κάποιος άλλος:

$ git fetch
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://10.0.1.254/Jam
   d254865..6afeb15  master     -> origin/master
$ git log --oneline --decorate --graph --all
* 6afeb15 (origin/master, origin/HEAD) Update copyright
| * cfd46ab (HEAD, master) Add documentation for new feature
| * a730d77 Whitespace
|/
* d254865 Upgrade to latest metrowerks on Beos -- the Intel one.
* bd2f54a Put in fix for jam's NT handle leak.
[...]

Φαίνεται ότι κάποιος δούλεψε! Δεν θα το γνωρίζατε από αυτήν την προβολή, αλλά η υποβολή 6afeb15 δημιουργήθηκε στην πραγματικότητα χρησιμοποιώντας έναν πελάτη Perforce. Απλώς μοιάζει με μια άλλη υποβολή από τη σκοπιά του Git, και ακριβώς αυτό είναι που θέλουμε. Ας δούμε πώς αντιμετωπίζει ο διακομιστής Perforce μια υποβολή συγχώνευσης:

$ git merge origin/master
Auto-merging README
Merge made by the 'recursive' strategy.
 README | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.
Total 9 (delta 6), reused 0 (delta 0)
remote: Perforce: 100% (3/3) Loading commit tree into memory...
remote: Perforce: 100% (5/5) Finding child commits...
remote: Perforce: Running git fast-export...
remote: Perforce: 100% (3/3) Checking commits...
remote: Processing will continue even if connection is closed.
remote: Perforce: 100% (3/3) Copying changelists...
remote: Perforce: Submitting new Git commit objects to Perforce: 4
To https://10.0.1.254/Jam
   6afeb15..89cba2b  master -> master

Το Git νομίζει ότι λειτούργησε. Ας ρίξουμε μια ματιά στο ιστορικό του αρχείου README από τη σκοπιά του Perforce, χρησιμοποιώντας τη λειτουργία του γραφήματος αναθεώρησης του p4v:

Γράφημα αναθεώρησης Perforce που προκύπτει από ώθηση Git.
Figure 2. Γράφημα αναθεώρησης Perforce που προκύπτει από ώθηση Git.

Εάν δεν έχουμε δει ποτέ αυτήν την προβολή προηγουμένως, μπορεί να φαίνεται συγκεχυμένη, αλλά δείχνει τις ίδιες έννοιες με ένα γραφικό πρόγραμμα προβολής του ιστορικού του Git. Εξετάζουμε το ιστορικό του αρχείου README, έτσι ώστε το δέντρο καταλόγων πάνω αριστερά να δείχνει μόνο αυτό το αρχείο καθώς αναδύεται σε διάφορους κλάδους. Στην επάνω δεξιά στήλη, έχουμε ένα οπτικό γράφημα του πώς σχετίζονται οι διάφορες αναθεωρήσεις του αρχείου και η ευρύτερη εικόνα αυτού του γραφήματος βρίσκεται στο κάτω δεξί μέρος. Η υπόλοιπη προβολή δίνεται στην προβολή λεπτομερειών για την επιλεγμένη αναθεώρηση (2 σε αυτήν την περίπτωση).

Ένα πράγμα που πρέπει να παρατηρήσουμε είναι ότι το γράφημα μοιάζει ακριβώς με το ιστορικό του Git. Το Perforce δεν είχε όνομα κλάδου για να αποθηκεύσει τις υποβολές 1 και` 2`, έτσι έκανε έναν `ανώνυμο'' κλάδο στον κατάλογο `.git-fusion για να τις κρατήσει. Αυτό θα συμβεί επίσης για τα κλάδους Git με όνομα που δεν αντιστοιχίζονται σε έναν κλάδο Perforce με όνομα (και μπορούμε αργότερα να τους αεπικονίσουμε σε κλάδο Perforce χρησιμοποιώντας το αρχείο διαμόρφωσης).

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

Ανακεφαλαίωση Git-Fusion

Εάν έχουμε (ή μπορούμε να αποκτήσουμε) πρόσβαση στον διακομιστή Perforce μας, το Git Fusion είναι ένας πολύ καλός τρόπος για να κάνουμε το Git και το Perforce να μιλάνε το ένας στο άλλο. Εμπλέκεται η διαμόρφωση κάποιων ρυθμίσεων, αλλά η καμπύλη μάθησης δεν είναι πολύ απότομη. Αυτή είναι μία από τις λίγες ενότητες αυτού του κεφαλαίου όπου δεν θα εμφανιστούν προειδοποιήσεις σχετικά με τη χρήση της πλήρους ισχύος του Git. Αυτό δεν σημαίνει ότι το Perforce θα είναι ευχαριστημένο από όλα όσα ρίχνουμε σε αυτό —αν προσπαθήσουμε να ξαναγράψουμε ιστορικό που έχει ήδη ωθηθεί, το Git Fusion θα την απορρίψει— αλλά το Git Fusion προσπαθεί πολύ σκληρά να νιώσει μέρος του Git. Μπορούμε ακόμα να χρησιμοποιήσουμε τις λειτουργικές υπομονάδες Git (αν και θα φαίνονται περίεργες στους χρήστες του Perforce) και να συγχωνεύσουμε κλάδους (αυτό θα καταγραφεί ως ενσωμάτωση στην πλευρά Perforce).

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

git-p4

Η git-p4 είναι μια αμφίδρομη γέφυρα μεταξύ Git και Perforce. Τρέχει εξ ολοκλήρου μέσα στο αποθετήριο Git, επομένως δεν θα χρειαστεί κανενός είδους πρόσβαση στον διακομιστή Perforce (εκτός από τα διαπιστευτήρια χρήστη, φυσικά). Η git-p4 δεν είναι τόσο ευέλικτο ούτε ολοκληρωμένο ως λύση όπως το Git Fusion, αλλά μας επιτρέπει να κάνουμε τα περισσότερα από όσα θέλουμε να κάνουμε χωρίς να επεμβαίνουμε στο περιβάλλον του διακομιστή.

Note

Θα χρειαστούμε το εργαλείο p4 κάπου στο PATH για να εργαστούμε με το git-p4. Όταν γράφεται αυτό το κείμενο, διατίθεται ελεύθερα στη διεύθυνση http://www.perforce.com/downloads/Perforce/20-User.

Εγκατάσταση

Για παράδειγμα, θα τρέχουμε τον διακομιστή Perforce από το Git Fusion OVA, όπως φαίνεται παραπάνω, αλλά θα παρακάμψουμε τον διακομιστή Git Fusion και θα πάμε κατευθείαν στον έλεγχο έκδοσης Perforce.

Για να χρησιμοποιήσουμε τον πελάτη γραμμής εντολών p4 (από τον οποίο εξαρτάται το git-p4), θα χρειαστεί να ορίσουμε μερικές μεταβλητές περιβάλλοντος:

$ export P4PORT=10.0.1.254:1666
$ export P4USER=john
Ξεκινώντας

Όπως και με ο,τιδήποτε στο Git, η πρώτη εντολή είναι να κλωνοποιήσουμε:

$ git p4 clone //depot/www/live www-shallow
Importing from //depot/www/live into www-shallow
Initialized empty Git repository in /private/tmp/www-shallow/.git/
Doing initial import of //depot/www/live/ from revision #head into refs/remotes/p4/master

Αυτό δημιουργεί ό,τι με όρους Git καλείτια ``ρηχός'' κλώνος· μόνο η τελευταία αναθεώρηση Perforce εισάγεται στο Git. Ας θυμηθούμε το Perforce δεν έχει σχεδιαστεί για να παρέχει κάθε αναθεώρηση σε κάθε χρήστη. Αυτό αρκεί για να χρησιμοποιήσουμε το Git ως πελάτη Perforce, αλλά για άλλους σκοπούς δεν είναι αρκετό.

Μόλις τελειώσει, έχουμε έναν πλήρως λειτουργικό αποθετήριο Git:

$ cd myproject
$ git log --oneline --all --graph --decorate
* 70eaf78 (HEAD, p4/master, p4/HEAD, master) Initial import of //depot/www/live/ from the state at revision #head

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

$ git remote -v

Δεν υπάρχουν καθόλου απομακρυσμένες μονάδες σε αυτό το αποθετήριο. Η git-p4 δημιούργησε κάποιες ref ώστε να αναπαριστά την κατάσταση του διακομιστή και αυτές μοιάζουν με απομακρυσμένες αναφορές στην git log, αλλά δεν τις διαχειρίζεται το ίδιο το Git και δεν μπορούμε να τις ωθήσουμε.

Ροή εργασίας

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

$ git log --oneline --all --graph --decorate
* 018467c (HEAD, master) Change page title
* c0fb617 Update link
* 70eaf78 (p4/master, p4/HEAD) Initial import of //depot/www/live/ from the state at revision #head

Έχουμε κάνει δύο νέες υποβολές ότι είμαστε έτοιμοι να υποβάλουμε στον διακομιστή Perforce. Ας ελέγξουμε αν κάποιος άλλος δούλευε σήμερα:

$ git p4 sync
git p4 sync
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
Import destination: refs/remotes/p4/master
Importing revision 12142 (100%)
$ git log --oneline --all --graph --decorate
* 75cd059 (p4/master, p4/HEAD) Update copyright
| * 018467c (HEAD, master) Change page title
| * c0fb617 Update link
|/
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Φαίνεται ότι κάποιος δούλευε και οι master και p4/master έχουν αποκλίνει. Το σύστημα διακλάδωσης της Perforce δεν είναι όπως του Git, οπότε οι υποβολές συγχώνευσης στερούνται νοήματος. Η git-p4 συνιστά να αλλάξουμε τη βάση των υποβολών μας και μάλιστα μας παρέχει και μια συντόμευση για να το κάνουμε:

$ git p4 rebase
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
No changes to import!
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
Applying: Update link
Applying: Change page title
 index.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Είναι ίσως φανερό από την έξοδο, αλλά η git p4 rebase είναι μια συντόμευση για το git p4 sync ακολουθούμενη από git rebase p4/master. Στην πραγματικότητα είναι λίγο πιο έξυπνο από αυτό, ειδικά όταν εργαζόμαστε με πολλαπλούς κλάδους, αλλά αυτή είναι μια καλή προσέγγιση.

Τώρα το ιστορικό μας είναι και πάλι γραμμικό και είμαστε έτοιμοι να συνεισφέρουμε τις αλλαγές μας στο Perforce. Η εντολή git p4 submit θα προσπαθήσει να δημιουργήσει μια νέα έκδοση Perforce για κάθε υποβολή Git μεταξύ του p4/master και master. Αν την τρέξουμε θα ανοίξει τον αγαπημένο μας επεξεργαστή και το περιεχόμενο του αρχείου θα είναι κάτι σαν αυτό:

# A Perforce Change Specification.
#
#  Change:      The change number. 'new' on a new changelist.
#  Date:        The date this specification was last modified.
#  Client:      The client on which the changelist was created.  Read-only.
#  User:        The user who created the changelist.
#  Status:      Either 'pending' or 'submitted'. Read-only.
#  Type:        Either 'public' or 'restricted'. Default is 'public'.
#  Description: Comments about the changelist.  Required.
#  Jobs:        What opened jobs are to be closed by this changelist.
#               You may delete jobs from this list.  (New changelists only.)
#  Files:       What opened files from the default changelist are to be added
#               to this changelist.  You may delete files from this list.
#               (New changelists only.)

Change:  new

Client:  john_bens-mbp_8487

User: john

Status:  new

Description:
   Update link

Files:
   //depot/www/live/index.html   # edit


######## git author [email protected] does not match your p4 account.
######## Use option --preserve-user to modify authorship.
######## Variable git-p4.skipUserNameCheck hides this message.
######## everything below this line is just the diff #######
--- //depot/www/live/index.html  2014-08-31 18:26:05.000000000 0000
+++ /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/index.html   2014-08-31 18:26:05.000000000 0000
@@ -60,7 +60,7 @@
 </td>
 <td valign=top>
 Source and documentation for
-<a href="http://www.perforce.com/jam/jam.html">
+<a href="jam.html">
 Jam/MR</a>,
 a software build tool.
 </td>

Αυτό είναι ως επί το πλείστον το ίδιο περιεχόμενο που θα βλέπαμε αν τρέχαμε την p4 submit, εκτός από τα πράγματα στο τέλος που η git-p4 έχει συμπεριλάβει. Η git-p4 προσπαθεί να τιμά τις ρυθμίσεις τόσο του Git όσο και του Perforce όταν πρέπει να παράσχει ένα όνομα για μια υποβολή ή ένα σύνολο αλλαγών, αλλά σε ορισμένες περιπτώσεις θέλουμε να τις παρκάμψουμε. Για παράδειγμα, εάν η υποβολή Git που εισάγουμε γράφτηκε από έναν συνεισφέροντα που δεν διαθέτει λογαριασμό χρήστη Perforce, ίσως θέλουμε να φαίνεται ότι αυτός έγραψε τα προκύπτοντα σύνολα αλλαγών (και όχι εμείς).

Η git-p4 εισήγαγε με προσοχή το μήνυμα από την υποβολή Git ως το περιεχόμενο αυτού του συνόλου αλλαγών του Perforce, οπότε το μόνο που έχουμε να κάνουμε είναι να αποθηκεύσουμε και να το βγούμε δύο φορές (μία φορά για κάθε υποβολή). Η έξοδος που εκτυπώνεται στο κέλυφος θα φαίνεται κάπως έτσι:

$ git p4 submit
Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Synchronizing p4 checkout...
... - file(s) up-to-date.
Applying dbac45b Update link
//depot/www/live/index.html#4 - opened for edit
Change 12143 created with 1 open file(s).
Submitting change 12143.
Locking 1 files ...
edit //depot/www/live/index.html#5
Change 12143 submitted.
Applying 905ec6a Change page title
//depot/www/live/index.html#5 - opened for edit
Change 12144 created with 1 open file(s).
Submitting change 12144.
Locking 1 files ...
edit //depot/www/live/index.html#6
Change 12144 submitted.
All commits applied!
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
Import destination: refs/remotes/p4/master
Importing revision 12144 (100%)
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
$ git log --oneline --all --graph --decorate
* 775a46f (HEAD, p4/master, p4/HEAD, master) Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Το αποτέλεσμα είναι σαν να κάναμε μία git push, που είναι και η κοντινότερη αναλογία με αυτό που πραγματικά συνέβη.

Υπόψη ότι κατά τη διάρκεια αυτής της διαδικασίας, κάθε υποβολή Git μετατρέπεται σε ένα σύνολο αλλαγών Perforce· αν θέλουμε να τις στριμώξουμε σε ένα ενιαίο σύνολο αλλαγών, μπορούμε να το κάνουμε αυτό με μια διαδραστική αλλαγή βάσης πριν τρέξουμε την git p4 submit. Επίσης, ας σημειωθεί ότι οι αριθμοί SHA-1 όλων των υποβολών που υποβλήθηκαν ως σύνολα αλλαγών έχουν αλλάξει· αυτό συμβαίνει επειδή η git-p4 προσθέτει μια γραμμή στο τέλος κάθε υποβολής που μετατρέπει:

$ git log -1
commit 775a46f630d8b46535fc9983cf3ebe6b9aa53145
Author: John Doe <[email protected]>
Date:   Sun Aug 31 10:31:44 2014 -0800

    Change page title

    [git-p4: depot-paths = "//depot/www/live/": change = 12144]

Τι θα συμβεί αν προσπαθήσουμε να υποβάλουμε μια υποβολή συγχώνευσης; Ας το δοκιμάσουμε. Ακολουθεί η κατάσταση στην οποία βρισκόμαστε:

$ git log --oneline --all --graph --decorate
* 3be6fd8 (HEAD, master) Correct email address
*   1dcbf21 Merge remote-tracking branch 'p4/master'
|\
| * c4689fc (p4/master, p4/HEAD) Grammar fix
* | cbacd0a Table borders: yes please
* | b4959b6 Trademark
|/
* 775a46f Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Τα ιστορικά Git και Perforce αποκλίνουν μετά την 775a46f. Η πλευρά του Git έχει δύο υποβολές, στη συνέχεια μια συγχώνευση υποβολής με την κεφαλή του Perforce, έπειτα μία άλλη υποβολή. Θα προσπαθήσουμε να τα υποβάλουμε στην κορυφή ενός ενιαίου συνόλου αλλαγών στην πλευρά του Perforce. Ας δούμε τι θα συμβεί αν προσπαθήσουμε να υποβάλουμε τώρα:

$ git p4 submit -n
Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Would synchronize p4 checkout in /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Would apply
  b4959b6 Trademark
  cbacd0a Table borders: yes please
  3be6fd8 Correct email address

Η σημαία -n είναι συνοτομογραφία για το --dry-run, το οποίο προσπαθεί να αναφέρει τι θα συνέβαινε εάν η εντολή submit εκτελούνταν πραγματικά. Σε αυτήν την περίπτωση, φαίνεται ότι θα δημιουργούσαμε τρία σύνολα αλλαγών Perforce, τα οποία θα αντιστοιχίζονταν στις τρεις υποβολές (όχι συγχώνευσης) που δεν υπάρχουν ακόμα στον διακομιστή Perforce. Αυτό ακούγεται ότι είναι ακριβώς αυτό που θέλουμε, ας δούμε τι έκβαση θα έχει:

$ git p4 submit
[…]
$ git log --oneline --all --graph --decorate
* dadbd89 (HEAD, p4/master, p4/HEAD, master) Correct email address
* 1b79a80 Table borders: yes please
* 0097235 Trademark
* c4689fc Grammar fix
* 775a46f Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

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

Διακλάδωση

Εάν το έργο Perforce έχει πολλούς κλάδους, δεν είμαστε και τόσο άτυχοι. Η git-p4 μπορεί να το χειριστεί με τρόπο που το δίνει την αίσθηση του Git. Ας υποθέσουμε ότι η αποθήκη Perforce είναι ως εξής:

//depot
  └── project
      ├── main
      └── dev

Και ας πούμε ότι έχουμε έναν κλάδο dev, ο οποίος έχει μία προβολή spec που μοιάζει με αυτό:

//depot/project/main/... //depot/project/dev/...

Η git-p4 μπορεί να εντοπίσει αυτόματα την κατάσταση και να κάνει το σωστό:

$ git p4 clone --detect-branches //depot/project@all
Importing from //depot/project@all into project
Initialized empty Git repository in /private/tmp/project/.git/
Importing revision 20 (50%)
    Importing new branch project/dev

    Resuming with change 20
Importing revision 22 (100%)
Updated branches: main dev
$ cd project; git log --oneline --all --graph --decorate
* eae77ae (HEAD, p4/master, p4/HEAD, master) main
| * 10d55fb (p4/project/dev) dev
| * a43cfae Populate //depot/project/main/... //depot/project/dev/....
|/
* 2b83451 Project init

Ας σημειωθεί ο προδιαγραφέας `@all'' στη διαδρομή αποθήκευσης· αυτό λέει στην `git-p4 να κλωνοποιήσει όχι μόνο το τελευταίο σύνολο αλλαγών για αυτό το υποδέντρο, αλλά όλες τις αλλαγές που έχουν αγγίξει ποτέ αυτές τις διαδρομές. Αυτό είναι πιο κοντά στην αντίληψη του Git για έναν κλώνο, αλλά αν εργαζόμαστε σε ένα έργο με εκτενές ιστορικό, αυτό μπορεί να έχει μεγάλη διάρκεια.

Η σημαία --detect-branches λέει στην git-p4 να χρησιμοποιήσει τις προδιαγραφές κλάδων του Perforce για να απεικονίσει τους κλάδους σε ref του Git. Εάν αυτές οι απεικονίσεις δεν υπάρχουν στον διακομιστή Perforce (και αυτό είναι ένας απόλυτα έγκυρος τρόπος χρήσης του Perforce), μπορούμε να πούμε στην git-p4 ποιες είναι οι απεικονίσεις κλάδων και έχουμε το ίδιο αποτέλεσμα:

$ git init project
Initialized empty Git repository in /tmp/project/.git/
$ cd project
$ git config git-p4.branchList main:dev
$ git clone --detect-branches //depot/project@all .

Η ρύθμιση της μεταβλητής διαμόρφωσης git-p4.branchList σε main:dev λέει στην git-p4 ότι οι main και dev είναι και οι δύο κλάδοι και ο δεύτερος είναι παιδί του πρώτου.

Αν τώρα κάνουμε git checkout -b dev p4/project/dev και μετά κάποιες υποβολές, η git-p4 είναι αρκετά έξυπνη ώστε να θεωρήσει ως στόχο τον σωστό κλάδο όταν κάνουμε git p4 submit. Δυστυχώς, η git-p4 δεν μπορεί να αναμίξει ρηχούς κλώνους και πολλαπλούς κλάδους· εάν έχουμε ένα τεράστιο έργο και θέλουμε να εργαστούμε σε περισσότερους από έναν κλάδους, θα πρέπει να κάνουμε git p4 clone μία φορά για κάθε κλάδο στο οποίο θέλουμε να υποβάλουμε.

Για τη δημιουργία ή την ενοποίηση κλάδων, θα πρέπει να χρησιμοποιήσουμε έναν πελάτη Perforce. Η git-p4 μπορεί μόνο να συγχρονίζει και να υποβάλλει σε υπάρχοντες κλάδους και μάλιστα μπορεί να το κάνει με μόνο μία γραμμική αλλαγή κάθε φορά. Εάν συγχωνεύσουμε δύο κλάδους στο Git και προσπαθήσουμε να υποβάλουμε τη νέα σειρά αλλαγών, όλα αυτά που θα καταγραφούν είναι κάμποσες αλλαγές αρχείων· τα μεταδεδομένα σχετικά με τους κλάδους που εμπλέκονται στην ενσωμάτωση θα χαθούν.

Ανακεφαλαίωση Git και Perforce

Η git-p4 καθιστά δυνατή τη χρήση μιας ροής εργασίας Git με έναν διακομιστή Perforce και είναι αρκετά καλή σε αυτό. Ωστόσο, είναι σημαντικό να θυμόμαστε ότι το Perforce είναι υπεύθυνο για την πηγή και χρησιμοποιούμε το Git μόνο για να εργαστούμε τοπικά. Απλά ας είμαστε πολύ προσεκτικοί σχετικά με την κοινή χρήση των υποβολών του Git· εάν διαθέτουμε έναν απομακρυσμένο κλάδο στον οποίο μπορούν να δουλεύουν άλλοι χρήστες, πρέπει να μην ωθούμε υποβολές που δεν έχουν ήδη υποβληθεί στον διακομιστή Perforce.

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