Τώρα που δεν φοβάστε πλέον το GIT, δείτε πώς μπορείτε να αξιοποιήσετε αυτά που γνωρίζετε

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

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

Συγχώνευση

Η συγχώνευση συγχωνεύει τον κωδικό σας.

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

Υπάρχουν 2 είδη συγχωνεύσεων:

Γρήγορη συγχώνευση προς τα εμπρός

Επιστρέφοντας στο παράδειγμά μας από την τελευταία φορά:

Αυτό είναι τόσο απλό όσο η μετακίνηση της ετικέτας masterστο the-ending. Ο Git δεν έχει καμία αμφιβολία για το τι ακριβώς πρέπει να γίνει - αφού το «δέντρο» μας είχε έναν μόνο συνδεδεμένο κατάλογο κόμβων.

$ git branch master * the-ending $ git checkout master Switched to branch 'master' $ git merge the-ending Updating a39b9fd..b300387 Fast-forward byeworld | 1 + 1 file changed, 1 insertion(+) create mode 100644 byeworld

Μη γρήγορη εμπρόσθια συγχώνευση

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

Εδώ είναι το πρώτο πράγμα που πρέπει να γνωρίζετε σχετικά με τις συγκρούσεις συγχώνευσης: Εάν δεν γνωρίζετε τι συμβαίνει:

git merge --abort

Αυτό θα σας επαναφέρει στην αρχική κατάσταση, χωρίς παρενέργειες. Απλώς ακυρώσατε το χάος που επρόκειτο να κάνετε.

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

$ git checkout -b the-middle Switched to a new branch 'the-middle'

Συνεχίζοντας το στυλ μας, ας μάθουμε μέσω ενός παραδείγματος. Τροποποιώ helloworldστον κλάδο the-middle.

$ git diff diff --git a/helloworld b/helloworld index a042389..e702052 100644 --- a/helloworld +++ b/helloworld @@ -1 +1,3 @@ hello world! + +Middle World

Προσθήκη και δέσμευση the-middle.

Στη συνέχεια, αλλάζω masterκαι τροποποιώ το helloworldmaster. Προσθέτω τα εξής:

$ git diff --cached diff --git a/helloworld b/helloworld index a042389..ac7a733 100644 --- a/helloworld +++ b/helloworld @@ -1 +1,3 @@ hello world! + +Master World

Βλέπετε γιατί έπρεπε να κάνω git diff --cachedεδώ; Εάν όχι, ρωτήστε με παρακάτω!

Τώρα, ήρθε η ώρα να συγχωνευτείτε!

$ git merge the-middle Auto-merging helloworld CONFLICT (content): Merge conflict in helloworld Automatic merge failed; fix conflicts and then commit the result.

Όταν mergeαποτύχει, εδώ κάνει το git: Τροποποιεί το αρχείο με τη συγχώνευση για να σας δείξει τι ακριβώς δεν μπορεί να αποφασίσει.

$ cat helloworld hello world!
$ cat helloworld hello world! <<<<<<>>>>>> the-middle

Βγάζει νόημα; Το <<<<< HEADμέρος είναι δικό μας (το βασικό κλάδο) και το >>>>> the-middle partείναι theirs(το υποκατάστημα συγχωνεύεται στο βασικό κλάδο).

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

$ git status On branch master You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add ..." to mark resolution) both modified: helloworld

Αποφάσισα να κρατήσω και τα δύο κομμάτια.

$ cat helloworld hello world! Master World Middle World

Και εκεί το έχετε:

$ git add helloworld $ git commit -m "resolve merge conflict" [master c747e68] resolve merge conflict

Τηλεχειριστήρια

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

Κλώνος

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

git clone 

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

git remote add  

Σπρώξε και τράβα

Push και Pull είναι ενέργειες που εφαρμόζονται στο remote.

