Chapters ā–¾ 2nd Edition

3.6 Git’də Branch - Rebasing

Rebasing

Git’də dəyişiklikləri bir budaqdan digərinə birləşdirməyin iki əsas yolu var: merge və rebase. Bu bƶlmədə rebase-in nə olduğunu, bunu necə edəcəyinizi, niyə olduqca gƶzəl bir vasitədir və hansı hallarda istifadə etmək istəmədiyinizi ƶyrənəcəksiniz.

Sadə Rebase

ʏvvəlki bir nümunəyə qayıtsanız Sadə Birləşdirmə, işinizi bƶlüşdürdüyünüzü və iki fərqli branch-da qərar verdiyinizi gƶrə bilərsiniz.

Sadə fikri ayrılığı
Figure 35. Sadə fikri ayrılığı

Branch-ları birləşdirməyin ən asan yolu, yuxarıda bəhs etdiyimiz kimi, merge əmridir. İki ən son branch snapshotu (C3 və` C4`) və ikisinin ən son ortaq ancestor-u (C2) arasında üç tərəfli birləşmə həyata keƧirir, yeni bir snapshot yaradır (və commit edir).

Ayrılmış iş tarixini inteqrasiya etmək üçün birləştirmək
Figure 36. Ayrılmış iş tarixini inteqrasiya etmək üçün birləştirmək

Ancaq başqa bir yol var: C4-də təqdim edilən dəyişikliyin patch-ını gƶtürüb C3-ün üstünə yenidən tətbiq edə bilərsiniz. Git-də buna rebasing deyilir. rebase əmri ilə bir branch-da edilmiş bütün dəyişiklikləri gƶtürüb başqa bir branch-da təkrarlaya bilərsiniz.

Bu misal üçün experiment branch-ını yoxlayıb, master branch-a aşağıdakı kimi qaytarın:

$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command

Bu əməliyyat iki branch-ın ortaq ancestor-una (birinə davam etdiyiniz və birinə rebasing etdiyiniz) gedərək işləyir,olduğunuz branch-ın hər bir commit-i tərəfindən təqdim olunan fərqləri əldə edərək, həmin fərqləri müvəqqəti sənədlərdə saxlayaraq işləyir, hazırkı branch-ı yenidən düzəltdiyiniz branch-la eyni commit-ə bərpa edin və nəhayət hər dəyişikliyi ƶz nƶvbəsində tətbiq edin.

`C4`də `C3`-ə edilən dəyişikliyin rebasing edilməsi
Figure 37. C4`də `C3-ə edilən dəyişikliyin rebasing edilməsi

Bu nƶqtədə, master branch-a qayıda və sürətli bir şəkildə birləşə bilərsiniz.

$ git checkout master
$ git merge experiment
Sürətli irəliləyən `master` branch-ı
Figure 38. Sürətli irəliləyən master branch-ı

İndi C4-ün işarələdiyi snapshot <the merge example-də C5 ilə işarələnmiş snapshotla eynidir. İnteqrasiyanın son məhsulu arasında heƧ bir fərq yoxdur, lakin rebasing daha təmiz bir tarix yaradır. Rebase edilmiş bir branch-ın log-larını araşdırsanız, xətti bir tarixə bənzəyir: gƶrünür ki, bütün işlər əvvəlcə paralel olaraq baş versə də, bütün işlərin ardıcıllıqla baş verdiyi anlaşılır.

Tez-tez verdiyiniz tapşırıqların uzaq bir branch-a təmiz tətbiq olunmasını təmin etmək üçün bunu edəcəksiniz - tƶhfə verməyə Ƨalışdığınız, ancaq qorumadığınız bir layihədə. Bu vəziyyətdə işinizi bir branch-da edər və sonra patch-larını əsas layihəyə təqdim etməyə hazır olduğunuz zaman işinizi origin/master-ə ya dəyişdirərdiniz. Bu yolla, qoruyucu heƧ bir inteqrasiya işi gƶrməməlidir - sadəcə irəli və ya təmiz tətbiq olunmalıdır.

Diqqət yetirin ki, başa Ƨatdığınız son commit-in gƶstərildiyi snapshot, istər bir düzəltmə əmrinin sonuncusu olsun, istərsə birləşmədən sonra edilən son birləşmə, eyni Rebasing dəyişikliklərini bir iş xəttindən digərinə təqdim edilmiş qaydada dəyişdirir, birləşmə isə son nƶqtələri gƶtürərək onları birləşdirir.

