Git
Chapters ▾ 2nd Edition

3.6 Git Branching - Rebasing

Rebasing

Git’də dəyişiklikləri bir budaqdan digərinə birləşdirməyin iki əsas yolu var: mergerebase. 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ə, clientserver 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 C4C6-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ığı C4C4' 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 rebasefilter-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.