-
Notifications
You must be signed in to change notification settings - Fork 119
Repository History
Ένα πρόβλημα που εμφανίζεται συχνά σε μεγάλα αποθετήρια με πολλούς contributors είναι το ιστορικό που μπορεί να μεγαλώσει πάρα πολύ σε μέγεθος, ίσως μετά από fork ενός προηγούμενου αποθετηρίου το οποίο περιέχει χιλιάδες commits ήδη. Το μέγεθος του ιστορικού στο git έχει την παρενέργεια ότι αυξάνει φυσικά το μέγεθος του αποθετήριου και επίσης περιέχει authors που δεν ήταν ποτέ μέρος της προσπάθειας ενός project και κάνει δύσκολη την δουλειά της ανάλυσης των authors και του ιστορικού στην καρτέλα _Insights _του GitHub.
Σαν μέθοδο για να λύσουμε αυτό το πρόβλημα στο δικό μας αποθετήριο είναι η χρήση των git grafts, με την εντολή $ git replace --graft a32be aea18, με τα a32be και aea18 να είναι αντίστοιχα οι πρώτοι 5 χαρακτήρες των CRC checksums του πρώτου και τελευταίου commit που θέλουμε να αφαιρέσουμε από το ιστορικό μας. Η εντολή δημιουργεί το graft σαν placeholder έως ότου να τρέξουμε την εντολή git filter-branch χωρίς φίλτρα για να κλειδώσουμε το graft στο ιστορικό, επαναγράφοντας στην διαδικασία όλα τα commits στο αποθετήριο βάση αυτού ($ git filter-branch --tag-name-filter cat -- --all). Η εντολή κάνει αυτόματα rewrite και τα branches ώστε να είναι σωστά μετά από την εκτέλεση της διαδικασίας.
Άρα με τις δύο προηγούμενες εντολές έχουμε διαγράψει όλα τα commits μεταξύ του πρώτου commit του αποθετηρίου και του πρώτου commit αφότου έχει γίνει fork το αποθετήριο. (ΥΓ: όλα τα checksums των commits έχουν αλλάξει με την εντολή filter-branch γιατί κυριολεκτικά ξαναχτίζουμε όλο το ιστορικό με καινούργια βάση, άρα όλα τα commits ενώ περιέχουν τις ίδιες αλλαγές και authors, είναι διαφορετικά γιατί έχουν διαφορετικό parent commit).
Μία άλλη παρενέργεια αυτής της διαδικασίας είναι το γεγονός ότι κανένας δεν θα μπορεί να κάνει αιτήματα από το παλίο αποθετήριο στο καινούργιο, αφού τα αποθετήρια έχουν "αποκλίσει" (divergent) μετά από το rewrite όλων των commits, θα πρέπει τα fork να γίνουν από το καινούργιο αποθετήριο για να δουλέψουν τα pull request.
Συγκεκριμένα για το δικό μας αποθετήριο βλέπουμε περίπου 1200 λιγότερα commits, κάναμε επαλήθευση των αποτελεσμάτων των παραπάνω εντολών με διάφορους τρόπους:
Για πρώτη επαλήθευση κοιτάμε το ιστορικό από το git init σε γράφο με git log --graph
Όπως βλέπουμε έχει μείνει μόνο το αρχικό commit (initial commit) του αποθετηρίου, με δεύτερο χρονολογικά να είναι το πρώτο commit μετά το fork.
Σαν δεύτερη επαλήθευση του καινούργιου ιστορικού κοιτάμε τα commits μέσω του GitHub
Σαν τρίτη επαλήθευση βλέπουμε το 2ο commit του αποθετηρίου που τώρα είναι το πρώτο commit μετά το fork, και δίνουμε προσοχή στα 821 αλλαγμένα αρχεία και στα 47,000 additions.
Η τέταρτη και τελευταία επαλήθευση είναι ένα clone του παλιού αποθετηρίου ένα φάκελο και τρέχουμε την linux εντολή $ diff (διαφορετική από την εντολή $ git diff) μεταξύ των 2 αποθετηρίων, δεν φαίνεται καμία απολύτως διαφορά στην κατάσταση του φακέλου, άρα και με την τέταρτη επαλήθευση είμαστε σίγουροι ότι δεν έχει αλλάξει το οτιδήποτε εκτώς από το ιστορικό του αποθετηρίου.