Daha Maraqlı Rebase-lər

Ayrıca, rebase hədəf branch-ında başqa bir şeydə yenidən istifadə edə bilərsiniz. Məsələn, Başqa bir mƶvzu branch-ından bir mƶvzu branch-a olan bir tarix kimi bir tarix Ƨəkin. Layihəinizə bəzi server tərəfi funksionallıq əlavə etmək üçün bir mƶvzu branch-nı (server) əlavə etdiniz və commit yaratdınız. Sonra müştəri tərəfində dəyişiklik etmək üçün (client) branch-ı düzəldin və bir neƧə dəfə commit edin. Nəhayət, yenidən server branch-ınıza qayıtdınız və daha bir neƧə commit etdiniz.

Başqa bir mövzu branch-ından bir mövzu branch-a olan bir tarix
Figure 39. Başqa bir mövzu branch-ından bir mövzu branch-a olan bir tarix

Tutaq ki, bir müştəri tərəfindəki dəyişiklikləri sərbəst buraxmaq üçün ana xəttinizə birləşdirmək istədiyinizə qərar verirsiniz, ancaq daha sonra sınaqdan keƧirilməyincə server tərəfindəki dəyişiklikləri dayandırmaq istəyərsiniz. server-də (` C8` və C9) olmayan client-dəki dəyişiklikləri gƶtürüb git rebase-in --onto seƧimini istifadə edərək master branch-ındə təkrarlaya bilərsiniz:

$ git rebase --onto master server client

Bu, əsasən ā€˜` client' branch-nı gƶtürün, `server branch-ından ayrıldığından patch-ları müəyyənləşdirin və bu patch-ları client branch-ında birbaşa master branch-ından kənarda qurulmuş kimi təkrarlayın . '’ Biraz mürəkkəb olsa da, amma nəticə olduqca gƶzəldir.

Bir mƶvzu branch-nı başqa bir mƶvzu branch-ından rebasing etmək
Figure 40. Bir mƶvzu branch-nı başqa bir mƶvzu branch-ından rebasing etmək

İndi master branch-ınızı sürətlə irəliləyə apara bilərsiniz ( Client branch-ındakı dəyişiklikləri daxil etmək üçün master branch-ınızı sürətli yƶnləndirin-ə bax):

$ git checkout master
$ git merge client
Client branch-ındakı dəyişiklikləri daxil etmək üçün `master` branch-ınızı sürətli yƶnləndirin
Figure 41. Client branch-ındakı dəyişiklikləri daxil etmək üçün master branch-ınızı sürətli yƶnləndirin

Deyək ki, həm də server branch-nızı pull etməyə qərar verdiniz. git rebase <basebranch> <topicbranch>-ı işə salmaqdan əvvəl server branch-ını master branch -a rebase edə bilərsiniz. Mƶvzu branch-nı yoxlayır (bu vəziyyətdə, server) və əsas branch-a (master) qaytarır.

$ git rebase master server

Bu, server işinizi master işinizin üstündə, Server branch-nızı master branch-nızın üstünə rebasing etmək-da gƶstərildiyi kimi təkrarlayır.

Server branch-nızı `master` branch-nızın üstünə rebasing etmək
Figure 42. Server branch-nızı master branch-nızın üstünə rebasing etmək

Sonra əsas branch-ı (master) sürətlə irəli sürə bilərsiniz:

$ git checkout master
$ git merge server

Bütün işlər inteqrasiya olunduğuna gƶrə, client və server branch-larını silə bilərsiniz, bu da bütün bu proses üçün tarixinizi Son commit tarixi kimi qoyur:

$ git branch -d client
$ git branch -d server
Son commit tarixi
Figure 43. Son commit tarixi

Rebasing-in Təhlükələri

Ahh, lakin Ƨatışmazlıqlar olmadan rebasing-in zƶvqü olmaz,hansı ki onları bir sətirdə yekunlaşdırmaq olar.

Depolarınızdan kənarda mƶvcud olan və insanların üzərində işləyə bildikləri commitləri rebase etməyin.

Bu qaydaya əməl etsəniz, yaxşı olacaqsınız. Bunu etməsəniz, insanlar sizə nifrət edəcəklər və dostlarınız və ailəniz tərəfindən rüsvay olacaqsınız.

