Εισαγωγή στο Git

dimitris | Κυρ, 09/11/2011 - 23:52 | 14'

Θέλουμε να προγραμματίσουμε, ακόμα και μικρά προγράμματα; Πρέπει να μάθουμε Git!

Του Σίμου Ξενιτέλλη

 

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

Ένα από τα συστήματα διαχείρισης εκδόσεων λογισμικού είναι το Git, που γράφτηκε αρχικά από τον Linus Torvalds και στηρίζει την ανάπτυξη του πυρήνα Linux, του GNOME και πολλών άλλων έργων ΕΛ/ΛΑΚ. Το Git είναι ένα κατανεμημένο σύστημα διαχείρισης εκδόσεων λογισμικού (Distributed Version Control System, DVCS), και είναι εξαιρετικό προσόν να γνωρίζουμε πως να το χρησιμοποιήσουμε. Στο άρθρο αυτό θα δούμε πως μπορούμε να χρησιμοποιήσουμε το Git για να διαχειριστούμε την ανάπτυξη ενός απλού προγράμματος.

 

Εγκατάσταση & Ρυθμίσεις

Για να εγκαταστήσουμε το Git, εγκαθιστούμε το πακέτο git από το Κέντρο λογισμικού της διανομής μας. Επίσης, εγκαθιστούμε το gitg που επιτρέπει να δούμε σε γραφικό περιβάλλον τις αλλαγές στον κώδικά μας.

Αρχικά, μπορούμε να καθορίσουμε τα στοιχεία μας ή να θέσουμε χρήσιμες ρυθμίσεις. Συγκεκριμένα, αντικαθιστούμε με τα προσωπικά μας στοιχεία:

git config --global user.name "ΟΝΟΜΑ ΕΠΩΝΥΜΟ"
git config --global user.email "[email protected]"

Η ρύθμιση επιτρέπει να βλέπουμε με χρώματα τα αποτελέσματα των εντολών git που θα εκτελέσουμε.

git config --global color.ui auto

 

Πρώτα βήματα

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

$ mkdir myproject
$ cd myproject
$ git init
Initialized empty Git repository in /home/user/Repositories/myproject/.git/

Μέσα στον υποκατάλογο myproject έχουμε φτιάξει το αποθετήριο (εντολή git init), που για τώρα είναι κενό. Για το Git, τα ειδικά αρχεία του βρίσκονται στον κρυφό υποκατάλογο .git/ και είναι φυσικά σημαντικό να μην το πειράξουμε. Οι εντολές Git που θα εκτελέσουμε, επιδρούν στα περιεχόμενα του υποκαταλόγου .git.

