Chapters ▾ 2nd Edition

2.3 Τα θεμελιώδη στοιχεία του Git - Χρησιμοποιώντας το ιστορικό υποβολών

Χρησιμοποιώντας το ιστορικό υποβολών

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

Τα παρακάτω παραδείγματα χρησιμοποιούν ένα πολύ απλό έργο που ονομάζεται “simplegit”. Για να αποκτήσουμε το έργο, εκτελούμε:

$ git clone https://github.com/schacon/simplegit-progit

Αν εκτελέσουμε την εντολή git log σε αυτό το έργο, θα πάρουμε κάτι σαν το εξής:

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    Initial commit

Εξ ορισμού, η εντολή git log παραθέτει όλες τις υποβολές που έχουν γίνει στο αποθετήριο σε αντίστροφη χρονολογική σειρά, οι πιο πρόσφατες υποβολές εμφανίζονται πρώτες. Όπως μπορούμε να δούμε, η εντολή καταγράφει κάθε υποβολή μαζί με το άθροισμα ελέγχου SHA-1, το όνομα και το e-mail του δημιουργού της, την ημερομηνία εγραφής, καθώς και το μήνυμα της υποβολής.

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

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

$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
     s.platform  =   Gem::Platform::RUBY
     s.name      =   "simplegit"
-    s.version   =   "0.1.0"
+    s.version   =   "0.1.1"
     s.author    =   "Scott Chacon"
     s.email     =   "schacon@gee-mail.com"
     s.summary   =   "A simple gem for using Git in Ruby code."

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
     end

 end
-
-if $0 == __FILE__
-  git = SimpleGit.new
-  puts git.show
-end

Η επιλογή αυτή εμφανίζει τις ίδιες πληροφορίες, αλλά κάθε υποβολή ακολουθείται και από τις διαφορές (diff) που εισήγαγε. Αυτό είναι πολύ χρήσιμο στην περίπτωση που θέλουμε να εξετάσουμε κάποιον κώδικα ή για να δούμε στα γρήγορα τι έγινε σε μια ακολουθία υποβολών που εισήγαγε κάποιος συνεργάτης μας. Μπορούμε επίσης να χρησιμοποιήσουμε επιλογές ανακεφαλαίωσης με την git log. Για παράδειμα, αν θέλουμε να δούμε κάποια συντομευμένα στατιστικά για την κάθε υποβολή, μπορούμε να χρησιμοποιήσουμε την επιλογή --stat:

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

 Rakefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

 lib/simplegit.rb | 5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    Initial commit

 README           |  6 ++++++
 Rakefile         | 23 +++++++++++++++++++++++
 lib/simplegit.rb | 25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

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

Μια ακόμα χρήσιμη επιλογή είναι η --pretty. Η επιλογή αυτή αλλάζει τη μορφή της εξόδου της εντολής. Υπάρχουν μερικές προϋπάρχουσες τιμές που μπορούμε να χρησιμοποιήσουμε. Η τιμή oneline εκτυπώνει κάθε υποβολή σε μία γραμμή, κάτι το οποίο μπορεί να μας φανεί χρήσιμο αν βλέπουμε πολλές υποβολές. Επιπλέον, οι τιμές short, full και fuller εμφανίζουν την ίδια έξοδο σε παρόμοια μορφή αλλά με λιγότερες ή περισσότερες πληροφορίες αντίστοιχα:

$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 Change version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Remove unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 Initial commit

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

$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : Change version number
085bb3b - Scott Chacon, 6 years ago : Remove unnecessary test
a11bef0 - Scott Chacon, 6 years ago : Initial commit

Ο πίνακας Χρήσιμες επιλογές για την git log --pretty=format παραθέτει μερικές από τις πιο χρήσιμες επιλογές μορφοποίησης.

Table 1. Χρήσιμες επιλογές για την git log --pretty=format
Επιλογή Περιγραφή εξόδου

%H

Αριθμός SHA-1 υποβολής

%h

Συντμημένος αριθμός SHA-1 υποβολής

%T

Αριθμός SHA-1 δέντρου

%t

Συντμημένος αριθμός SHA-1 δέντρου

%P

Αριθμοί SHA-1 γονέων

%p

Συντμημένοι αριθμός SHA-1 γονέων

%an

Όνομα συγγραφέα

%ae

E-mail συγγραφέα

%ad

Ημερομηνία συγγραφέα (σε μορφή που ορίζεται από την επιλογή --date=)