ĘÅŸyaları rebase etdiyinizdə mƶvcud commit-lərdən imtina edirsiniz və oxşar, lakin fərqli olanları yaradırsınız. ʏgər commit-ləri bir yerə push etsəniz və başqaları onları aşağı pull edib üzərində işləyirsə, sonra git rebase ilə yenidən yazıb yenidən push etsəniz, iş yoldaşların işlərini yenidən birləşdirməyə məcbur olacaqlar və işləriniz qarışıq olacaq. Ona gƶrə işlərini ƶzünüzə qaytarmağa Ƨalışın.

Ɩublic etdiyiniz işin rebasing olunanda problem yarada biləcəyinə dair bir nümunəyə baxaq. Tutaq ki, mərkəzi bir serverdən klonlaşdırırsınız və daha sonra bir az iş gƶrürsünüz.

Commit tarixƧəniz belə gƶrünür:

Deponu klonlaşdırın və üzərində bir az iş aparın.
Figure 44. Deponu klonlaşdırın və üzərində bir az iş aparın

İndi başqası birləşməyi əhatə edən daha Ƨox iş gƶrür və mərkəzi serverə işləyir. Siz gƶtürün və yeni uzaq branch-ı işinizə birləşdirərək tarixinizi bu kimi bir hala gətirin:

Daha Ƨox commit fetch edin və onları işinizə birləşdirin
Figure 45. Daha Ƨox commit fetch edin və onları işinizə birləşdirin

Sonra birləşən işi push edən şəxs geri qayıtmağı və işlərini dəyişdirməyi qərara alır; serverdəki tarixi yenidən yazmaq üçün git push --force tətbiq edirlər. Daha sonra yeni commit-ləri gətirərək həmin serverdən alırsınız.

Kimsə işinizə əsaslanaraq verdiyiniz commit-ləri tərk edərək, rebase edilmiş commit-ləri push edir.
Figure 46. Kimsə işinizə əsaslanaraq verdiyiniz commit-ləri tərk edərək, rebase edilmiş commit-ləri push edir

İndi ikiniz də turşu iƧindəsiniz. Bir git pull etsəniz, tarixin hər iki xəttini ƶzündə birləşdirən birləşmə əməliyyatı yaradacaqsınız və depo bu cür gƶrünəcək:

Eyni işdə yenidən yeni birləşmə commit-nə qoşulursunuz
Figure 47. Eyni işdə yenidən yeni birləşmə commit-nə qoşulursunuz

Tarixiniz bu kimi gƶrünəndə git log işlədirsinizsə, qarışıqlıq yaradan eyni müəllif, tarix və mesajı olan iki commit gƶrürsünüz. Bundan əlavə, bu tarixi yenidən serverə push etsəniz, insanları qarışdıra biləcək bütün əvəz edilmiş sənədləri mərkəzi serverə yenidən təqdim etmiş olacaqsınız. Digər developerin C4 və C6-ların tarixdə olmasını istəmədiyini güman etmək olduqca təhlükəsizdir; buna gƶrə ilk nƶvbədə yenidən Ƨap etdilər.

Rebase etdiyiniz zaman yenidən yazın

ʏgər belə bir vəziyyətdə ƶzünüzü taparsanız, Git sizə kƶmək edə biləcək daha bir sehrə sahibdir. ʏgər komandanızdakı kimsə işə əsaslandığınız işin üzərində yazılan dəyişiklikləri push edirsə, problem sizin kim olduğunuzu və yenidən yazdıqlarını anlamaqdır.

Məlum olub ki, SHA-1 yoxlama cədvəlinə əlavə olaraq, Git yalnız commit ilə təqdim olunan patch-a əsaslanan bir Ƨek məbləğini də hesablayır. Buna ā€œpatch-idā€ deyilir.

Yenidən yazılmış işi pull doün etsəniz və tərəfdaşınızdan aldığınız yeni işin üstünə yazsanız, Git tez-tez misilsiz sizin nəyi başa düşdüyünüzü yeni branch-ın üstünə tətbiq edə bilər.