Το Push ωθεί τις αλλαγές σας στο τηλεχειριστήριο. Λοιπόν, στέλνουμε το Indexκαι αντίστοιχο Objectsαπό το αντικείμενο-κατάστημα!

git push  

Το Pull τραβά τον κωδικό από το τηλεχειριστήριο. Ακριβώς όπως και πριν, αντιγράφουμε Indexκαι αντιστοιχίζουμε Objectsαπό το κατάστημα αντικειμένων!

git pull origin master

originείναι το προεπιλεγμένο όνομα του τηλεχειριστηρίου. Και δεδομένου ότι masterείναι η προεπιλεγμένη υποκατάστημα, μπορείτε να δείτε πώς οι περιέρχεται εντολή στο όνομα απλό βρίσκουμε παντού: git pull origin master. Τώρα ξέρετε καλύτερα.

Επαναφορά

Η επαναφορά επαναφέρει τη βάση κώδικα σας σε προηγούμενη έκδοση. Η επαναφορά συνοδεύεται από 3 σημαίες:

--soft, --hardκαι --mixed.

Η ομορφιά του reset, είναι σε θέση να αλλάξει την ιστορία. Ας πούμε ότι κάνετε ένα λάθος με ένα commit, και τώρα git logόλα σας ταλαντεύονται με δεσμεύσεις όπως:

Bugfix

Final BugFix

Final Final BugFix

God why isn't this working last try bug fix

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

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

Από εκεί resetέρχεται: Θα μπορούσατε να κάνετε resetόλες τις δεσμεύσεις σας και να τις μετατρέψετε σε μία μόνο δέσμευσηgot sh*t done!

(Μην το χρησιμοποιείτε ως μήνυμα δέσμευσης - ακολουθήστε τις βέλτιστες πρακτικές!)

Επιστρέφοντας στο παράδειγμά μας, εδώ έχω κάνει.

$ git log commit 959781ec78c970d4797c5e938ec154de44d0151b (HEAD -> master) Author: Neil Kakkar Date: Mon Nov 5 07:32:55 2018 +0000 God why isn't this working last final BugFix commit affa90c0db78999d22c326fdbd6c1d5057228822 Author: Neil Kakkar Date: Mon Nov 5 07:32:19 2018 +0000 Final Final BugFix commit 2e9570cffc0a8206132d75c402d68351eda450bd Author: Neil Kakkar Date: Mon Nov 5 07:31:49 2018 +0000 Final BugFix commit 4560fc0ec6305d0b7bcfb4be1901438fd126d6d1 Author: Neil Kakkar Date: Mon Nov 5 07:31:21 2018 +0000 BugFix commit c747e6891af419119fd817dc69a2e122084aedae Merge: 3d01508 fb8b2fc Author: Neil Kakkar Date: Tue Oct 23 07:44:09 2018 +0100 resolve merge conflict

Now that the bug is fixed, I want to clean up my history before I push to master. This would work well too — when, say, I realise later on that I introduced another bug and need to revert to the previous version. In this case, c747e689 doesn’t have the best commit message to understand this.

$ git reset c747e6891af419119fd817dc69a2e122084aedae $ git log commit c747e6891af419119fd817dc69a2e122084aedae (HEAD -> master) Merge: 3d01508 fb8b2fc Author: Neil Kakkar Date: Tue Oct 23 07:44:09 2018 +0100 resolve merge conflict

There, all sorted?

$ git status On branch master Untracked files: (use "git add ..." to include in what will be committed) clean.txt nothing added to commit but untracked files present (use "git add" to track)

clean.txt is the file I had committed for the bug fix. Now, all I have to do is:

$ git add clean.txt $ git commit -m "fix bug: Unable to clean folder" [master d8487ca] fix bug: Unable to clean folder 1 file changed, 4 insertions(+) create mode 100644 clean.txt $ git log commit d8487ca8b9acfa9666bdf2c6b7fa27b3971bd957 (HEAD -> master) Author: Neil Kakkar Date: Mon Nov 5 07:41:41 2018 +0000 fix bug: Unable to clean folder commit c747e6891af419119fd817dc69a2e122084aedae Merge: 3d01508 fb8b2fc Author: Neil Kakkar Date: Tue Oct 23 07:44:09 2018 +0100 resolve merge conflict

