Git
Chapters ▾ 2nd Edition

2.4 Τα θεμελιώδη στοιχεία του Git - Αναιρώντας κάτι

Αναιρώντας κάτι

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

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

$ git commit --amend

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

Όταν εκτελέσουμε την εντολή, θα σας εμφανιστεί το μήνυμα από την προηγούμενή σας υποβολή. Το μήνυμα αυτό μπορούμε να το επεξεργαστούμε, αλλά η τελευταία υποβολή θα αντικατασταθεί.

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

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

Έτσι καταλήγουμε με μια και μοναδική υποβολή. Η δεύτερη υποβολή αντικαθιστά τα αποτελέσματα της πρώτης.

Αφαίρεση αρχείου από το στάδιο καταχώρισης

Στις επόμενες δύο ενότητες θα δούμε πώς μπορούμε να διαχειριστούμε τις αλλαγές στην περιοχή καταχώρησης και στον κατάλογο εργασίας. Κάτι που θα σας φανεί πολύ χρήσιμο είναι ότι η εντολή που μας προσδιορίζει την κατάσταση αυτών των περιοχών, μας υπενθυμίζει και πώς να αναιρέσουμε τις αλλαγές σε αυτές. Για παράδειγμα, έστω ότι έχουμε κάνει αλλαγές σε δύο αρχεία και θέλουμε να τα υποβάλλουμε ως ξεχωριστές αλλαγές, αλλά τα καταχωρήσαμε και τα δύο κατά λάθος με την εντολή git add *. Πώς μπορούμε να αναιρέσουμε την καταχώρηση του ενός από τα δύο; Η εντολή git status μας υπενθυμίζει:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README
    modified:   CONTRIBUTING.md

Όπως βλέπουμε, το κείμενο της εντολής μας συμβουλεύει να χρησιμοποιήσουμε την εντολή git reset HEAD <file>... ώστε να αναιρέσουμε μια καταχώρηση. Ας χρησιμοποιήσουμε λοιπόν τη συμβουλή αυτή για το αρχείο CONTRIBUTING.md:

$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M	CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Η εντολή φαίνεται λίγο περίεργη, αλλά δουλεύει. Το αρχείο CONTRIBUTING.md είναι τροποποιημένο, αλλά δεν βρίσκεται στην περιοχή καταχώρησης.

Note

Ενώ η εντολή git reset μπορεί να είναι επικίνδυνη αν την καλέσουμε με την επιλογή --hard, στην προηγούμενη περίπτωση το αρχείο στον κατάλογο εργασίας σας δεν τροποποιείται από την εντολή. Η εκτέλεση της εντολής git reset χωρίς επιπλέον επιλογές δεν είναι επικίνδυνη, τροποποιεί μόνο την περιοχή καταχώρησης.

Προς το παρόν, το μόνο που χρειάζεται να γνωρίζουμε για την εντολή git reset είναι η παραπάνω χρήση της. Θα μπούμε σε περισσότερες λεπτομέρειες για την εντολή αυτή καθώς και για πιο ενδιαφέροντα πράγματα που μπορούμε να κάνουμε με αυτήν στο κεφάλαιο Απομυθοποίηση της reset.

Αναιρώντας τροποποιήσεις ενός αρχείου

Τι μπορούμε να κάνουμε όμως αν διαπιστώσουμε ότι δεν θέλουμε να κρατήσουμε τις αλλαγές που κάναμε στο αρχείο CONTRIBUTING.md; Πώς μπορούμε να τις αναιρέσουμε εύκολα και να φέρουμε το αρχείο στη μορφή που είχε στην τελευταία του υποβολή (ή όπως βρισκόταν αρχικά στον κατάλογο εργασίας σας); Η εντολή git status μας βοηθάει εδώ και πάλι. Στο αποτέλεσμα του προηγούμενου παραδείγματος, η περιογή με τα μη καταχωρημένα αρχεία ήταν κάπως έτσι:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Η εντολή μας ενημερώνει αναλυτικά πώς να απορρίψουμε τις αλλαγές που έχουμε κάνει. Ας ακολουθήσουμε τι λέει:

$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Μπορούμε να δούμε πλέον ότι οι αλλαγές σας έχουν απορριφθεί.

Important

Είναι σημαντικό να καταλάβουμε ότι η εντολή git checkout -- [file] είναι αρκετά επικίνδυνη. Όλες οι αλλαγές που έχουμε κάνει σε αυτό το αρχείο έχουν πλέον χαθεί καθώς έχουμε αντιγράψει ένα αρχείο πάνω από αυτό. Δεν πρέπει να χρησιμοποιούμε αυτήν την εντολή παρά μόνο αν είμαστε σίγουροι ότι δεν θέλουμε να κρατήσουμε τις αλλαγές σας.

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

Ο,τιδήποτε έχει υποβληθεί στο Git μπορεί να ανακτηθεί. Μπορούμε να ανακτήσουμε ακόμα και υποβολές σε κλάδους που έχουν διαγραφεί ή υποβολές που επανεγγράφηκαν, με την εντολή git commit --amend (βλ. Ανάκτηση δεδομένων για περισσότερα σχετικά με την ανάκτηση δεδομένων). Ωστόσο, αν κάτι δεν είναι υποβεβλημένο και το χάσουμε, είναι πολύ πιθανό να μην μπορέσουμε να το ανακτήσουμε.