Məsələn, əvvəlki ssenaridə, əgər Kimsə işinizə əsaslanaraq verdiyiniz commit-ləri tərk edərək, rebase edilmiş commit-ləri push edir olduğumuz zaman birləşmə yerinə git rebase teamone/master işlədiriksə, Git:

  • Branch-ımız üçün hansı işin ƶzünəməxsus olduğunu müəyyənləşdirin (C2, C3, C4, C6, C7)

  • Hansıların birləşmədiyini təyin edin (C2, C3, C4)

  • Hədəf branch-ına yenidən yazılmayanları təyin edin (C4 C4 'ilə eyni patch olduğundan)

  • Bu commit-ləri teamone/master başına tətbiq edin

Beləliklə, Eyni işdə yenidən yeni birləşmə commit-nə qoşulursunuz-də gƶrdüyümüz nəticənin əvəzinə daha Ƨox Force-pushed rebase işə yenidən başlayın kimi bir şeylə nəticələnərdik.

Force-pushed rebase işə yenidən başlayın
Figure 48. Force-pushed rebase işə yenidən başlayın

Bu yalnız ortağınızın hazırladığı C4 və C4' demək olar ki, eyni bir patch olduqda işləyir. ʏks təqdirdə, yenidən yükləmə bunun bir dublikat olduğunu sƶyləyə bilməyəcək və başqa bir C4-ə bənzər bir yamaq əlavə edəcəkdir (ehtimal ki, təmiz tətbiq olunmayacaq, çünki dəyişikliklər heƧ olmasa orada olacaq).

Normal bir git pull yerinə git pull --rebase işlətməklə bunu asanlaşdıra bilərsiniz. Və ya bu vəziyyətdə git rebase teamone/master ardınca git fetch ilə manual edə bilərsiniz.

git pull istifadə edirsinizsə və --rebase standart etmək istəyirsinizsə, git config --global pull.rebase true kimi bir şey ilə pull.rebase konfiqurasiya dəyərini təyin edə bilərsiniz.

HeƧ vaxt ƶz kompüterinizi tərk etməyən commit-ləri yenidən yerinə yetirsəniz, yaxşı olacaqsınız. ʏgər push etdiyiniz commit-ləri geri qaytarsanız, lakin başqa heƧ kim əsas gƶtürməmişsə, həmƧinin yaxşı olacaqsınız. ʏgər siz əvvəlcədən ictimailəşdirilmiş commit-ləri geri qaytarsanız və insanlar bu commit-ləri əsas gƶtürsələr, o zaman bəzi narahat problemlərə və komanda yoldaşlarınızın qınağına dĆ¼ÅŸÉ™ bilərsiniz.

ʏgər siz və ya tərəfdaş bir anda zəruri hesab edirsinizsə,hər kəsin git pull --rebase işlətdiyini bildiyinizdən əmin olun ki, bu da bir az daha sadə olur.

Rebase vs Birləşdirmək

İndi siz rebasing və birləşdirmə hərəkətlərini gƶrdünüz, hansının daha yaxşı olduğunu düşünə bilərsiniz. Buna cavab verməzdən əvvəl bir az geri Ƨəkilib tarixin nə demək olduğunu danışaq.

Bu baxımdan bir məqam odur ki, depozit tarixƧənizin tarixƧəsi əslində baş verənlərin qeydidir. Tarixi bir sənəddir, ƶz dəyərindədir və dəyişdirilməməlidir. Bu baxımdan, commit tarixinin dəyişdirilməsi demək olar ki, küfrdür; əslində nəyi ƶtürdüyünüz barədə lying danışırsınız. Birləşməyin qarışıq sıra seriyası varsa nə olacaq? Bu belə oldu və depoları bunu sonrakı nəsillər üçün saxlamalıdır.

Qarşı nƶqtə, commit tarixinin olmasıdır, yəni layihənizin necə edildiyi haqqında hekayədir. Bir kitabın ilk layihəsini yayımlamazsınız və proqramınızı necə qoruyacağınıza dair təlimat diqqətlə redaktəyə etməlisiniz. Bu, hekayəni gələcək oxuculara ən yaxşı şəkildə izah etmək üçün rebase və filter-branch kimi vasitələrdən istifadə edən dĆ¼ÅŸÉ™rgədir.

İndi gələk birləşməyin və ya rebasing etməyin daha yaxşı olması sualına: ümid edirik bunun asan olmadığını gƶrərsiniz. Git güclü bir vasitədir və tarixinizlə birlikdə Ƨox şey etməyə imkan verir, lakin hər komanda və hər layihə fərqlidir.

Artıq hər ikisinin necə işlədiyini bildiyinizdən, hansınızın vəziyyətiniz üçün ən uyğun olduğunu qərar verməyiniz sizə bağlıdır.

Ümumiyyətlə, hər iki dünyanın ən yaxşısını qazanmağın yolu hekayənizi təmizləmək üçün onları təkzib etmədən əvvəl etdiyiniz, lakin hələ paylaşmadığınız yerli dəyişiklikləri geri qaytarmaqdır.

scroll-to-top