-
1. Ξεκινώντας με το Git
-
2. Τα θεμελιώδη στοιχεία του Git
-
3. Διακλαδώσεις στο Git
-
4. Το Git στον διακομιστή
- 4.1 Τα πρωτόκολλα
- 4.2 Εγκατάσταση του Git σε διακομιστή
- 4.3 Δημιουργία δημόσιου κλειδιού SSH
- 4.4 Στήσιμο του διακομιστή
- 4.5 Δαίμονες του Git
- 4.6 Έξυπνο HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Επιλογές φιλοξενίας από τρίτους
- 4.10 Ανακεφαλαίωση
-
5. Κατανεμημένο Git
-
6. GitHub
-
7. Εργαλεία του Git
- 7.1 Επιλογή αναθεώρησης
- 7.2 Διαδραστική εργασία με το στάδιο καταχώρισης
- 7.3 Αποθέματα και Καθαρισμός
- 7.4 Υπογραφή της δουλειάς μας
- 7.5 Αναζήτηση
- 7.6 Η ιστορία ξαναγράφεται
- 7.7 Απομυθοποίηση της reset
- 7.8 Προχωρημένη Συγχώνευση
- 7.9 Rerere
- 7.10 Αποσφαλμάτωση με το Git
- 7.11 Υπομονάδες
- 7.12 Δεμάτιασμα δεδομένων
- 7.13 Replace
- 7.14 Αποθήκευση διαπιστευτηρίων
- 7.15 Ανακεφαλαίωση
-
8. Εξατομίκευση του Git
-
9. Το Git και άλλα συστήματα
- 9.1 Το Git ως πελάτης
- 9.2 Μετανάστευση στο Git
- 9.3 Ανακεφαλαίωση
-
10. Εσωτερική λειτουργία του Git
- 10.1 Διοχετεύσεις και πορσελάνες
- 10.2 Αντικείμενα του Git
- 10.3 Αναφορές του Git
- 10.4 Πακετάρισμα αρχείων
- 10.5 Τα refspec
- 10.6 Πρωτόκολλα μεταφοράς
- 10.7 Διατήρηση και ανάκτηση δεδομένων
- 10.8 Μεταβλητές περιβάλλοντος
- 10.9 Ανακεφαλαίωση
-
A1. Appendix A: Το Git σε άλλα περιβάλλοντα
- A1.1 Γραφικές διεπαφές
- A1.2 Το Git στο Visual Studio
- A1.3 Git στο Visual Studio Code
- A1.4 Git στο IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git στο Sublime Text
- A1.6 Το Git στο Bash
- A1.7 Το Git στο Zsh
- A1.8 Το Git στο Powershell
- A1.9 Ανακεφαλαίωση
-
A2. Appendix B: Ενσωμάτωση του Git στις εφαρμογές μας
- A2.1 Γραμμή εντολών Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Appendix C: Εντολές Git
- A3.1 Ρύθμιση και διαμόρφωση
- A3.2 Λήψη και δημιουργία έργων
- A3.3 Βασική λήψη στιγμιοτύπων
- A3.4 Διακλάδωση και συγχώνευση
- A3.5 Κοινή χρήση και ενημέρωση έργων
- A3.6 Επιθεώρηση και σύγκριση
- A3.7 Αποσφαλμάτωση
- A3.8 Επιθέματα
- A3.9 Ηλεκτρονικό ταχυδρομείο
- A3.10 Εξωτερικά Συστήματα
- A3.11 Διοίκηση
- A3.12 Εντολές διοχέτευσης
7.6 Εργαλεία του Git - Η ιστορία ξαναγράφεται
Η ιστορία ξαναγράφεται
Πολλές φορές όταν εργαζόμαστε με το Git, μπορεί να θέλουμε να αναθεωρήσουμε το ιστορικό των υποβολών μας για κάποιο λόγο.
Ένα από τα σπουδαία πράγματα για το Git είναι ότι μας επιτρέπει να λαμβάνουμε αποφάσεις την τελευταία δυνατή στιγμή.
Μπορούμε να αποφασίσουμε ποια αρχεία πηγαίνουν σε ποια υποβολή αμέσως πριν τα υποβάλλουμε στο στάδιο καταχώρισης, μπορούμε να αποφασίσουμε ότι δεν θέλαμε ακόμα να εργαζόμαστε σε κάτι με την εντολή git stash και μπορούμε να ξαναγράψουμε υποβολές που έχουν ήδη γίνει, έτσι ώστε να φαίνεται ότι συνέβησαν με διαφορετικό τρόπο.
Αυτό μπορεί να συνεπάγεται την αλλαγή της σειράς των υποβολών, την αλλαγή μηνυμάτων ή την τροποποίηση των αρχείων σε μια υποβολή, τον συνδυασμό ή διαχωρισμό υποβολών, ή την πλήρη κατάργηση των υποβολών —όλα αυτά προτού μοιραστούμε τη δουλειά μας με άλλους.
Σε αυτήν την ενότητα, θα καλύψουμε τον τρόπο επίτευξης αυτών των πολύ χρήσιμων εργασιών, ώστε να μπορούμε να κάνουμε το ιστορικό των υποβολών μας να έχει τη μορφή που θέλουμε πριν τη μοιραστούμε με άλλους.
|
Note
|
Μην ωθείτε την δουλειά σας μέχρι να είτε ευχαριστημένοι με αυτήν
Ένας από τους θεμελιώδες κανόνες του Git είναι ότι, εφόσον τόση πολλή δουλειά είναι τοπικά μέσα στον κλώνο (clone), έχουμε μεγάλη ελευθερία να ξαναγράψουμε το ιστορικό τοπικά. Ωστόσο, μόλις ωθήσουμε την δουλειά μας, είναι μια τελειώς διαφορετική ιστορία, και θα πρέπει να μεριμνούμε να ωθούμε την δουλειά τελειωμένη, εκτός αν έχουμε έναν καλό λόγο για να την αλλάξουμε. Έν συντομία, θα πρέπει να αποφεύγουμε να ωθούμε την δουλειά μας μέχρι να είμαστε ευχαριστημένοι με αυτή και έτοιμοι να την μοιραστούμε με τον υπόλοιπο κόσμο. |
Αλλαγή της τελευταίας υποβολής
Η αλλαγή της τελευταίας μας υποβολής είναι πιθανώς η πιο συνηθισμένη επανεγγραφή ιστορικού που θα κάνουμε. Θα θέλουμε συχνά να κάνουμε δύο βασικά πράγματα στην τελευταία μας υποβολή: να αλλάξουμε το μήνυμα υποβολής ή να αλλάξουμε το στιγμιότυπο που μόλις καταγράψαμε προσθέτοντας, αλλάζοντας και αφαιρώντας αρχεία.
Αν θέλουμε να τροποποιήσουμε μόνο το τελευταίο μας μήνυμα, τα πράγματα είναι πολύ απλά:
$ git commit --amend
Αυτό μας μεταφέρει στον επεξεργαστή κειμένων μας, ο οποίος έχει το τελευταίο μας μήνυμα υποβολής σε αυτό, έτοιμο να το τροποποιήσουμε. Όταν αποθηκεύουμε και κλείνουμε τον επεξεργαστή, ο επεξεργαστής γράφει μια νέα υποβολή που περιέχει αυτό το μήνυμα και κάνει αυτήν, τη νέα μας τελευταία υποβολή.
Αν από την άλλη θέλουμε να αλλάξουμε το περιεχόμενο της τελευταίας υποβολής μας, η διαδικασία λειτουργεί με τον ίδιο τρόπο — ορώτα κάνουμε τις αλλαγές που νομιζούμε ότι ξεχάσαμε, βάζουμε στο στάδιο καταχώρισης αυτές τις αλλαγές, και στη συνέχεια git commit --amend αντικαθιστά τη τελευταία υποβολή με την νέα, βελτιωμένη υποβολή.
Πρέπει να είμαστε προσεκτικοί με αυτήν την τεχνική επειδή η amend τροποποιεί τον αριθμό SHA-1 της υποβολής.
Είναι σαν ένα πολύ μικρό rebase —δεν πρέπει να τροποποιοιούμε την τελευταία μας υποβολή εάν την έχουμε ήδη ωθήσει.
|
Tip
|
Μια τροποποιημένη υποβολή μπορεί (ή μπορεί να μην) χρειάζεται τροποποιημένο μήνυμα υποβολής
Όταν τροποποιούμε μια υποβολή, έχουμε την ευκαιρία να αλλάξουμε και τα δύο: το μήνυμα υποβολής και το περιεχόμενο της υποβολής. Αν τροποποιήσουμε το περιεχόμενο της υποβολής ουσιαστικά, θα πρέπει σχεδόν σίγουρα να αλλάξουμε το μήνυμα υποβολής για να αντικατοπτρήζει το τροποποιημένο περιεχόμενο. Από την άλλη, αν οι τροποποιήσεις είναι σχετικά απλές (διόρθωση ενός τυπογραφικού ή προσθήκη ενός αρχείου που ξεχάσαμε να βάλουμε στο στάδιο καταχώρισης) τότε το προηγούμενο μήνυμα υποβολής είναι μια χαρά, μπορούμε απλώς να κάνουμε τις αλλαγές, να τις βάλουμε στο στάδιο καταχώρισης, και να αποφύγουμε τον μη αναγκαίο επεξεργαστή κειμένου, με την εντολή:
|
Αλλαγή πολλών μηνυμάτων υποβολών
Για να τροποποιήσουμε μια υποβολή που είναι πιο πίσω στο ιστορικό μας, πρέπει να χρησιμοποιήσουμε πιο πολύπλοκα εργαλεία.
Το Git δεν διαθέτει ένα εργαλείο τροποποίησης ιστορικού, αλλά μπορούμε να χρησιμοποιήσουμε το εργαλείο rebase για να αλλάξουμε τη βάση μιας σειράς υποβολών στον HEAD στον οποίο είχαν αρχικά βασιστεί αντί να τις μετακινήσουμε σε κάποιον άλλο.
Με το εργαλείο διαδραστικής αλλαγής βάσης, μπορούμε στη συνέχεια να σταματήσουμε μετά από κάθε υποβολή που θέλουμε να τροποποιήσουμε και να αλλάξουμε το μήνυμα, να προσθέσουμε αρχεία ή να κάνουμε ό,τι επιθυμούμε.
Μπορούμε να εκτελέσουμε την rebase διαδραστικά προσθέτοντας την επιλογή -i στην git rebase.
Πρέπει να υποδείξουμε πόσο πίσω θέλουμε να ξαναγράψουμε τις υποβολές λέγοντας στην εντολή ποια υποβολή να είναι η νέα βάση.
Για παράδειγμα, εάν θέλουμε να αλλάξουμε τα τελευταία τρία μηνύματα υποβολής ή κάποιο από αυτά τα μηνύματα υποβολής, δίνουμε ως όρισμα στην git rebase -i τον γονέα της τελευταίας υποβολής που θέλουμε να επεξεργαστούμε, που είναι HEAD~2^ ή HEAD~3.
Μπορεί να είναι πιο εύκολο να θυμηθούμε το ~3 επειδή προσπαθούμε να επεξεργαστούμε τις τελευταίες τρεις υποβολές· αλλά καλό είναι θυμόμαστε ότι στην πραγματικότητα πηγαίνουμε τέσσερις υποβολές πιο πριν, στον γονέα της τελευταίας υποβολής που θέλουμε να επεξεργαστούμε:
$ git rebase -i HEAD~3
Ας θυμηθούμε ξανά ότι αυτή είναι μια εντολή αλλαγής βάσης —κάθε υποβολή που περιλαμβάνεται στο εύρος HEAD~3..HEAD με αλλαγμένο μήνυμα και όλοι οι απόγονοι θα ξαναγραφούν.
Δεν πρέπει να συμπεριλάβουμε καμία υποβολή που έχουμε ήδη ωθήσει σε κάποιον κεντρικό διακομιστή —αυτό θα προκαλέσει σύγχυση στους άλλους προγραμματιστές, αφού θα τους παρέχει μία εναλλακτική έκδοση της ίδιας αλλαγής.
Η εκτέλεση αυτής της εντολής μάς δίνει μια λίστα υποβολών στον επεξεργαστή κειμένου μας που μοιάζει με κάτι σαν αυτό:
pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
Είναι σημαντικό να σημειώσουμε ότι αυτές οι υποβολές παρατίθενται με την αντίθετη σειρά από αυτήν που συνήθως βλέπουμε όταν χρησιμοποιούμε την εντολή log.
Αν εκτελέσουμε την `log ', θα δούμε κάτι σαν αυτό:
$ git log --pretty=format:"%h %s" HEAD~3..HEAD
a5f4a0d Add cat-file
310154e Update README formatting and add blame
f7f3f6d Change my name a bit
Η σειρά είναι αντίστροφη.
Η διαδραστική αλλαγή βάσης μάς δίνει ένα script, το οποίο και θα τρέξει.
Θα ξεκινήσει από την υποβολή που καθορίσαμε στη γραμμή εντολών (HEAD~3) και θα ξαναβάλει (replay) τις αλλαγές που εισήχθησαν σε καθεμία από αυτές τις υποβολές από πάνω προς τα κάτω.
Εμφανίζει την παλαιότερη στην κορυφή, αντί για την πιο πρόσφατη, επειδή είναι η πρώτη που θα ξαναμπεί.
Πρέπει να επεξεργαστούμε το script έτσι ώστε να σταματήσει στην υποβολή που θέλουμε να επεξεργαστούμε. Για να το κάνουμε αυτό, αλλάζουμε τη λέξη “pick” στη λέξη “edit” για καθεμία από τις υποβολές στην οποία θέλουμε να σταματήσει το script. Για παράδειγμα, για αν θέλουμε μόνο να τροποποιήσουμε το μήνυμα της τρίτης υποβολής, αλλάζουμε το αρχείο έτσι ώστε να φαίνεται ως εξής:
edit f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
Όταν αποθηκεύσουμε και κλείσουμε τον επεξεργαστή, το Git μάς επιστρέφει στην τελευταία υποβολή της λίστας και μας πετάει στη γραμμή εντολών με το ακόλουθο μήνυμα:
$ git rebase -i HEAD~3
Stopped at f7f3f6d... Change my name a bit
You can amend the commit now, with
git commit --amend
Once you're satisfied with your changes, run
git rebase --continue
Αυτές οι οδηγίες μάς λένε ακριβώς τι να κάνουμε. Πληκτρολογούμε:
$ git commit --amend
Αλλάζουμε το μήνυμα υποβολής και βγαίνουμε από τον επεξεργαστή. Τότε τρέχουμε:
$ git rebase --continue
Αυτή η εντολή θα εφαρμόσει αυτόματα τις άλλες δύο υποβολές και τελειώσαμε.
Εάν αλλάξουμε το pick σε edit σε περισσότερες γραμμές, θα επαναλάβουμε αυτά τα βήματα για κάθε υποβολή που αλλάξαμε σε edit.
Κάθε φορά, το Git θα σταματήσει, θα μας επιτρέψει να τροποποιήσουμε την υποβολή και να συνεχίσουμε όταν τελειώσουμε.
Αλλαγή βάσης υποβολών
Μπορούμε επίσης να χρησιμοποιήσουμε διαδραστικές αλλαγές βάσης για να αναδιατάξουμε ή να αφαιρέσουμε πλήρως υποβολές. Εάν θέλουμε να αφαιρέσουμε την υποβολή “Add cat-file” και να αλλάξουμε τη σειρά με την οποία εισήχθησαν οι άλλες δύο υποβολές, μπορούμε να αλλάξουμε το script αλλαγής βάσης από αυτό:
pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
σε αυτό:
pick 310154e Update README formatting and add blame
pick f7f3f6d Change my name a bit
Όταν αποθηκεύουμε και εξερχόμαστε από τον επεξεργαστή, το Git επιστρέφει τον κλάδο μας στον γονέα αυτών των υποβολών, εφαρμόζει την 310154e και στη συνέχεια f7f3f6d και στη συνέχεια σταματά.
Ουσιαστικά αλλάζουμε τη σειρά αυτών των υποβολών και αφαιρούμε πλήρως την υποβολή “Add cat-file”.
Squashing Commits
Είναι επίσης δυνατό να πάρουμε μιας ακολουθία υποβολών και να τις ενώσουμε (squash) σε μια ενιαία υποβολή με το εργαλείο διαδραστικής αλλαγής βάσης.
Το script παρέχει χρήσιμες οδηγίες στο μήνυμα της rebase:
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
Εάν, αντί για “pick” ή “edit”, καθορίσουμε “squash”, το Git εφαρμόζει τόσο αυτήν την υποβολή όσο και την υποβολή ακριβώς πριν από αυτήν και μας κάνει να συγχωνεύσουμε τα μηνύματα των υποβολών. Επομένως εάν θέλουμε να πραγματοποιήσουμε μόνο μία υποβολή από αυτές τις τρεις υποβολές, θα κάνουμε το script να μοιάζει με αυτό:
pick f7f3f6d Change my name a bit
squash 310154e Update README formatting and add blame
squash a5f4a0d Add cat-file
Όταν αποθηκεύσουμε και βγούμε από τον επεξεργαστή, το Git εφαρμόζει και τις τρεις αλλαγές και στη συνέχεια μας επαναφέρει στον επεξεργαστή για να συγχωνεύσουμε τα τρία μηνύματα υποβολής:
# This is a combination of 3 commits.
# The first commit's message is:
Change my name a bit
# This is the 2nd commit message:
Update README formatting and add blame
# This is the 3rd commit message:
Add cat-file
Όταν το αποθηκεύσουμε αυτό, θα έχουμε μόνο μία υποβολή που εισάγει τις αλλαγές και των τριών προηγούμενων υποβολών.
Διαχωρισμός υποβολών
Ο διαχωρισμός μιας υποβολής αναιρεί την υποβολή και στη συνέχεια προσθέτει στο στάδιο καταχώρισης και υποβάλλει τόσες υποβολές όσες θέλουμε.
Για παράδειγμα, ας υποθέσουμε ότι θέλουμε να χωρίσουμε τη μεσαία από τις τρεις υποβολές μας.
Αντί της “Update README formatting and add blame”, θέλουμε να τη χωρίσουμε σε δύο υποβολές: “Update README formatting” για την πρώτη και “Add blame” για τη δεύτερη.
Μπορούμε να το κάνουμε αυτό στο script rebase -i αλλάζοντας την εντολή για την υποβολή που θέλουμε να χωρίσουμε σε “edit”:
pick f7f3f6d Change my name a bit
edit 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
Στη συνέχεια, όταν το script μάς βγάζει στη γραμμή εντολών, επαναφέρουμε (reset) αυτήν την υποβολή, παίρνουμε τις αλλαγές που έχουν αναιρεθεί και δημιουργούμε πολλαπλές υποβολές από αυτές τις αλλαγές.
Όταν αποθηκεύουμε και βγαίνουμε από τον επεξεργαστή κειμένου, το Git επιστρέφει στον γονέα της πρώτης υποβολής της λίστας, εφαρμόζει την πρώτη υποβολή (f7f3f6d), εφαρμόζει τη δεύτερη (310154e) και μας επαναφέρει στην κονσόλα.
Εκεί, μπορούμε να εκτελέσουμε μια μεικτή επαναφορά αυτής της υποβολής με την git reset HEAD^, το οποίο ουσιαστικά αναιρεί αυτήν την υποβολή και αφήνει τα τροποποιημένα αρχεία εκτός σταδίου καταχώρισης.
Τώρα μπορούμε να προσθέσουμε αρχεία στο στάδιο καταχώρισης και να τα υποβάλλουμε μέχρι να έχουμε αρκετές υποβολές και τρέχουμε την git rebase --continue όταν τελειώσουμε:
$ git reset HEAD^
$ git add README
$ git commit -m 'Update README formatting'
$ git add lib/simplegit.rb
$ git commit -m 'Add blame'
$ git rebase --continue
Το Git εφαρμόζει την τελευταία υποβολή (a5f4a0d) στο script και το ιστορικό μας μοιάζει με αυτό:
$ git log -4 --pretty=format:"%h %s"
1c002dd Add cat-file
9b29157 Add blame
35cfb2b Update README formatting
f7f3f6d Change my name a bit
Αυτό αλλάζει τους αριθμούς SHA-1 των τριών τελευταίων υποβολών στη λίστα μας, οπότε θα πρέπει να βεβαιωθούμε ότι καμία αλλαγμένη υποβολή δεν εμφανίζεται σε αυτή τη λίστα που έχουμε ήδη ωθήσει στο κοινόχρηστο αποθετήριο.
Παρατηρούμε ότι η τελευταία υποβολή (f7f3f6d) σε αυτή τη λίστα είναι αμετάβλητη.
Άσχετα που αυτή η υποβολή εμφανιζόταν στο script, επειδή ήταν σημειωμένη ως “pick” και εφαρμόστηκε πριν από τις αλλαγές βάσης (rebase changes), το Git αφήνει την υποβολή αμετάβλητη.
Διαγραφή μιας υποβολής
Αν θέλουμε να απαλλαγούμε από μια υποβολή, μπορούμε να την διαγράψουμε χρησιμοποιώντας το rebase -i script.
Στην λίστα με τις υποβολές, βάζουμε την λέξη “drop” πριν την υποβολή που θέλουμε να διαγράψουμε (ή απλώς διαγράφουμε αυτή τη γραμμή από το rebase script):
pick 461cb2a This commit is OK
drop 5aecc10 This commit is broken
Λόγω του τρόπου που το Git χτίζει τα αντικείμενα υποβολών, διαγράφοντας ή αλλάζοντας μια υποβολή θα προκαλέσει το ξανγραάψιμο όλων των υποβολών που το ακολουθούν. Όσο πιο πίσω πάμε στην ιστορία του αποθετηρίου μας πάμε, τόσο πιο πολλές υποβολές θα χρειαστεί να ξαναδημιουργηθούν. Αυτό μπορεί να δημιουργήσει πολλές συγκρούσεις συγχωνεύσεων αν έχουμε πολλές υποβολές πίσω στην σειρά που βασίζονται σε αυτήν που μόλις διαγράψαμε.
Αν τα καταφέρουμε μέχρι την μέση μιας αλλαγής βάσης όπως αυτής και αποφασίσουμε ότι δεν είναι καλή ιδεά να συνεχίσουμε, μπορούμε πάντα να σταματήσουμε.
Πληκτρολογούμε git rebase --abort, και το αποθετήριο θα επιστρέψει στη κατάσταση που ήταν πριν αρχίσουμε την αλλαγή βάσης (rebase).
Αν τελειώσαμε την αλλαγή βάσης (rebase) και αποφασίσουμε ότι δεν είναι αυτο που θέλουμε, μπορούμε να χρησιμοποιήσουμε git reflog για να ανακτήσουμε μια προηγούμενη έκδοση του κλάδου μας.
Βλ. Ανάκτηση δεδομένων για περισσότερες πληροφορίες της εντολής reflog.
|
Note
|
Ο Drew DeVault έκανε ένα πρακτικό οδηγό με ασκήσεις για να μάθουμε πως να χρησιμοποιούμε την |
Η πυρηνική επιλογή: filter-branch
Υπάρχει μια άλλη επιλογή επανεγγραφής ιστορικού που μπορούμε να χρησιμοποιήσουμε αν χρειάζεται να ξαναγράψουμε έναν μεγαλύτερο αριθμό υποβολών χρησιμοποιώντας script —π.χ. για να αλλάξουμε τη διεύθυνση e-mail μας παντού ή να αφαιρέσουμε ένα αρχείο από κάθε υποβολή.
Η σχετική εντολή είναι η filter-branch και μπορεί να ξαναγράψει τεράστια τμήματα του ιστορικού μας, επομένως ενδεχομένως δεν πρέπει να τη χρησιμοποιήσουμε, εκτός εάν το έργο μας δεν είναι ακόμη δημόσια και άλλοι δεν έχουν βασίσει τη δουλειά τους στις υποβολές που πρόκειται να ξαναγράψουμε.
Ωστόσο, μπορεί να είναι πολύ χρήσιμο.
Θα δούμε μερικές κοινές χρήσεις της, ώστε να έχουμε μια ιδέα για κάποια από τα πράγματα που είναι σε θέση να κάνει.
|
Caution
|
Η |
Αφαίρεση ενός αρχείου από κάθε υποβολή
Αυτό συμβαίνει αρκετά συχνά.
Κάποιος υποβάλλει ένα τεράστιο δυαδικό αρχείο με ένα άσκοπο git add . και θέλουμε να το αφαιρέσουμε από παντού.
Ίσως υποβάλαμε κατά λάθος ένα αρχείο που περιείχε έναν κωδικό πρόσβασης και θέλουμε να κάνουμε το έργο μας ανοιχτή πρόσβασης.
Η filter-branch είναι το εργαλείο που θέλουμε να χρησιμοποιήσουμε για να συμμαζέψουμε ολόκληρο το ιστορικό μας.
Για να καταργήσουμε ένα αρχείο που ονομάζεται passwords.txt από παντού στο ιστορικό μας, μπορούμε να χρησιμοποιήσουμε την επιλογή --tree-filter με την filter-branch:
$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
Ref 'refs/heads/master' was rewritten
Η επιλογή --tree-filter εκτελεί την εντολή που έχει οριστεί μετά από κάθε ενημέρωση (checkout) του έργου και κατόπιν ξαναϋποβάλει τα αποτελέσματα.
Σε αυτήν την περίπτωση, αφαιρούμε ένα αρχείο που ονομάζεται passwords.txt από κάθε στιγμιότυπο, είτε υπάρχει είτε όχι.
Αν θέλουμε να καταργήσουμε όλα τα αρχεία backup του επεξεργαστή κειμένου που υποβλήθηκαν κατά λάθος, μπορούμε να εκτελέσουμε κάτι σαν την git filter-branch --tree-filter 'rm -f *~' HEAD.
Θα δούμε το Git να ξαναγράφει δέντρα και υποβολές και στη συνέχεια να μετακινήσει τον δείκτη του κλάδου στο τέλος.
Γενικά είναι καλή ιδέα να κάνουμε κάτι τέτοιο σε κάποιον δοκιμαστικό κλάδο και στη συνέχεια να επαναφέρουμε σκληρά (hard reset) τον master κλάδο αφού έχουμε βεβαιωθεί ότι το αποτέλεσμα είναι αυτό που πραγματικά θέλουμε.
Για να εκτελέσουμε το filter-branch σε όλους τους κλάδους μας, μπορούμε να περάσουμε την επιλογή --all στην εντολή.
Κάνοντας έναν υποκατάλογο τη νέα ρίζα
Ας υποθέσουμε ότι έχουμε πραγματοποιήσει εισαγωγή από ένα άλλο σύστημα ελέγχου και έχουμε υποκαταλόγους που δεν έχουν νόημα (κορμός, ετικέτες κ.ο.κ.).
Αν θέλουμε ο υποκατάλογος trunk να γίνει ο νέος ριζικός κατάλογος του έργου για κάθε υποβολή, η filter-branch μπορεί να μας βοηθήσει και σ' αυτό:
$ git filter-branch --subdirectory-filter trunk HEAD
Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
Ref 'refs/heads/master' was rewritten
Τώρα, η νέα ρίζα του έργου είναι ό,τι υπήρχε στον υποκατάλογο trunk κάθε φορά.
Επιπλέον το Git θα καταργήσει αυτόματα υποβολές που δεν επηρέασαν τον υποκατάλογο.
Αλλαγή διευθύνσεων e-mail παντού
Μια άλλη συνηθισμένη περίπτωση είναι ότι ξεχάσαμε να εκτελέσουμε την git config για να ορίσουμε το όνομα και τη διεύθυνση e-mail μας πριν αρχίσουμε να εργαζόμαστε ή ίσως θέλουμε να κάνουμε δημόσιο ένα έργο που είχαμε στον χώρο εργασίας μας και γι' αυτό θέλουμε να αλλάξουμε όλες τις διευθύνσεις e-mail από αυτήν της εργασίας μας στην προσωπική μας διεύθυνση.
Σε κάθε περίπτωση, μπορούμε να αλλάξουμε τις διευθύνσεις e-mail σε πολλαπλές υποβολές με τη μία επίσης με την filter-branch.
Πρέπει να είμαστε προσεκτικοί ώστε να αλλάξουμε μόνο τις διευθύνσεις e-mail που είναι δικές μας, γι' αυτό χρησιμοποιούμε την επιλογή `--commit-filter':
$ git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
then
GIT_AUTHOR_NAME="Scott Chacon";
GIT_AUTHOR_EMAIL="schacon@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
Αυτό πάει σε όλες τις υποβολές και τις ξαναγράφει με τη νέα μας διεύθυνση. Επειδή οι υποβολές περιέχουν τις τιμές SHA-1 των γονέων τους, αυτή η εντολή αλλάζει τον αριθμό SHA-1 κάθε υποβολής στο ιστορικό μας, όχι μόνο εκείνες που έχουν την αντίστοιχη διεύθυνση e-mail.