Ας γράψουμε ένα μικρό πρόγραμμα. Το αρχείο lotto.py είναι γραμμένο στη γλώσσα προγραμματισμού Python, και στην αρχική μορφή παράγει έξι τυχαίους αριθμούς, που αντιστοιχούν σε μια στήλη του Λόττο. Αν δε γνωρίζετε Python, δείτε το ελεύθερο βιβλίο A Byte of Python (http://goo.gl/oYdNT) που μεταφράστηκε στα ελληνικά από την κοινότητα Ubuntu-gr:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import random

for i in range(0, 6):

  print random.randint(1, 49)

Αποθηκεύουμε τον παραπάνω κώδικα σε αρχείο με όνομα lotto.py, μέσα στον υποκατάλογο του αποθετηρίου μας, και τον τρέχουμε με

python lotto.py

Κάθε φορά που τρέχει, καλεί έξι φορές τη συνάρτηση random.randint(), που επιστρέφει ένα τυχαίο ακέραιο αριθμό μεταξύ 1 και 49, και έτσι παράγει μια στήλη Λόττο. Ας εισάγουμε το πρόγραμμα στο αποθετήριο.

$ git add lotto.py
$ git commit -m "Αρχική υποβολή" lotto.py
[master (root-commit) 520e2b5] Initial addition
1 files changed, 7 insertions(+), 0 deletions(-)
create mode 100644 lotto.py

Με την εντολή git add ενημερώνουμε το αποθετήριο ότι πρόκειται να προσθέσουμε ένα νέο αρχείο. Το git add το κάνουμε μόνο την πρώτη φορά που εισάγουμε ένα νέο αρχείο στο αποθετήριο. Μετά, με την εντολή git commit, εισάγουμε την πρώτη έκδοση του κώδικά μας στο αποθετήριο. Με το διακόπτη -m καθορίζουμε το σχόλιο, εδώ "Αρχική υποβολή". Είναι εντάξει να γράψουμε ελληνικά, αρκεί οι συνεργάτες μας να γνωρίζουν τη γλώσσα. Τέλος, καθορίζουμε το όνομα αρχείου για την υποβολή.

 

Διορθώνοντας τον κώδικα

Η πρώτη έκδοση του προγράμματος έχει μια αδυναμία: δεν ελέγχει για επαναλήψεις αριθμών. Με μια διόρθωση (δείτε το lotto.py 2.0), τα νέα νούμερα τοποθετούνται σε δομή λίστας.

lotto.py 2.0


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import random

numbers = []

while len(numbers) < 6:
  candidate = random.randint(1, 49)
  while candidate in numbers:
    candidate = random.randint(1, 49)
  numbers.append(candidate)
numbers.sort()

print numbers


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

Η διόρθωση που κάναμε δεν έχει εισαχθεί (commit) στο αποθετήριο. Μπορούμε να το διαπιστώσουμε με

git diff

όπου εμφανίζει τις αλλαγές μας (εικόνα 1). Οι γραμμές με κόκκινο είναι αυτές που βγαίνουν ενώ με πράσινο είναι αυτές που προστίθενται. Με την εντολή

git status

μπορούμε να επιβεβαιώσουμε ότι το αρχείο lotto.py έχει αλλαγές που δεν έχουν εισαχθεί στο αποθετήριο.

Αν θέλαμε να αναιρέσουμε αυτές τις πρόσφατες αλλαγές ώστε να χαθούν οριστικά, θα εκτελούσαμε

git reset --hard

Αν για κάποιο λόγο θέλαμε να χαθεί για πάντα η πιο πρόσφατη υποβολή, εκτελούμε

git reset --hard HEAD^1

Η διόρθωση όμως είναι καλή, οπότε ας κάνουμε την υποβολή της στο αποθετήριο με την εκτέλεση της εντολής

$ git commit -m "Έλεγχος για διπλά· ταξινόμηση στήλης" lotto.py
[master a2f8310] Έλεγχος για διπλά· ταξινόμηση στήλης
1 files changed, 10 insertions(+), 2 deletions(-)

Μπορούμε να δούμε το ιστορικό των δύο υποβολών με την εντολή

git log

Μπορούμε να μελετήσουμε οπτικά αυτές τις δύο υποβολές τρέχοντας

gitg

 

Φτιάχνουμε κλάδο

Τι θα είχε ενδιαφέρον να κάνουμε με ένα πρόγραμμα για Λόττο; Μπορούμε να παράγουμε, για παράδειγμα, 100.000 τυχαίες στήλες και να ελέγξουμε στην πράξη το συνολικό κέρδος ή απώλεια σε σχέση με μια πραγματική νικήτρια στήλη. Έτσι θα δούμε αν έχει νόημα να παίξουμε ένα μεγάλο ποσό που ενδεχομένως έχει περισσότερες πιθανότητες για κέρδος.

Φτιάχνουμε έναν κλάδο (branch) στο αποθετήριό μας για το νεότερο κώδικα που θα γράψουμε. Αν είμαστε ευχαριστημένοι με το αποτέλεσμα, θα τον συνενώσουμε με τον κώδικα που έχουμε ήδη γράψει, στον κορμό, που έχει το όνομα master. Τούτη είναι μια εξαιρετική πρακτική για πειραματισμούς. Με την εντολή:

git branch myexperiment

δημιουργούμε τον κλάδο myexperiment ενώ με την εντολή:

$ git branch

μπορούμε να δούμε τη λίστα των κλάδων.

Για να μεταβούμε από τον ένα κλάδο στον άλλο, εκτελούμε

$ git checkout myexperiment
Switched to branch 'myexperiment'

και πάντα επιβεβαιώνουμε ότι όντως μεταβήκαμε (το υποδηλώνει ο χαρακτήρας «*») με την εντολή:

git branch

ή με την:

gitg

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

$ git checkout master
Switched to branch 'master'

$ git branch -D myexperiment
Deleted branch myexperiment (was a2f8310).

 

Προσθήκη στον κλάδο

Ας προχωρήσουμε με τον προγραμματισμό ώστε να κάνουμε μια ακόμα υποβολή. Θέλουμε η δημιουργία στήλης του Λόττο να γίνει συνάρτηση, ώστε να την καλούμε εύκολα πολλές φορές. Διορθώνουμε τον κώδικα όπως στο παρακάτω κώδικα "lotto.py 3.0".

lotto.py 3.0

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import random


def getLottoNumbers():

    numbers = []
    while len(numbers) < 6:
        candidate = random.randint(1, 49)
        while candidate in numbers:
            candidate = random.randint(1, 49)
        numbers.append(candidate)
    numbers.sort()
    return numbers

print getLottoNumbers()


Τώρα φτιάξαμε και συνάρτηση που παράγει στήλες. Με την εντολή

git diff

μπορούμε να δούμε τις αλλαγές και κάνουμε την υποβολή με

$ git commit -m "Μετατροπή σε συνάρτηση" lotto.py

Δοκιμάζουμε την νέα έκδοση και βλέπουμε ότι λειτουργεί. Οπότε κάνουμε μια συνένωση (merge) του κώδικα που μόλις γράψαμε με τον κορμό (master).

$ git checkout master
Switched to branch 'master'
$ git merge myexperiment
Updating a2f8310..607e2d5
Fast-forward
lotto.py | 19 +++++++++++--------
1 files changed, 11 insertions(+), 8 deletions(-)

Έτσι, έχουμε φέρει τις αλλαγές μας στον κορμό.

Είναι καλή πρακτική να γίνονται πειραματισμοί σε ένα κλάδο, και όταν είμαστε σίγουροι για το αποτέλεσμα, να μεταφέρουμε τη δουλειά στον κορμό.

 

Κλωνοποίηση

Ένα χαρακτηριστικό των αποθετηρίων είναι η δυνατότητα να λάβουμε πλήρη αντίγραφα, που συμπεριλαμβάνει όλο το ιστορικών των υποβολών που έγιναν (cloning). Για το Git, μπορούμε να κλωνοποιήσουμε ένα αποθετήριο με την εντολή git clone δίνοντας τη διαδρομή του αποθετηρίου. Το υπόλοιπο του προγράμματος για το Λόττο έχει ολοκληρωθεί σε online αποθετήριο που έφτιαξα, οπότε μπορείτε να εκτελέσετε τις παρακάτω εντολές για να το κλωνοποιήσετε στο PC σας:

$ cd ..
$ git clone git://github.com/simos/lotto.git

Θα δημιουργηθεί ένας νέος υποκατάλογος lotto όπου θα βρείτε το ολοκληρωμένο lotto.py.
Με το gitg είναι εφικτό να δει κανείς τις διαδοχικές αλλαγές στον κώδικα και να δοκιμάσει να κάνει τη διαδικασία ξανά για εκμάθηση. Στην εικόνα 2 μπορούμε να δούμε τις διαδοχικές αλλαγές στον κώδικα από το εργαλείο gitg.

 

Επίλογος

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



Ο Σίμος περνάει τον ελεύθερο χρόνο του μαθαίνοντας περισσότερα για ΕΛ/ΛΑΚ. 

Δώσε αστέρια!

MO: (ψήφοι: 0)