Πρώτα: τι είναι ένα Git branch;
Φαντάσου ότι φτιάχνεις ένα παιχνίδι με LEGO.
Έχεις την κανονική έκδοση του παιχνιδιού σου:
mainΑλλά θέλεις να δοκιμάσεις ένα νέο κάστρο χωρίς να χαλάσεις αυτό που ήδη έφτιαξες.
Δημιουργείς λοιπόν:
feature-castleΑυτό είναι ένα branch.
Το branch δεν είναι δεύτερος φάκελος στον υπολογιστή σου. Είναι ουσιαστικά ένας δείκτης προς μια συγκεκριμένη κατάσταση του κώδικα.
Τα branches είναι ελαφριοί δείκτες προς commits του Git repository.
Τι γίνεται όταν αλλάζω branch;
Ας πούμε ότι έχεις αυτόν τον φάκελο:
MyProject/και βρίσκεσαι στο:
mainΑν γράψεις:
git switch feature-castleπαραμένεις μέσα στον ίδιο φάκελο:
MyProject/Το Git όμως αλλάζει τα αρχεία ώστε να αντιστοιχούν στο άλλο branch.
Δηλαδή:
MyProject/
↓
main
git switch feature-castle
MyProject/
↓
feature-castleΈχεις έναν φάκελο, αλλά μπορείς να αλλάζεις ποιο branch εμφανίζεται μέσα του.
Και τότε τι είναι το worktree;
Το Git worktree κάνει κάτι διαφορετικό.
Σου επιτρέπει να έχεις πολλά branches ανοιχτά ταυτόχρονα, μέσα σε διαφορετικούς φακέλους.
Για παράδειγμα:
MyProject/
main
MyProject-login/
feature-login
MyProject-payments/
feature-paymentsΌλοι αυτοί οι φάκελοι χρησιμοποιούν το ίδιο Git repository και το ίδιο ιστορικό.
Όμως κάθε worktree έχει τα δικά του πραγματικά αρχεία και τις δικές του μη αποθηκευμένες αλλαγές.
Αυτό είναι ιδιαίτερα χρήσιμο όταν χρησιμοποιούμε AI coding agents.
Μπορούμε να έχουμε:
Agent 1 → feature-login
Agent 2 → feature-payments
Agent 3 → bugfix-emailχωρίς ο ένας agent να αλλάζει συνεχώς τα αρχεία του άλλου.
Branch και worktree λοιπόν δεν είναι το ίδιο
Η πιο απλή εξήγηση είναι αυτή:
Το branch είναι η έκδοση της δουλειάς.
Το worktree είναι ο φάκελος όπου δουλεύεις πάνω σε αυτή την έκδοση.
Ένα branch είναι λογική έννοια.
Ένα worktree είναι πραγματικός φάκελος στον δίσκο σου.
Το VS Code χρησιμοποιεί ακριβώς αυτή τη λογική για παράλληλη εργασία σε διαφορετικά branches.
Και τώρα έρχεται το περίεργο: τι γίνεται με το .env;
Εδώ βρίσκεται ένα σημείο που μπορεί εύκολα να προκαλέσει προβλήματα.
Ένα .env αρχείο συνήθως περιέχει ρυθμίσεις που αφορούν το συγκεκριμένο μηχάνημα ή περιβάλλον.
Για παράδειγμα:
DB_HOST=localhost
DB_NAME=myproject
DB_USER=root
DB_PASSWORD=supersecretΜπορεί επίσης να περιέχει:
OPENAI_API_KEY=xxxx
STRIPE_SECRET_KEY=xxxxΑυτές οι πληροφορίες δεν πρέπει κανονικά να ανεβαίνουν στο GitHub.
Γι' αυτό συνήθως έχουμε:
.envΤο Git τότε αγνοεί το συγκεκριμένο αρχείο.
Τι γίνεται με το .env όταν αλλάζω branch;
Ας έχουμε:
MyProject/
.env
Program.cs
README.mdκαι το .env βρίσκεται στο .gitignore.
Βρίσκεσαι στο:
mainκαι κάνεις:
git switch feature-loginΤο Git αλλάζει τα αρχεία που παρακολουθεί.
Το .env όμως συνήθως παραμένει εκεί, επειδή δεν ανήκει στο Git.
Άρα:
main
│
│ git switch
↓
feature-login
ίδιος φάκελος
ίδιο τοπικό .envΑυτό είναι πολύ σημαντικό.
Τα branches μπορεί να αλλάζουν, αλλά το τοπικό .env παραμένει συνδεδεμένο με τον φάκελο, όχι με το branch.
Τι γίνεται όμως με ένα worktree;
Εδώ αλλάζει η κατάσταση.
Ας έχεις:
MyProject/και μέσα:
.envΔημιουργείς τώρα ένα δεύτερο worktree:
git worktree add ../MyProject-login feature-loginΘα αποκτήσεις:
MyProject/
.env
MyProject-login/Το .env δεν αντιγράφεται αυτόματα στο δεύτερο worktree όταν είναι ignored και untracked.
Γιατί;
Επειδή το Git δημιουργεί το δεύτερο worktree χρησιμοποιώντας τα αρχεία που γνωρίζει το repository.
Το .env όμως το έχουμε πει στο Git να αγνοεί.
Άρα μπορεί να καταλήξουμε με:
MyProject/
.env ✅
MyProject-login/
.env ❌Το πρόγραμμα στο δεύτερο worktree μπορεί τότε να ξεκινήσει και να πει:
Database connection failedή:
Missing API keyΔεν χάλασε το branch.
Δεν χάλασε το Git.
Απλώς ο νέος φάκελος δεν έχει τις απαραίτητες τοπικές ρυθμίσεις.
Και τι γίνεται με το connection string;
Ένα connection string είναι ουσιαστικά η «διεύθυνση και τα κλειδιά» που χρειάζεται η εφαρμογή για να βρει τη βάση δεδομένων.
Για παράδειγμα:
Server=localhost;
Database=CodeCraft;
User Id=developer;
Password=secret;Μπορούμε να το αποθηκεύσουμε ως environment variable:
DATABASE_URL=Server=localhost;Database=CodeCraft;User Id=developer;Password=secret;ή σε εφαρμογές .NET με ονομασία όπως:
ConnectionStrings__DefaultConnectionΟι environment variables μπορούν να αντικαθιστούν αντίστοιχες τιμές της configuration του ASP.NET Core.
Άρα ισχύει ακριβώς το ίδιο πρόβλημα.
Αν το connection string βρίσκεται στο τοπικό .env:
Project-main/
.env
DATABASE_URL=...το νέο worktree:
Project-feature/δεν αποκτά αυτόματα αυτό το .env.
Θα πρέπει να του δοθεί με κάποιον ασφαλή τρόπο.
Τι δεν πρέπει να κάνουμε
Η εύκολη λύση φαίνεται να είναι:
«Ας βάλω το
.envμέσα στο Git για να πηγαίνει παντού».
Αυτό όμως είναι συνήθως πολύ κακή ιδέα.
Ένα .env μπορεί να περιέχει:
Database passwords
API keys
SMTP passwords
Stripe keys
JWT secrets
Cloud credentialsΑν γίνει commit, αυτά μπορεί να καταλήξουν στο GitHub και στο ιστορικό του repository.
Ακόμη και αν διαγράψουμε αργότερα το αρχείο, το secret μπορεί να υπάρχει σε παλαιότερο commit.
Η Microsoft επίσης συνιστά τα secrets να αποθηκεύονται έξω από το project και να μην γίνονται commit στο source repository.
Η καλύτερη πρακτική
Στο Git μπορούμε να έχουμε ένα αρχείο:
.env.exampleπου περιέχει μόνο τα ονόματα:
DB_HOST=
DB_NAME=
DB_USER=
DB_PASSWORD=
OPENAI_API_KEY=Το .env.example μπορεί να βρίσκεται κανονικά στο Git.
Το πραγματικό:
.envπαραμένει στο:
Έτσι ένας developer ή agent βλέπει τι χρειάζεται η εφαρμογή, χωρίς να βλέπει τα πραγματικά passwords.
Με worktrees λοιπόν έχουμε:
repository
│
├── main worktree
│ └── .env
│
├── login worktree
│ └── .env
│
└── payment worktree
└── .envΤα τρία .env μπορούν να έχουν ίδιες ή διαφορετικές τιμές.
Για παράδειγμα:
main
↓
Database: development_main
login
↓
Database: development_login
payments
↓
Database: development_paymentsΑυτό μάλιστα μπορεί να είναι επιθυμητό όταν τρέχουν πολλά instances της εφαρμογής ταυτόχρονα.
Ειδικά για .NET
Στο .NET υπάρχει ακόμη καλύτερη επιλογή για development secrets.
Η Microsoft παρέχει το User Secrets σύστημα.
Για παράδειγμα:
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "..."Το secret αποθηκεύεται έξω από τον φάκελο του project.
Έτσι δεν χρειάζεται να βρίσκεται ούτε:
appsettings.jsonούτε:
.envούτε στο Git repository.
Η Microsoft προτείνει User Secrets για development και ασφαλέστερες secret stores, όπως Azure Key Vault, για production περιβάλλοντα.
Η εικόνα που πρέπει να θυμόμαστε
Φαντάσου ένα σχολείο.
Το Git repository είναι η βιβλιοθήκη του σχολείου.
Τα branches είναι διαφορετικές εκδόσεις του ίδιου βιβλίου.
Τα worktrees είναι διαφορετικά θρανία όπου έχουμε ανοιχτές διαφορετικές εκδόσεις.
Και το .env;
Το .env είναι ένα χαρτάκι με passwords που έχει αφήσει κάθε μαθητής πάνω στο δικό του θρανίο.
Όταν αλλάζεις βιβλίο στο ίδιο θρανίο, το χαρτάκι παραμένει εκεί.
Όταν όμως πας σε καινούριο θρανίο, το χαρτάκι δεν εμφανίζεται μαγικά.
Και σίγουρα δεν θέλουμε να βάλουμε το χαρτάκι με τα passwords μέσα στο βιβλίο της βιβλιοθήκης.
Με μία πρόταση
Branch = ποια έκδοση του κώδικα δουλεύω.
Worktree = σε ποιον φάκελο δουλεύω.
.env = τοπικές ρυθμίσεις του συγκεκριμένου φακέλου.
Connection string = μία από αυτές τις ρυθμίσεις, συχνά ευαίσθητη.
Αν καταλάβουμε αυτές τις τέσσερις έννοιες, τα Git worktrees παύουν να φαίνονται περίπλοκα.




Φόρτωση σχολίων…