There, done and dusted. Can you guess now, using the clues from the log, the reset command syntax and your tech-sense to figure out how it works behind the scenes?

Reset cuts off the commit-tree at the specified commit. All labels for that branch — if ahead — are moved back to the specified commit. Do the existing files stay in the object store though? You know how to check that now, Ace.

The files are also removed from the staging area. Now this might be a problem if you have lots of untracked/modified files which you don’t want to add.

How do you do that?

Can you pick up the clue I left in the beginning of this section?

Behaviour flags!

--soft keeps all files staged.

$ git reset --soft c747e6891af419119fd817dc69a2e122084aedae $ git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: clean.txt

--mixed is the default: Removes all files from staging area too.

--hard is hard-core. Deletes files from the object store — and directory as well. Use with extreme caution. There goes my bug fix*. Gone.

$ git reset --hard c747e6891af419119fd817dc69a2e122084aedae HEAD is now at c747e68 resolve merge conflict $ git status On branch master nothing to commit, working tree clean

*Well, not completely. Git is amazing. Have you heard of meta-meta data? A redundancy log of what happened in the repository? Yes, of course git keeps it!

$ git reflog c747e68 (HEAD -> master) [email protected]{0}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae efc6d21 [email protected]{1}: commit: soft reset c747e68 (HEAD -> master) [email protected]{2}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae d8487ca [email protected]{3}: commit: fix bug: Unable to clean folder c747e68 (HEAD -> master) [email protected]{4}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae 959781e [email protected]{5}: commit: God why isn't this working last final BugFix affa90c [email protected]{6}: commit: Final Final BugFix 2e9570c [email protected]{7}: commit: Final BugFix 4560fc0 [email protected]{8}: commit: BugFix c747e68 (HEAD -> master) [email protected]{9}: commit (merge): resolve merge conflict 3d01508 [email protected]{10}: commit: add Master World b300387 (the-ending) [email protected]{11}: checkout: moving from the-middle to master fb8b2fc (the-middle) [email protected]{12}: commit: add Middle World b300387 (the-ending) [email protected]{13}: checkout: moving from master to the-middle b300387 (the-ending) [email protected]{14}: checkout: moving from the-middle to master b300387 (the-ending) [email protected]{15}: checkout: moving from master to the-middle b300387 (the-ending) [email protected]{16}: merge the-ending: Fast-forward a39b9fd [email protected]{17}: checkout: moving from the-ending to master b300387 (the-ending) [email protected]{18}: checkout: moving from master to the-ending a39b9fd [email protected]{19}: checkout: moving from the-ending to master b300387 (the-ending) [email protected]{20}: commit: add byeworld a39b9fd [email protected]{21}: checkout: moving from master to the-ending a39b9fd [email protected]{22}: commit (initial): Add helloworld

This is everything from the beginning of the example in the previous article. Does this mean I can recover things if I made an awful mistake?

$ git checkout d8487ca Note: checking out 'd8487ca'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b  HEAD is now at d8487ca... fix bug: Unable to clean folder $ ls byeworld clean.txt helloworld

There you have it.

Congratulations, you’re a Git Ninja — Apprentice now.

Υπάρχει κάτι περισσότερο για το οποίο θα θέλατε να μάθετε; Κάτι που σε μπερδεύει για το Git; Ενημερώστε με παρακάτω! Θα προσπαθήσω να το εξηγήσω με τον τρόπο που το έμαθα!

Σας άρεσε αυτό; Μην χάσετε ξανά μια ανάρτηση - εγγραφείτε στη λίστα αλληλογραφίας μου!