Εύρεση και επαναφορά ενός διαγραμμένου αρχείου σε ένα αποθετήριο Git

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

Ξέρω ότι μπορώ να κάνω checkout ένα αρχείο χρησιμοποιώντας git checkout HEAD^ foo.bar, αλλά δεν ξέρω πραγματικά πότε διαγράφηκε αυτό το αρχείο.

  1. Ποιος θα ήταν ο γρηγορότερος τρόπος για να βρω το commit που διέγραψε ένα συγκεκριμένο όνομα αρχείου;
  2. Ποιος θα ήταν ο ευκολότερος τρόπος για να επαναφέρω αυτό το αρχείο στο αντίγραφο εργασίας μου;

Ελπίζω ότι δεν χρειάζεται να περιηγηθώ χειροκίνητα στα αρχεία καταγραφής μου, να ελέγξω ολόκληρο το έργο για ένα δεδομένο SHA και στη συνέχεια να αντιγράψω χειροκίνητα αυτό το αρχείο στο αρχικό μου checkout του έργου.

Λύση

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


git rev-list -n 1 HEAD -- 
Σχόλια (20)
  1. Χρησιμοποιήστε το git log --diff-filter=D --summary για να λάβετε όλες τις δεσμεύσεις που έχουν διαγράψει αρχεία και τα αρχεία που έχουν διαγραφεί,
  2. Χρησιμοποιήστε git checkout $commit~1 path/to/file.ext για να επαναφέρετε το διαγραμμένο αρχείο.

Όπου $commit είναι η τιμή του commit που βρήκατε στο βήμα 1, π.χ. e4cf499627.

Σχόλια (11)

Αν είστε τρελοί, χρησιμοποιήστε το git-bisect. Ακούστε τι πρέπει να κάνετε:

git bisect start
git bisect bad
git bisect good 

Τώρα ήρθε η ώρα να εκτελέσετε την αυτοματοποιημένη δοκιμή. Η εντολή του κελύφους '[ -e foo.bar ]' θα επιστρέψει 0 αν το foo.bar υπάρχει, και 1 διαφορετικά. Η εντολή "run" του git-bisect θα χρησιμοποιήσει δυαδική αναζήτηση για να βρει αυτόματα την πρώτη δέσμευση όπου η δοκιμή αποτυγχάνει. Ξεκινάει από τη μέση του εύρους που δίνεται (από το καλό στο κακό) και το κόβει στη μέση με βάση το αποτέλεσμα της καθορισμένης δοκιμής.

git bisect run '[ -e foo.bar ]'

Τώρα βρίσκεστε στο commit που το διέγραψε. Από εδώ, μπορείτε να μεταβείτε πίσω στο μέλλον και να χρησιμοποιήσετε το git-revert για να αναιρέσετε την αλλαγή,

git bisect reset
git revert 

ή μπορείτε να πάτε πίσω ένα commit και να επιθεωρήσετε χειροκίνητα τη ζημιά:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .
Σχόλια (4)