Για να μεταφέρουμε το git αποθετήριο τώρα στο καινούργιο του GitHub αποθετήριο πρέπει να δημιουργήσουμε πρώτα ένα καινούργιο αποθετήριο στο GitHub, να το προσθέσουμε σαν remote αποθετήριο στο τοπικό αποθετήριο με την εντολή git remote add new-origin git@github.com:ioniodi/sitegr.git, αφαιρούμε για λόγους ασφαλείας το αρχικό origin remote με την εντολή git remote rm origin για να συνεχίσουμε με push στο καινούργιο αποθετήριο.
Τελικά, χρησιμοποιώντας την εντολή git push -uf new-origin master ωθούμε το αποθετήριο στο καινούργιο GitHub αποθετήριο και δημιουργούμε ταυτόχρονα "tracking branch" με όνομα new-origin που βλέπει τις αλλαγές που γίνονται στο GitHub. (Όλες οι παραπάνω εντολές ενημερώνουν τα όποια τοπικά branches για τις αλλαγές που γίνανε στο master branch, όμως αν θέλουμε να μην έχουμε προβλήματα με το origin στο GitHub θα πρέπει να κάνουμε checkout όλα τα branches για να τα έχουμε τοπικά καθώς εκτελούνται οι εντολές, και έπειτα να κάνουμε $ git push --force --all για να ενημερωθούν όλα τα branches του GitHub.
Σαν αποτέλεσμα, στην καρτέλα των contributors τώρα στο καινούργιο αποθετήριο, βλεπουμε μονο τους δικούς μας contributors.
Επίσης, υπάρχει τρόπος να μετακινήσουμε (αντιγραφή) όλο το wiki από το site-gr (παλίο αποθετήριο) με command line στο καινούργιο αποθετήριο. Αυτό είναι δυνατό μόνο μέσα από εντολές git γιατί το wiki κάθε αποθετηρίου στο GitHub είναι και αυτό ένα αποθετήριο git! Με την εντολή $ git clone https://github.com/ioniodi/site-gr.wiki.git κάνουμε τοπικά clone το αποθετήριο του wiki του παλιού site-gr.
Έπειτα δημιουργούμε ένα κενό wiki στο καινούργιο αποθετήριο, προσθέτουμε σαν remote το wiki του καινούργιου αποθετηρίου στο τοπικό fork του παλιού με την εντολή $ git remote add new-wiki https://github.com/ioniodi/sitegr.wiki.git και για λόγους ασφάλειας αφαιρούμε το παλίο "origin" με την εντολή git remote rm origin. Τελικά, κάνουμε push με $ git push -uf new-wiki master και μπορούμε να δούμε το εντελώς 1-προς-1 αντιγραμμένο wiki στο καινούργιο αποθετήριο!
Επαληθεύουμε ότι είναι ίδια με τον έλεγχο των checksum hashes των commits του wiki.

Ένα μικρό πρόβλημα είναι ότι όποιος χρησιμοποιεί SSH με το git δεν μπορεί να κάνει την δουλειά αυτή, γιατί το GitHub σου δίνει μόνο την HTTPS σύνδεση για να κάνεις clone αποθετήρια των wikis. Πρέπει με το χέρι να μετατρέψεις το HTTPS σε SSH format για να δουλέψει. Μετά η διαδικασία ήταν όπως περιγράφηκε πιο πάνω.

Τα Issues και τα Pull Requests είναι τα τελευταία πράγματα που θα θέλαμε να μεταφέρουμε στο καινούργιο αποθετήριο, τα Pull Request δεν γίνεται να μεταφερθούν όμως οπότε μένουν τα issues. Υπάρχει η δυνατότητα μεταφορά θεμάτων από αποθετήριο σε αποθετήριο αν κάποιος έχει write-access και στα δύο αυτά αποθετήρια.