%ar

Ημερομηνία συγγραφέα, σχετική

%cn

Όνομα υποβάλλοντος

%ce

E-mail υποβάλλοντος

%cd

Ημερομηνία υποβολής

%cr

Ημερομηνία υποβολής, σχετική

%s

Θέμα

Ίσως αναρωτιέστε ποια είναι η διαφορά μεταξύ του author (δημιουργού, συγγραφέα) και του committer (αυτού που έκανε την υποβολή). Ο δημιουργός είναι το πρόσωπο που έγραψε αρχικά τη δουλειά, ενώ o committer είναι αυτός που την υπέβαλε τελευταίος. Συνεπώς, αν στείλουμε ένα επίθεμα για ένα έργο και κάποιος άλλος το υποβάλλει, θα πρέπει και οι δύο να πιστωθούμε τη δουλειά: εμείς ως δημιουργός και ο άλλος ως αυτός που την υπέβαλλε. Θα αναλύσουμε αυτή τη διαφορά αυτή σε λίγο, στην ενότητα Κατανεμημένο Git.

Οι επιλογές oneline και format είναι ιδιαίτερα χρήσιμες σε συνδυασμό με μια άλλη επιλογή της εντολής log, την --graph. Η επιλογή αυτή προσθέτει ένα μικρό γράφημα με χαρακτήρες ASCII που δείχνει το ιστορικό των κλάδων και των συγχωνεύσεων:

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 Ignore errors from SIGCHLD on trap
*  5e3ee11 Merge branch 'master' of https://github.com/dustin/grit.git
|\
| * 420eac9 Add method for getting the current branch
* | 30e367c Timeout code and tests
* | 5a09431 Add timeout protection to grit
* | e1193f8 Support for heads with slashes in them
|/
* d6016bc Require time for xmlschema
*  11d191e Merge branch 'defunkt' into local

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

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

Table 2. Συνήθεις επιλογές για την git log
Επιλογή Περιγραφή

-p

Δείξε το επίθεμα (patch) που εισήχθηκε σε κάθε υποβολή.

--stat

Δείξε στατιστικά σχετικά με τα αρχεία που τροποποιήθηκαν σε κάθε υποβολή.

--shortstat

Δείξε μόνον την τελευταία γραμμή από την επιλογή --stat, που δείχνει μόνο τον συνολικό αριθμό αρχείων που τροποποιήθηκαν και αριθμό γραμμών που προστέθηκαν και αφαιρέθηκαν.

--name-only

Δείξε τη λίστα των αρχείων που τροποποιήθηκαν (μετά τις πληροφορίες για την υποβολή).

--name-status

Δείξε επιπλέον τη λίστα των αρχείων που επηρεάστηκαν με προσθήκη/τροποποίηση/διαγραφή πληροφοριών.

--abbrev-commit

Δείξε μόνο τους πρώτους χαρακτήρες από τους 40 του αθροίσματος ελέγχου SHA-1.

--relative-date

Δείξε τη σχετική ημερομηνία σε σχετική μορφή (π.χ. “2 weeks ago”) αντί για την πλήρη.

--graph

Δείξε ένα γράφημα ASCII του κλάδου και του ιστορικού συγχώνευσης δίπλα στην έξοδο του μητρώου.

--pretty

Δείξε τις υποβολές σε εναλλακτική μορφή· οι επιλογές είναι: oneline, short, full, fuller και format (στην οποία ορίζουμε τη δική μας μορφή).

--oneline

Συντόμευση για --pretty=oneline --abbrev-commit χρήση και των δύο μαζί.

Περιορίζοντας την έξοδο της log

Εκτός από τις επιλογές μορφοποίησης, η εντολή git log έχει και πολλές επιλογές που περιορίζουν την έξοδό της — δηλαδή, επιλογές που μας δείχνουν μόνο ένα υποσύνολο των συνολικών υποβολών. Έχουμε ήδη δει μια τέτοια επιλογή, την -2, η οποία εμφανίζει μόνο τις δύο τελευταίες υποβολές. Μάλιστα, μπορούμε να χρησιμοποιήσουμε -<n>, όπου n είναι ένας ακέραιος που αντιστοιχεί στις τελευταίες n υποβολές. Στην πραγματικότητα, βέβαια, είναι σχετικά απίθανο να χρησιμοποιούμε αυτή την επιλογή συχνά, καθώς το Git εκ προεπιλογής παροχετεύει την έξοδο σε έναν σελιδοποιητή οπότε βλέπουμε μόνο μια σελίδα με τα στοιχεία του μητρώου κάθε φορά.

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

