Merge — είναι μια λειτουργία στο Git που συνδυάζει αλλαγές από έναν κλάδο σε έναν άλλο, δημιουργώντας ένα commit συγχώνευσης (merge commit). Το Git υποστηρίζει πολλές στρατηγικές: fast-forward (γραμμικό ιστορικό), three-way merge (με δημιουργία merge commit) και squash merge (συμπίεση όλων των commit σε ένα). Σύμφωνα με τα δεδομένα του git-scm.com, 2025, το merge παραμένει ο πιο συχνά χρησιμοποιούμενος μηχανισμός ενσωμάτωσης κώδικα στην ομαδική ανάπτυξη με Git.
Κύρια σημεία
Merge (συγχώνευση) — είναι μια θεμελιώδης λειτουργία στο Git που συνδυάζει αλλαγές από έναν κλάδο (source) σε έναν άλλο (target). Ως αποτέλεσμα της συγχώνευσης, ο κλάδος-στόχος λαμβάνει όλα τα commit από τον κλάδο-πηγή που δεν υπήρχαν ακόμα σε αυτόν. Ανάλογα με την κατάσταση, το Git μπορεί να εκτελέσει merge με τρεις διαφορετικούς τρόπους.
Η κύρια αξία του merge είναι η διατήρηση του ιστορικού: το merge commit καταγράφει το γεγονός της συγχώνευσης κλάδων, αποθηκεύει πληροφορίες για το πότε και ποιοι κλάδοι συγχωνεύτηκαν. Αυτό διευκολύνει τον έλεγχο αλλαγών, την αναζήτηση παλινδρομήσεων και την κατανόηση της χρονολογίας ανάπτυξης. Σε μεγάλα έργα, το merge commit είναι ο τυπικός τρόπος ενσωμάτωσης κώδικα.
Σύμφωνα με τα δεδομένα του GitLab Flow, τα merge commit χρησιμοποιούνται στο 73% των ομάδων που εργάζονται με Git. Εναλλακτικές προσεγγίσεις (rebase, squash) προτιμούνται από ομάδες που προσανατολίζονται σε γραμμικό ιστορικό. Η επιλογή στρατηγικής εξαρτάται από το μέγεθος της ομάδας, τη συχνότητα εκδόσεων και τις συμφωνίες που έχουν γίνει αποδεκτές στο έργο.
Merge απαιτείται όταν ο προγραμματιστής έχει ολοκληρώσει την εργασία σε μια λειτουργία και θέλει να την ενσωματώσει στο develop ή main. Τυπικό σενάριο: ο προγραμματιστής δημιούργησε έναν κλάδο λειτουργίας από το develop, εργάστηκε για μερικές ημέρες, και κατά τη διάρκεια αυτής της περιόδου εμφανίστηκαν νέα commit στο develop από άλλους συμμετέχοντες. Πριν από τη συγχώνευση, πρέπει να συνδυαστούν οι αλλαγές — και για αυτό χρησιμοποιείται το merge.
Χωρίς merge, είναι αδύνατη η κοινή εργασία στον ίδιο κώδικα στο Git. Κάθε φορά που δύο προγραμματιστές ταυτόχρονα κάνουν αλλαγές στην ίδια βάση κώδικα, οι κλάδοι τους αποκλίνουν. Το Merge — είναι ο μόνος τρόπος να συνδυαστούν αυτές οι αλλαγές ξανά χωρίς απώλεια δεδομένων.
Το Git υποστηρίζει τρεις τύπους merge, ο καθένας προορισμένος για το δικό του σενάριο. Η επιλογή του τύπου συγχώνευσης επηρεάζει το ιστορικό commit, την ευκολία επαναφοράς και την αναγνωσιμότητα του αρχείου καταγραφής.
Fast-forward συμβαίνει όταν ο κλάδος-στόχος δεν είχε νέα commit από τη δημιουργία του κλάδου-πηγής. Σε αυτήν την περίπτωση, το Git απλά μετακινεί τον δείκτη του κλάδου-στόχου προς τα εμπρός, στο τελευταίο commit του κλάδου-πηγής. Το ιστορικό παραμένει γραμμικό, χωρίς merge commit.
# Fast-forward merge: το develop δεν έχει αλλάξει από τη δημιουργία του feature
git checkout develop
git merge feature/new-login
# Αποτέλεσμα: ο δείκτης develop μετακινήθηκε στο τέλος του feature
# Δεν δημιουργήθηκε κανένα merge commit
Το Fast-forward είναι βολικό για βραχύβιους κλάδους, όπου ο προγραμματιστής εργαζόταν μόνος. Αλλά αυτή η προσέγγιση έχει ένα μειονέκτημα: χάνεται η πληροφορία ότι ο κλάδος υπήρχε — όλα τα commit φαίνονται σαν να έγιναν απευθείας στο develop.
Three-way merge εκτελείται όταν και οι δύο κλάδοι έχουν νέα commit μετά το σημείο απόκλισης. Το Git δημιουργεί ένα ξεχωριστό merge commit με δύο γονείς, το οποίο καταγράφει το γεγονός της συγχώνευσης κλάδων. Αυτή η προσέγγιση συνιστάται για κλάδους λειτουργίας στην ομαδική ανάπτυξη.
# Αναγκαστικό three-way merge με τη σημαία --no-ff
git checkout develop
git merge --no-ff feature/new-login
# Δημιουργήθηκε merge commit με προεπιλεγμένο μήνυμα
# Μπορείτε να ορίσετε το δικό σας μήνυμα μέσω -m
git merge --no-ff feature/new-login -m "Merge feature/new-login into develop"
Η σημαία --no-ff εγγυάται τη δημιουργία merge commit, ακόμα κι αν το fast-forward είναι δυνατό. Αυτή είναι η βέλτιστη πρακτική για τη διατήρηση πληροφοριών σχετικά με τη διακλάδωση στο έργο.
Squash merge συμπιέζει όλα τα commit του κλάδου-πηγής σε ένα και το εφαρμόζει στον κλάδο-στόχο. Το ιστορικό της λειτουργίας χάνεται — ένα commit με όλες τις αλλαγές εισέρχεται στον κλάδο. Αυτό είναι βολικό όταν τα λεπτομερή commit στον κλάδο λειτουργίας δεν έχουν αξία για το γενικό ιστορικό.
# Squash merge: όλα τα commit του feature συμπιέστηκαν σε ένα
git checkout develop
git merge --squash feature/experimental
git commit -m "feat: experimental login flow (squashed)"
Squash είναι κατάλληλο για πρόχειρα, πειραματικούς κλάδους και καταστάσεις όπου η διατήρηση της καθαρότητας του ιστορικού είναι σημαντική. Μείον — χάνεται η σύνδεση με τα αρχικά commit, γεγονός που περιπλέκει την επαναφορά μεμονωμένων αλλαγών.
Ours και Theirs — δύο ειδικές στρατηγικές merge στο Git. Το Ours αγνοεί πλήρως τις αλλαγές από τον κλάδο-πηγή, διατηρώντας μόνο ό,τι υπάρχει στον κλάδο-στόχο. Το Theirs, αντίθετα, αποδέχεται την έκδοση του κλάδου-πηγής σε κάθε σύγκρουση. Αυτές οι στρατηγικές είναι χρήσιμες κατά τη συγχώνευση μεγάλων όγκων κώδικα, όταν είναι εκ των προτέρων γνωστό ποια έκδοση πρέπει να επικρατήσει.
Ο μηχανισμός merge στο Git βασίζεται στη σύγκριση τριών σημείων: του κοινού προγόνου (merge base), της κατάστασης του κλάδου-πηγής και της κατάστασης του κλάδου-στόχου. Το Git βρίσκει το merge base — το τελευταίο commit κοινό και για τους δύο κλάδους — και υπολογίζει ποιες αλλαγές συνέβησαν σε κάθε κλάδο μετά την απόκλιση.
Το Git χρησιμοποιεί τον τριμερή αλγόριθμο συγχώνευσης, ο οποίος λαμβάνει υπόψη όχι μόνο τις δύο συγκρινόμενες εκδόσεις του αρχείου, αλλά και τον κοινό τους πρόγονο. Χάρη σε αυτό, το Git μπορεί να επιλύσει αυτόματα καταστάσεις όπου οι αλλαγές στον έναν κλάδο δεν επηρεάζουν τα τροποποιημένα τμήματα του άλλου — ακόμα κι αν και τα δύο αρχεία έχουν τροποποιηθεί.
Ας εξετάσουμε το σενάριο: δύο προγραμματιστές εργάζονται σε διαφορετικά αρχεία στον ίδιο κλάδο λειτουργίας. Ο πρώτος τροποποίησε το LoginActivity.kt, ο δεύτερος — το ProfileFragment.kt. Όταν συγχωνεύουν τις αλλαγές τους, το Git βλέπει ότι οι αλλαγές αφορούν διαφορετικά αρχεία και εκτελεί το merge αυτόματα, χωρίς ανθρώπινη παρέμβαση.
Εάν και οι δύο προγραμματιστές τροποποίησαν το LoginActivity.kt, αλλά σε διαφορετικές μεθόδους — το Git θα το χειριστεί επίσης αυτόματα, συνδυάζοντας τις αλλαγές γραμμή προς γραμμή. Σύγκρουση προκύπτει μόνο εάν και οι δύο άλλαξαν τις ίδιες γραμμές ή εάν ο ένας διέγραψε κώδικα που ο άλλος τροποποίησε.
Σύγκρουση merge προκύπτει όταν το Git δεν μπορεί να συνδυάσει αυτόματα τις αλλαγές, επειδή και οι δύο κλάδοι τροποποίησαν τις ίδιες γραμμές με διαφορετικό τρόπο. Σε αυτήν την περίπτωση, το Git επισημαίνει τα τμήματα σύγκρουσης στα αρχεία και αναμένει χειροκίνητη επίλυση από τον προγραμματιστή.
Τα τμήματα σύγκρουσης επισημαίνονται με ειδικούς δείκτες: το <<<<<<< HEAD δείχνει τον κώδικα από τον κλάδο-στόχο, το ======= — το διαχωριστικό, το >>>>>>> source-branch — τον κώδικα από τον κλάδο-πηγή. Ο προγραμματιστής πρέπει να επιλέξει χειροκίνητα ποια παραλλαγή να διατηρήσει ή να τις συνδυάσει.
# 1. Εκτέλεση merge και προβολή σύγκρουσης
git merge feature/new-login
# Έξοδος: CONFLICT (content): Merge conflict in LoginActivity.kt
# 2. Προβολή λίστας αρχείων με συγκρούσεις
git status
# both modified: src/ui/login/LoginActivity.kt
# 3. Επίλυση σύγκρουσης: επεξεργασία αρχείου, αφαίρεση δεικτών
# 4. Προσθήκη επιλυμένου αρχείου και ολοκλήρωση merge
git add src/ui/login/LoginActivity.kt
git merge --continue
# ή: git commit (χωρίς --continue)
Για την επίλυση συγκρούσεων υπάρχουν εργαλεία: το git mergetool ανοίγει ένα οπτικό εργαλείο συγχώνευσης (Meld, Beyond Compare, VS Code). Πολλοί προγραμματιστές προτιμούν να επιλύουν συγκρούσεις στο IDE — τα IntelliJ IDEA και Android Studio παρέχουν ένα ενσωματωμένο εργαλείο με σύγκριση τριών πλαισίων, το οποίο απλοποιεί σημαντικά αυτήν τη διαδικασία.
Συμβουλές για την επίλυση συγκρούσεων: πάντα να κατανοείτε τι κάνει κάθε πλευρά της σύγκρουσης, μην διαγράφετε ξένο κώδικα χωρίς να κατανοείτε τη λογική του, και εάν η σύγκρουση είναι πολύ περίπλοκη — συμπεριλάβετε τον συγγραφέα και των δύο κλάδων στην κοινή επίλυση.
Η επιλογή μεταξύ Merge και Rebase — μία από τις πιο συχνές αρχιτεκτονικές αποφάσεις στο Git. Και οι δύο προσεγγίσεις συνδυάζουν αλλαγές, αλλά το κάνουν με διαφορετικό τρόπο: το merge διατηρεί το ιστορικό διακλάδωσης, το rebase ξαναγράφει το ιστορικό, καθιστώντας το γραμμικό.
Πολλές ομάδες χρησιμοποιούν υβριδική προσέγγιση: rebase για να φέρουν τον κλάδο λειτουργίας στην τρέχουσα κατάσταση του develop (git rebase develop), στη συνέχεια merge με τη σημαία --no-ff για καταγραφή της συγχώνευσης. Αυτό δίνει καθαρό ιστορικό εντός της λειτουργίας και ενημερωτικά σημεία συγχώνευσης σε επίπεδο develop.
Συχνές Ερωτήσεις
Χωρίς --no-ff το Git εκτελεί fast-forward merge, εάν είναι δυνατό — απλά μετακινεί τον δείκτη του κλάδου. Με --no-ff το Git δημιουργεί πάντα ένα merge commit, διατηρώντας πληροφορίες σχετικά με τη διακλάδωση. Συνιστάται για κλάδους λειτουργίας στην ομαδική ανάπτυξη.
Χρησιμοποιήστε το git mergetool ή το ενσωματωμένο εργαλείο του IDE. Εάν η σύγκρουση αφορά δεκάδες αρχεία — πιθανώς οι κλάδοι έχουν αποκλίνει πάρα πολύ. Σε αυτήν την περίπτωση, αξίζει να συζητήσετε με την ομάδα το σχέδιο συγχώνευσης, ίσως να το χωρίσετε σε πολλά στάδια.
Ναι: το git merge --abort ακυρώνει το merge εάν δεν έχει ακόμη ολοκληρωθεί (σύγκρουση). Εάν το merge έχει ήδη ολοκληρωθεί — χρησιμοποιήστε git reset --hard HEAD~1 ή git revert -m 1 <merge-commit> για ασφαλή επαναφορά.
Συνιστάται για ομαδική εργασία. Το merge commit καταγράφει το γεγονός της συγχώνευσης, περιέχει αναφορές και στους δύο κλάδους και διευκολύνει την κατανόηση του ιστορικού. Για προσωπικούς ή πειραματικούς κλάδους, το squash merge ή το fast-forward είναι αποδεκτά.
Το Git δεν μπορεί να συγχωνεύσει αυτόματα δυαδικά αρχεία — επιλέγει μία από τις εκδόσεις στο σύνολό της. Για δυαδικά αρχεία (εικόνες, .aab, .apk) συνιστάται η ελαχιστοποίηση παράλληλων αλλαγών και η χρήση Git LFS για μεγάλα αρχεία.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.