Εργαστήκατε σε έναν κλάδο feature, ο κώδικας είναι έτοιμος. Τώρα πρέπει να τον επανενσωματώσετε στο main. Το Git προσφέρει δύο μηχανισμούς γι' αυτό: τη συγχώνευση (merge) και την αναβάθμιση βάσης (rebase).
Και τα δύο επιτυγχάνουν τον ίδιο στόχο — να ενώσουν τη δουλειά — αλλά με διαφορετική μορφή ιστορικού. Αυτό είναι όλο το διακύβευμα αυτού του μαθήματος.
| Μηχανισμός | Ιδέα σε μία πρόταση |
|---|---|
| Merge | Δημιουργούμε ένα commit που ενώνει τους δύο κλάδους, κρατώντας την ιστορία τους ως έχει. |
| Rebase | Ξαναπαίζουμε τα commits ενός κλάδου πάνω από έναν άλλο, σαν να είχαμε ξεκινήσει αργότερα. |
Πριν από κάθε ενσωμάτωση, βεβαιωνόμαστε ότι έχουμε την τελευταία έκδοση:
git switch main
git pull origin mainΗ εντολή git merge ενώνει έναν κλάδο σε έναν άλλο. Υπάρχουν δύο περιπτώσεις.
Περίπτωση 1 — Γρήγορη συγχώνευση (fast-forward): αν το main δεν έχει κινηθεί από τη δημιουργία του κλάδου, το Git απλώς προωθεί τον δείκτη. Δεν δημιουργείται commit συγχώνευσης.
Περίπτωση 2 — Συγχώνευση τριών κλάδων (three-way merge): αν το main έχει λάβει νέα commits στο μεταξύ, το Git δημιουργεί ένα commit συγχώνευσης που έχει δύο γονείς.
# Τοποθέτηση στον κλάδο-στόχο, έπειτα συγχώνευση
git switch main
git merge feature/panier
# Επιβολή commit συγχώνευσης ακόμα κι αν είναι δυνατό το fast-forward
git merge --no-ff feature/panier| Επιλογή | Αποτέλεσμα |
|---|---|
git merge feature | Συγχώνευση (fast-forward αν είναι δυνατό) |
git merge --no-ff feature | Πάντα δημιουργία commit συγχώνευσης (ίχνος του κλάδου) |
git merge --abort | Ακύρωση συγχώνευσης σε εξέλιξη λόγω σύγκρουσης |
Το merge διατηρεί την πραγματική ιστορία: βλέπουμε πότε και πώς ενώθηκαν οι κλάδοι. Είναι ειλικρινές, αλλά το ιστορικό μπορεί να γίνει πυκνό με πολλά commits συγχώνευσης.
🔧 Μίνι-άσκηση — Θέλετε να συγχωνεύσετε το feature/panier στο main επιβάλλοντας τη δημιουργία ενός commit συγχώνευσης, ακόμα κι αν ένα fast-forward θα ήταν δυνατό. Γράψτε την εντολή.
git merge --no-ff feature/panier — το --no-ff κρατά ρητό ίχνος του συγχωνευμένου κλάδου.
Το git rebase μετακινεί τα commits του κλάδου σας για να τα ξαναπαίξει πάνω στην κορυφή ενός άλλου κλάδου. Αποτέλεσμα: ένα γραμμικό ιστορικό, σαν να είχατε ξεκινήσει τη δουλειά σας μετά τα τελευταία commits του main.
Πριν από το rebase:
Μετά το git rebase main (τα commits B και C ξαναπαίζονται μετά το D):
# Στον κλάδο feature, επανάληψη πάνω από το main
git switch feature/panier
git rebase main
# Έπειτα καθαρή συγχώνευση fast-forward στο main
git switch main
git merge feature/panier| Πλεονέκτημα του rebase | Προφύλαξη |
|---|---|
| Ιστορικό γραμμικό και ευανάγνωστο | Ξαναγράφει τα commits (νέα SHA) |
| Χωρίς παράσιτα commits συγχώνευσης | Ποτέ μην κάνετε rebase σε κλάδο ήδη σταλμένο και κοινόχρηστο |
| Ιδανικό πριν από ένα pull request | Συγκρούσεις προς επίλυση commit προς commit |
⚠️ Χρυσός κανόνας του rebase: μην κάνετε ποτέ rebase σε commits ήδη δημοσιευμένα και χρησιμοποιούμενα από άλλους. Ξαναγράφετε την ιστορία, κάτι που θα έσπαγε τα αποθετήριά τους. Το rebase είναι για την τοπική, μη κοινόχρηστη εργασία σας.
🔧 Μίνι-άσκηση — Βρίσκεστε στον κλάδο feature/panier. Γράψτε την εντολή για να ξαναπαίξετε τα commits σας πάνω στην κορυφή του main (γραμμικό ιστορικό).
git rebase main (όντας στον feature/panier).
Μια σύγκρουση εμφανίζεται όταν το Git δεν μπορεί να αποφασίσει αυτόματα: δύο κλάδοι τροποποίησαν την ίδια γραμμή του ίδιου αρχείου. Το Git σταματά και σας ζητά να αποφασίσετε.
Το Git εισάγει δείκτες σύγκρουσης στο αρχείο:
<<<<<<< HEAD
prix = 10 # version de main
=======
prix = 12 # version de feature
>>>>>>> feature/panierΗ επίλυση βήμα προς βήμα:
<<<<<<<, =======, >>>>>>>.git add.# Προβολή αρχείων σε σύγκρουση
git status
# Μετά από χειροκίνητη επεξεργασία
git add fichier-en-conflit.py
# Ολοκλήρωση ενός merge
git commit
# Ολοκλήρωση ενός rebase
git rebase --continue
# Σε περίπτωση πανικού: ακύρωση όλων
git merge --abort # ή: git rebase --abort| Εργαλείο βοήθειας | Χρήση |
|---|---|
git status | Λίστα αρχείων σε σύγκρουση |
git diff | Προβολή των συγκρουόμενων διαφορών |
git mergetool | Εκκίνηση γραφικού εργαλείου επίλυσης |
| VS Code | Κουμπιά Accept Current / Incoming / Both |
Μια σύγκρουση δεν είναι σφάλμα: είναι το Git που, ειλικρινά, σας λέει «δεν ξέρω ποιο να κρατήσω, είναι δική σας απόφαση». Ηρεμία και ανάγνωση των δεικτών αρκούν στο 99 % των περιπτώσεων.
🔧 Μίνι-άσκηση — Επεξεργαστήκατε το αρχείο app.py για να επιλύσετε μια σύγκρουση κατά τη διάρκεια ενός rebase. Ποιες δύο εντολές ολοκληρώνουν τη λειτουργία;
git add app.py
git rebase --continue(Για ένα merge, θα ήταν git add app.py και έπειτα git commit.)
Και τα δύο ενώνουν τη δουλειά, αλλά παράγουν διαφορετικό ιστορικό. Η επιλογή είναι συχνά μια σύμβαση ομάδας.
| Πτυχή | Merge | Rebase |
|---|---|---|
| Ιστορικό | Πιστό, διακλαδισμένο | Γραμμικό, καθαρό |
| Commit συγχώνευσης | Ναι (αν όχι fast-forward) | Όχι |
| Ξαναγράφει την ιστορία | Όχι | Ναι (νέα SHA) |
| Ασφαλές σε κοινόχρηστο κλάδο | ✅ Ναι | ❌ Όχι |
Αναγνωσιμότητα του log | Πιο πυκνή | Πιο καθαρή |
Η πιο συνηθισμένη συνιστώμενη πρακτική:
main πριν ανοίξετε ένα pull request → καθαρό ιστορικό.main → σαφές ίχνος της ενσωμάτωσης.# 1. Καθαρισμός του τοπικού κλάδου πριν από το PR
git switch feature/x
git rebase main
# 2. Μόλις εγκριθεί το PR, το GitHub κάνει το mergeΜνημονικός κανόνας: «Rebase ιδιωτικά, merge δημόσια.» Κάνουμε rebase ό,τι είναι δικό μας, merge ό,τι είναι κοινόχρηστο.
Question 1 : Τι κάνει το git merge feature από το main όταν το main έχει επίσης νέα commits;
a) Διαγράφει τον κλάδο feature
b) Δημιουργεί ένα commit συγχώνευσης με δύο γονείς
c) Σβήνει το ιστορικό
d) Αρνείται πάντα να συγχωνεύσει
✅ Απάντηση: b) — Είναι συγχώνευση τριών κλάδων: το Git δημιουργεί ένα commit συγχώνευσης που ενώνει τις δύο ιστορίες.
Question 2 : Ποιο είναι το κύριο αποτέλεσμα ενός git rebase main;
a) Να ξαναπαίξει τα commits του κλάδου πάνω από το main για γραμμικό ιστορικό
b) Να κλωνοποιήσει το αποθετήριο
c) Να διαγράψει το main
d) Να δημιουργήσει απομακρυσμένο αντίγραφο ασφαλείας
✅ Απάντηση: a) — Το rebase μετακινεί και ξαναπαίζει τα commits σας στην κορυφή του main, παράγοντας γραμμική ιστορία.
Question 3 : Γιατί δεν πρέπει να κάνουμε rebase σε κλάδο ήδη σταλμένο και κοινόχρηστο;
a) Επειδή το απαγορεύει το GitHub
b) Επειδή ξαναγράφει τα commits και σπάει τα αποθετήρια των άλλων
c) Επειδή το rebase είναι πιο αργό
d) Επειδή διαγράφει το main
✅ Απάντηση: b) — Το rebase δημιουργεί νέα SHA. Αν άλλοι έχουν ήδη αυτά τα commits, το ιστορικό τους γίνεται ασυνεπές.
Question 4 : Τι αντιπροσωπεύουν οι δείκτες <<<<<<<, =======, >>>>>>>;
a) Σχόλια κώδικα
b) Συντακτικό σφάλμα Python
c) Τις ζώνες μιας σύγκρουσης προς χειροκίνητη επίλυση
d) Το τέλος ενός αρχείου
✅ Απάντηση: c) — Είναι οι δείκτες σύγκρουσης: πάνω η τρέχουσα έκδοση (HEAD), κάτω η εισερχόμενη έκδοση. Επιλέγουμε και τους διαγράφουμε.
Question 5 : Πώς ακυρώνουμε καθαρά μια συγχώνευση μπλοκαρισμένη από συγκρούσεις;
a) git delete
b) git merge --abort
c) git reset --cloud
d) Διαγραφή του φακέλου .git
✅ Απάντηση: b) — Το git merge --abort (ή git rebase --abort) επαναφέρει το αποθετήριο στην κατάσταση πριν από τη λειτουργία.
Δύο κλάδοι τροποποιούν την ίδια γραμμή ενός αρχείου config.txt. Αναπαραγάγετε τη σύγκρουση, έπειτα επιλύστε την κρατώντας και τις δύο πληροφορίες συνδυασμένες.
main, το αρχείο περιέχει port = 8080.feature/ssl αλλάζει αυτή τη γραμμή σε port = 443.main αλλάζει την ίδια γραμμή σε port = 9090.feature/ssl στο main, επιλύστε τη σύγκρουση κρατώντας port = 443 (HTTPS), έπειτα ολοκληρώστε.# Προετοιμασία: δημιουργία της σύγκρουσης
echo "port = 8080" > config.txt
git add config.txt
git commit -m "Config initiale"
git switch -c feature/ssl
echo "port = 443" > config.txt
git commit -am "Passage en HTTPS (port 443)"
git switch main
echo "port = 9090" > config.txt
git commit -am "Changement de port en 9090"
# Απόπειρα συγχώνευσης → σύγκρουση
git merge feature/sslΤο Git εμφανίζει τότε:
Auto-merging config.txt
CONFLICT (content): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.Το αρχείο config.txt περιέχει:
<<<<<<< HEAD
port = 9090
=======
port = 443
>>>>>>> feature/sslΕπεξεργαζόμαστε ώστε να κρατήσουμε μόνο τη σωστή τιμή:
echo "port = 443" > config.txt # απόφαση υπέρ του HTTPS
git add config.txt
git commit -m "Fusion feature/ssl : conservation du port 443"Αναμενόμενο αποτέλεσμα:
| Επαλήθευση | Εντολή | Έξοδος |
|---|---|---|
| Σύγκρουση επιλυμένη | git status | « nothing to commit, working tree clean » |
| Τελικό περιεχόμενο | cat config.txt | port = 443 |
| Commit συγχώνευσης | git log --oneline -1 | « Fusion feature/ssl : conservation du port 443 » |
Συμβουλή: αν κάνετε λάθος στη μέση μιας σύγκρουσης, το
git merge --abortσας επιστρέφει το αποθετήριο ανέπαφο. Κανένας κίνδυνος να πειραματιστείτε.
add, ολοκληρώνουμε.main.Ξέρετε να ενσωματώνετε τεχνικά τον κώδικα. Το μάθημα 03 — Pull requests δείχνει πώς να ζητήσετε αναθεώρηση αυτής της εργασίας πριν την ενσωματώσετε, στον πυρήνα της συνεργασίας στο GitHub.
Με την επιφύλαξη παντός δικαιώματος. Οποιαδήποτε αναπαραγωγή, διάδοση, χρήση ή προσαρμογή αυτού του μαθήματος, εν όλω ή εν μέρει, απαγορεύεται αυστηρά χωρίς την προηγούμενη γραπτή άδεια του Dr. Haythem REHOUMA.
Μάθημα δημιουργημένο από τον Dr. Haythem REHOUMA — Ανάπτυξη και ανάπτυξη λύσεων δεδομένων