$ git log --since=2.weeks

Η εντολή αυτή χρησιμοποιείται με πολλές διαφορετικές μορφές — μπορούμε να προσδιορίσουμε μια συγκεκριμένη μέρα, "2008-01-15", ή μια σχετική μέρα όπως "2 years 1 day 3 minutes ago".

Μπορούμε επίσης να φιλτράρουμε τη λίστα με τις υποβολές με βάση κάποια κριτήρια. Η επιλογή --author μας επιτρέπει να φιλτράρουμε με βάση έναν συγκεκριμένο δημιουργό και η επιλογή --grep μας επιτρέπει να ψάξουμε για λέξεις-κλειδιά στα μηνύματα των υποβολών.

Note

Μπορείτε να χρησιμοποιήσετε περισσότερες από μία φορές τα κριτήρια αναζήτησης --author και --grep, κάτι που θα περιορίσει την έξοδο της εντολής log σε υποβολές που συμφωνούν με οποιοδήποτε από τα μοτίβα για τον --author και οποιοδήποτε από τα μοτίβα του --grep· πάντως αν προσθέσετε επιπλέον την επιλογή --all-match, θα περιορίσετε την έξοδο σε αυτές τις υποβολές που συμφωνούν με όλα τα μοτίβα του --grep.

Ένα ακόμα πολύ χρήσιμο φίλτρο είναι η επιλογή -S (κατά το κοινώς λεγόμενο η “αξίνα” (“pickaxe”) του Git) η οποία παίρνει μια συμβολοσειρά και μας δείχνει μόνο τις υποβολές που εισήγαγαν κάποια αλλαγή στον κώδικα, η οποία προσέθεσε ή αφαίρεσε αυτή τη συμβολοσειρά. Για παράδειγμα, αν θέλουμε να βρούμε την τελευταία υποβολή που προσέθεσε ή αφαίρεσε μια αναφορά σε μια συγκεκριμένη συνάρτηση, θα γράφαμε:

$ git log -S function_name

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

$ git log -- path/to/file

Στον πίνακα Επιλογές που περιορίζουν την έξοδο της git log καταγράφουμε κάποιες από αυτές τις επιλογές αυτές για εύκολη αναφορά.

Table 3. Επιλογές που περιορίζουν την έξοδο της git log
Επιλογή Περιγραφή

-(n)

Δείξε μόνον τις τελευταίες n υποβολές.

--since, --after

Περιόρισε τις υποβολές σε αυτές που έγιναν μετά από συγκεκριμένη ημερομηνία.

--until, --before

Περιόρισε τις υποβολές σε αυτές που έγιναν πριν από συγκεκριμένη ημερομηνία.

--author

Δείξε μόνο τις υποβολές στις οποίες το πεδίο author συμφωνεί με συγκεκριμένη συμβολοσειρά.

--committer

Δείξε μόνο τις υποβολές στις οποίες το πεδίο committer συμφωνεί με συγκεκριμένη συμβολοσειρά.

--grep

Δείξε μόνο τις υποβολές στις οποίες το μήνυμα υποβολής περιέχει συγκεκριμένη συμβολοσειρά.

-S

Δείξε μόνο τις υποβολές στις οποίες προστέθηκε ή αφαιρέθηκε κώδικας που ταιριάζει με συγκεκριμένη συμβολοσειρά.

Για παράδειγμα, αν θέλουμε να δούμε ποιες υποβολές τροποποίησαν αρχεία τεστ στο ιστορικό του πηγαίου κώδικα του Git από τον Junio Hamano και δεν είναι υποβολές συγχώνευσης κατά τον Οκτώβριο του 2008, μπορούμε να εκτελέσουμε κάτι τέτοιο:

$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
   --before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch

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

Tip
Αποτροπή της εμφάνισης των υποβολών συγχώνευσης

Ανάλογα με τη ροή εργασίας που χρησιμοποιοείτε στο αποθετήριό σας, ενδέχεται ένα σημαντικό ποσοστό των υποβολών στο ιστορικό να είναι απλά υποβολές συγχώνευσης, οι οποίες γενικά δεν εμπεριέχουν πολλές πληροφορίες. Για να αποτρέψετε την εμφάνιση των υποβολών συγχώνευσης, απλά προσθέτετε στη log την επιλογή --no-merges.