Git
Chapters ▾ 2nd Edition

5.2 Paylanmış Git - Layihəyə Töhfə vermək

Layihəyə Töhfə vermək

Bir layihəyə necə töhfə verəcəyinizi izah etməyin əsas çətinliyi bunu necə etmək barədə olan çoxsaylı dəyişikliklərdir. Git çox çevik olduğu üçün insanlar bir çox cəhətdən birlikdə işləyə bilər və necə töhfə verəcəyinizi izah etmək problemlidir - hər layihə bir az fərqlidir. İştirak edən bəzi dəyişənlər aktiv töhfə sayı, seçilmiş iş axını, commit girişiniz və bəlkə də xarici töhfə metodudur.

Birinci dəyişən aktiv iştirakçı sayı - bu layihəyə neçə istifadəçi kodu töhfə edir və neçə dəfə? Bir çox hallarda, gündə bir neçə layihə üçün iki və ya üç developer və ya daha az hərəkətsiz layihə üçün daha az developer lazım olacaq. Daha böyük şirkətlər və ya layihələr üçün developer-lərin sayı minlərlə ola bilər, hər gün yüzlərlə və ya minlərlə commit gəlir. Bu vacibdir, çünki daha çox developerlə kodunuzun təmiz tətbiq olunduğuna və ya asanlıqla birləşdirilə biləcəyinə əmin olmaq üçün daha çox problem qarşılaşırsınız. Təqdim etdiyiniz dəyişikliklər işlədiyiniz müddətdə birləşdirilmiş və ya dəyişikliklərinizin təsdiqlənməsini və tətbiq olunmasını gözlədiyi zaman köhnəlmiş və ya ciddi şəkildə pozulmuş ola bilər. Kodunuzu həmişə aktual və commit-lərinizi necə keçərli saxlaya bilərsiniz?

Növbəti dəyişən, layihə üçün istifadə olunan iş axınlarıdır. Hər bir developerin əsas kod xəttinə bərabər yazılı girişi olması mərkəzləşdirilib? Layihədə bütün patch-ları yoxlayan bir qoruyucu və ya inteqrasiya meneceri varmı? Bütün patch-lar araşdırılıb təsdiqlənibmi? Bu müddətdə iştirak edirsiniz? Leytenant bir sistem var və ilk növbədə işinizi onlara təqdim etməlisiniz?

Növbəti dəyişən commit girişinizdir. Bir layihəyə töhfə vermək üçün tələb olunan iş axını, layihəyə yazılı girişiniz varsa, etmədiyinizdən daha çox fərqlidir. Yazı icazəniz yoxdursa, layihə töhfə olunan işləri necə qəbul etməyi üstün tutur? Hətta bir politikası varmı? Bir anda nə qədər işə töhfə verirsiniz? Nə qədər tez-tez iştirak edirsiniz?

Bütün bu suallar bir layihəyə necə təsirli bir şəkildə töhfə verdiyinizə və hansı iş axınının sizin üçün tərcih edilib istifadə edə biləcəyinizə təsir edə bilər. Bunların hər birinin aspektlərini sadə vəziyyətdən daha mürəkkəbinə keçərək bir sıra istifadə hallarında əhatə edəcəyik; praktikada ehtiyac duyduğunuz xüsusi iş axınlarını bu nümunələrdən qura bilməlisiniz.

Commit Guidelines

Xüsusi istifadə hallarına baxmağa başlamazdan əvvəl commit mesajları haqqında qısa bir qeyd edək. Commit yaratmaq və buna bağlı qalmaq üçün yaxşı guideline-a sahib olmaq Git və başqları ilə işləməyi daha çox asanlaşdırır. Git layihəsi, patch-lar göndərilməsini təmin edən bir sıra yaxşı tövsiyələri özündə cəmləşdirən bir sənəd təqdim edir - onu Git mənbə kodundan Documentation/SubmittingPatches sənədində oxuya bilərsiniz.

Birincisi, təqdimatlarınızda boşluq xətaları olmamalıdır. Git bunu yoxlamaq üçün asan bir yol təqdim edir - commit etməzdən əvvəl, boşluq xətalarını müəyyənləşdirən və onları sizin üçün siyahıya salan git diff --check əmrini tətbiq edin.

`git diff --check` nəticəsi
Figure 57. git diff --check nəticəsi

Commit etmədən əvvəl bu əmri işlədirsinizsə, digər developerləri qıcıqlandıra biləcək boşluq məsələlərini etməyiniz barədə edib etməycəyinizi anlaya bilərsiniz.

Sonrasında, hər bir commiti məntiqi olaraq ayrı bir dəyişiklik etməyə çalışın. Əgər edə bilsəniz, dəyişikliklərinizi həzm oluna bləcək hala çevirməyə çalışın - bütün həftə sonu üçün beş fərqli mövzu kodlamayın və sonra hamısını bazar ertəsi bir massiv commit kimi təqdim edin. Həftə sonu commit etməsəniz belə, bazar ertəsi günü işinizi hər mövzu üçün ən azı bircommit etmək üçün hazırlıq sahəsindən istifadə edin və hər commit üçün faydalı bir mesaj əlavə edin. Bəzi dəyişikliklər eyni faylı dəyişdirirsə, qismən sənədləşdirmək üçün git add --patch istifadə edin(Ətraflı detallar Interaktiv Səhnələşdirmə-da əhatə olunub). Branch-ın ucundakı layihə snapshotu bir və ya beş dəyişiklik etməyinizlə eynidir. Buna görə də, dəyişikliklər bir anda əlavə olunduğundan developerlərin işini asanlaşdırmaq üçün dəyişikliklərinizi nəzərdən keçirməyə çalışın.

Bu yanaşma daha sonra ehtiyacınız olduqda dəyişikliklərdən birini çıxarmağı və ya geri qaytarmağı da asanlaşdırır. Tarixi Yenidən Yazmaq tarixin yenidən yazılması və interaktiv şəkildə qurulması üçün bir sıra faydalı Git tövsiyələrini təsvir edir - bu vasitələrdən istifadə edərək başqasına göndərməzdən əvvəl təmiz və başa düşülən bir tarixi hazırlamaqda istifadə edin.

Unudulmamalı olan son şey commit mesajıdır. Keyfiyyətli commit mesajlar yaratmaq vərdişinə yiyələnmək Git ilə işləməyi asanlaşdırır. Bir qayda olaraq, mesajlarınız təxminən 50 işarədən çox olmayan bir dəyişikliyi qısa təsvir edən, boş bir xətt izləyən və daha ətraflı izahat verilən bir xətt ilə başlamalıdır. Git layihəsi tələb edir ki, daha ətraflı izahat dəyişiklik üçün motivasiyanızı daxil etsin və həyata keçirilməsini əvvəlki davranışla müqayisə etsin - bu əməl etmək üçün yaxşı bir təlimatdır. Commit mesajınızı əmr qutusuna yazın: "Fix bug","Fixed bug" və ya "Fixes bug." deyil. Budur, Tim Pope tərəfindən yazılmış original məqalə:

Capitalized, short (50 chars or less) summary

More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.

Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug."  This convention matches up with commit messages generated
by commands like git merge and git revert.

Further paragraphs come after blank lines.

- Bullet points are okay, too

- Typically a hyphen or asterisk is used for the bullet, followed by a
  single space, with blank lines in between, but conventions vary here

- Use a hanging indent

Bütün commit mesajlarınız bu modeli təqib edərsə, sizin və əməkdaşlıq etdiyiniz developer-lər üçün işlər çox asan olacaqdır. Git layihəsi yaxşı formatlanmış commit mesajlarına malikdir - qəşəng formatlı bir layihə commit-i tarixinin necə olduğunu görmək üçün orada git log --no-merges işlətməyə çalışın.

Note
Dediyimiz kimi edin, etdiyimiz kimi yox.

Qısaca demək lazımdırsa, bu kitabdakı nümunələrin çoxunda bunun kimi yaxşı işlənmiş commit mesajları yoxdur; bunun yerinə git commit üçün -m seçimi istifadə edirik.

Bir sözlə, etdiyimiz kimi deyil, dediyimiz kimi edin.

Private Kiçik Komanda

Qarşınıza gələ biləcəyiniz ən sadə quraşdırma, bir və ya iki developeri olan xüsusi bir layihədir. Bu kontekstdə “private,”, qapalı mənbə anlamına gəlir - xarici dünya üçün əlçatmazdır. Siz və digər developerlərinizin hamısının depoya girmə imkanı var.

Bu mühitdə Subversion və ya başqa bir mərkəzləşdirilmiş sistem istifadə edərkən edə biləcəyinizə bənzər bir iş axını izləyə bilərsiniz.

Siz hələ də oflayn işləmə və olduqca sadə branch-lara ayırma və birləşmə kimi şeylərin üstünlüklərini əldə edirsiniz, amma iş axını çox oxşar ola bilər; Əsas fərq, birləşmələrin törədildiyi vaxt serverdə deyil, müştəri tərəfində baş verməsidir. İki developerin ortaq bir depo ilə birlikdə işə başladıqda nə görünə biləcəyinə baxaq. İlk developer John depolarını klonlaşdırır, dəyişiklik edir və local olaraq yerinə yetirir. Protokol mesajları bu nümunələrdə bir qədər qısaldılması üçün ... ilə əvəz edilmişdir.

# John's Machine
$ git clone john@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'Remove invalid default value'
[master 738ee87] Remove invalid default value
 1 files changed, 1 insertions(+), 1 deletions(-)

İkinci developer Jessica da eyni şeyi edir - depoları klonlaşdırır və dəyişiklik edir:

# Jessica's Machine
$ git clone jessica@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'Add reset task'
[master fbff5bc] Add reset task
 1 files changed, 1 insertions(+), 0 deletions(-)

İndi Jessica öz işini yalnız yaxşı işləyən serverə push edir:

# Jessica's Machine
$ git push origin master
...
To jessica@githost:simplegit.git
   1edee6b..fbff5bc  master -> master

Yuxarıdakı çıxışın son sətri push əməliyyatından faydalı bir geri göndərmə mesajını göstərir. Əsas format <oldref>..<newref> fromref → toref` şəklindədir. Burada oldref köhnə referans mənasına gəlir, newref yeni referans mənasına gəlir, fromref push edilən local referansdır və toref yenilənən uzaq referansın adıdır. Müzakirələrdə aşağıdakı kimi oxşar nəticəni görəcəksən, buna görə məna haqqında əsas təsəvvürə sahib olmaq, depoların müxtəlif vəziyyətlərini anlamağa kömək edəcəkdir. Daha çox detallı məlumat üçün git-push-a baxın.

Bu nümunə ilə davam edək, qısa müddətdən sonra John bəzi dəyişikliklər edir, onları local depolarına commit edir və eyni serverə push etməyə çalışır:

# John's Machine
$ git push origin master
To john@githost:simplegit.git
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'john@githost:simplegit.git'

Bu vəziyyətdə, John’un push etməsi Jessica’nın dəyişikliklərini daha əvvəl itələməsinə görə uğursuz olur. Subversiya anlamaq xüsusilə vacibdir, çünki iki developerin eyni faylı düzəltmədiyini görəcəksiniz. Müxtəlif fayllar Git ilə düzəldilibsə Subversion avtomatik olaraq serverdə belə bir birləşmə əmələ gətirsə də, local əməliyyatları birləşdirməlisiniz. Başqa sözlə, John əvvəlcə Jessica’nın yuxarıdakı dəyişikliklərini götürməli və push etməyə icazə verilməzdən əvvəl onları local depolarına birləşdirməlidir.

İlk addım olaraq John Jessica’nın işini fetch edir (bu yalnız fetches Jessica’nın yuxarı işidir, hələ onu John’un işinə birləşdirmir):

$ git fetch origin
...
From john@githost:simplegit
 + 049d078...fbff5bc master     -> origin/master

Bu halda John’un local deposu bu kimi bir şeyə bənzəyəcəkdir:

John’un tarix ayrılığı
Figure 58. John’un tarix ayrılığı

İndi John Jessica’nın öz local işinə apardığı işləri birləşdirə bilər:

$ git merge origin/master
Merge made by the 'recursive' strategy.
 TODO |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

Yerli birləşmə rəvan getdikcə Johnun yenilənmiş tarixi indi belə görünəcək:

John’un deposu `origin/master` birləşdirdikdən sonra
Figure 59. John’un deposu origin/master birləşdirdikdən sonra

Bu anda John Jessica’nın heç bir işinin onun hər hansı birinə təsir etmədiyindən əmin olmaq üçün bu yeni kodu sınamaq istəyə bilər və hər şeyin yaxşı göründüyü müddətcə nəhayət yeni birləşdirilmiş işi serverə push edə bilər:

$ git push origin master
...
To john@githost:simplegit.git
   fbff5bc..72bbc59  master -> master

Sonda John’un commit tarixi belə görünəcək:

`origin` serverə pushing etdikdən sonra John’un tarixi
Figure 60. origin serverə pushing etdikdən sonra John’un tarixi

Bu vaxt, Jessica issue54 adlı yeni bir mövzu branch-ı yaratdı və bu branch üçün üç commit yaratdı. O, John’un dəyişikliklərini fetch etmədi, buna görə də commit tarixi bu kimi görünür:

Jessica’nın mövzu branch-ı
Figure 61. Jessica’nın mövzu branch-ı

Birdən, Jessica John’un serverə yeni bir iş sövq etdiyini və ona bir nəzər salmaq istədiyini öyrənir və buna görə hələ də olmayan serverdən bütün yeni məzmunu ala bilir:

# Jessica's Machine
$ git fetch origin
...
From jessica@githost:simplegit
   fbff5bc..72bbc59  master     -> origin/master

Bu vaxt John-un pushed up etdiyi işi pulls down edir. Jessica’nın tarixi indi belə görünür:

John dəyişikliklərini aldıqdan sonra Jessica’nın tarixi
Figure 62. John dəyişikliklərini aldıqdan sonra Jessica’nın tarixi

Jessica onun mövzu branch-nın hazır olduğunu düşünür, ancaq John-un aldığı işin hansı hissəsini işinə birləşdirməli olduğunu bilmək istəyir. Bunu tapmaq üçün git log işlədir:

$ git log --no-merges issue54..origin/master
commit 738ee872852dfaa9d6634e0dea7a324040193016
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 16:01:27 2009 -0700

   Remove invalid default value

issue54..origin/master sintaksis Git-dən yalnız sonuncu branch-da olan commit-ləri göstərməyi tələb edən bir log filtridir (bu vəziyyətdə origin/master) bunlar ilk branch-da yoxdur (bu vəziyyətdə issue54). Daha ətraflı bu sintaksisi Commit Aralıqları-da əldə edə bilərsiniz.

Yuxarıdakı çıxışdan, John’un Jessica’nın local işinə birləşməməsini təmin etdiyi bir commit-in olduğunu görə bilərik. origin/master ilə birləşirsə, bu, local işini dəyişdirəcək yeganə commit-dir.

İndi Jessica mövzu işini özünün master branch-a birləşdirə bilər, John’un işini (origin/master) master branch-a birləşdirə bilər və sonra yenidən serverə push edə bilər.

Birincisi (bütün işlərini "problem54" mövzu branch-ı üzərində işləmiş), Jessica bütün bu işə inteqrasiya etməyə hazırlaşaraq yenidən master branch-a keçir:

$ git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.

Jessica əvvəlcə origin/master və ya issue54 branch-nı birləşdirə bilər — hər ikisi upstream olduğu üçün sıra heç bir əhəmiyyət kəsb etmir. Son snapshot hansı seçimi seçməsindən asılı olmayaraq eyni olmalıdır; yalnız tarix fərqli olacaq. Əvvəlcə issue54 branch-nı birləşdirməyi seçir:

$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
 README           |    1 +
 lib/simplegit.rb |    6 +++++-
 2 files changed, 6 insertions(+), 1 deletions(-)

Heç bir problem yaranmır; göründüyü kimi sadə və sürətli birləşmə idi. İndi Jessica John’un origin/master branch-da oturan John’un əvvəllər əldə edilmiş işlərini birləşdirərək local birləşmə prosesini tamamlayır.

$ git merge origin/master
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
 lib/simplegit.rb |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Hər şey təmiz birləşir və Jessica’nın tarixi indi belə görünür:

John dəyişikliklərini birləşdirdikdən sonra Jessica’nın tarixi
Figure 63. John dəyişikliklərini birləşdirdikdən sonra Jessica’nın tarixi

İndi origin/master Jessica’nın master branch-dan əldə edilə bilər, buna görə uğurla push etməyi bacarmalıdır (Johnun bu vaxt başqa dəyişiklik etmədiyini güman edərək):

$ git push origin master
...
To jessica@githost:simplegit.git
   72bbc59..8059c15  master -> master

Hər bir developer bir neçə dəfə commit etdi və bir-birinin işlərini uğurla birləşdirdi.

Bütün dəyişiklikləri serverə push etdikdən sonra Jessica’nın tarixi
Figure 64. Bütün dəyişiklikləri serverə push etdikdən sonra Jessica’nın tarixi

Bu ən sadə iş axınlarından biridir. Bir müddət (ümumiyyətlə bir mövzu branch-da) işləyəcəksiniz və bu işi inteqrasiya olunmağa hazır olduqda master branch-nıza birləşdirəcəksiniz. Bu işi bölüşmək istədikdə dəyişdirildiyi təqdirdə origin/master- dən master-i götürün və birləşdirin və nəhayət serverdəki master branch-na push edin. Ümumi ardıcıllıq belə olacaqdır:

Sadə bir multiple-developer Git iş axını üçün hadisələrin ümumi ardıcıllığı
Figure 65. Sadə bir multiple-developer Git iş axını üçün hadisələrin ümumi ardıcıllığı

Private İdarə olunan Komanda

Bu növbəti ssenaridə daha böyük bir private qrupda iştirakçı rollarına baxacaqsınız. Kiçik qrupların xüsusiyyətlər üzərində əməkdaşlıq etdiyi bir mühitdə necə işləmək lazım olduğunu öyrənəcəksiniz, bundan sonra bu komanda əsaslı töhfələr başqa tərəf tərəfindən birləşdirilir.

Deyək ki, John və Jessica bir xüsusiyyət üzərində işləyirlər (buna “featureA” deyək), Jessica və üçüncü developer Josie isə ikinci (“featureB” deyək) üzərində işləyir. Bu vəziyyətdə, şirkət ayrı-ayrı qrupların işi yalnız müəyyən mühəndislər tərəfindən inteqrasiya olunduğu və əsas reponun master branch-ı yalnız həmin mühəndislər tərəfindən yenilənə biləcəyi bir növ inteqrasiya-menecer iş axınından istifadə edir. Bu ssenaridə bütün işlər komanda əsaslı branch-larda aparılır və sonradan inteqratorlar tərəfindən bir yerə yığılır.

Bu mühitdə iki fərqli developer ilə paralel olaraq iki xüsusiyyəti üzərində işlədiyi üçün Jessica’nın iş axınını izləyək. Artıq öz depolarını klonlaşdırdığını düşünərək ilk olaraq featureA üzərində işləməyi qərara alır.

Xüsusiyyət üçün yeni bir branch yaradır və orada bəzi işlər görür:

# Jessica's Machine
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ vim lib/simplegit.rb
$ git commit -am 'Add limit to log function'
[featureA 3300904] Add limit to log function
 1 files changed, 1 insertions(+), 1 deletions(-)

Bu anda, işini John ilə bölüşməlidir, ona görə də featureA branch-ı serverə commit edir. Jessica’nın master branch-a push etməyə icazəsi yoxdur - yalnız inteqratorlar bunu edir - ona görə də John ilə əməkdaşlıq etmək üçün başqa bir branch-a push etmək məcburiyyətindədir:

$ git push -u origin featureA
...
To jessica@githost:simplegit.git
 * [new branch]      featureA -> featureA

Jessica John’a e-poçt göndərərək featureA adlı bir branch-a bir iş push etdiyini və indi baxa biləcəyini yazar. John’dan rəy gözlədiyi müddətdə, Jessica Josie ilə featureB üzərində işləməyə qərar verdi. Başlamaq üçün o, serverin master branch-dan istifadə edərək yeni bir xüsusiyyət branch-na başlayır:

# Jessica's Machine
$ git fetch origin
$ git checkout -b featureB origin/master
Switched to a new branch 'featureB'

İndi Jessica featureB branch-da bir neçə commit yaradır:

$ vim lib/simplegit.rb
$ git commit -am 'Make ls-tree function recursive'
[featureB e5b0fdc] Make ls-tree function recursive
 1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'Add ls-files'
[featureB 8512791] Add ls-files
 1 files changed, 5 insertions(+), 0 deletions(-)

Jessica’s deposu indi belə görünür:

Jessica’nın ilkin commit tarixi
Figure 66. Jessica’nın ilkin commit tarixi

İşini push etməyə hazırdır, amma Josie-dən bir e-poçt alır ki, bunun üzərində bir neçə ilkin “featureB” işi olan bir branch artıq featureBee branch-ı olaraq serverə push edildi. Jessica, işini serverə push etməzdən əvvəl bu dəyişiklikləri özü ilə birləşdirməlidir. Jessica əvvəlcə Josie’nin dəyişikliklərini git fetch ilə qəbul edir:

$ git fetch origin
...
From jessica@githost:simplegit
 * [new branch]      featureBee -> origin/featureBee

Jessica’nın hələ yoxlanılmış featureB branch-ında olduğunu düşündükdə indi Josie’nin işini git merge ilə bu branch-a birləşdirə bilər:

$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
 lib/simplegit.rb |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

Bu anda, Jessica bu birləşdirilmiş “featureB” işinin hamısını yenidən serverə qaytarmaq istəyir, ancaq sadəcə öz featureB branch-nı push etmək istəmir. Əksinə, Josie artıq yuxarı bir featureBee branch-na başlamış olduğundan, Jessica özü ilə birlikdə etdiyi bu branch-a push etmək istəyir:

$ git push -u origin featureB:featureBee
...
To jessica@githost:simplegit.git
   fba9af8..cd685d1  featureB -> featureBee

Bu refspec adlanır. Git refspecs hnlarla edə biləcəyiniz fərqli şeylər barədə daha ətraflı müzakirə etmək üçün Refspec baxın. -u bayrağına da diqqət yetirin; bu, branch-ları daha sonra push və pull etmək üçün konfiqurasiya edən --set-upstream üçün qısaldılmış formasıdır.

Birdən, Jessica John’dan e-poçt alır, onun əməkdaşlıq etdikləri featureA branch-a bəzi dəyişikliklər etdiyini söyləyir və Jessica’dan onlara baxmağı xahiş edir. Yenə Jessica sadə bir git fetch işlədərək John’un son işi də daxil olmaqla serverdən bütün yeni məzmunu əldə edir:

$ git fetch origin
...
From jessica@githost:simplegit
   3300904..aad881d  featureA   -> origin/featureA

Jessica yeni gətirilən featureA branch-nın kontentini eyni branch-ın local kopyası ilə müqayisə edərək John’un yeni işinə baxa bilər.

$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 19:57:33 2009 -0700

    Increase log output to 30 from 25

Əgər Jessica gördüyünü bəyənsə, John’un yeni işini local featureA branch-a birləşdirə bilər:

$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
 lib/simplegit.rb |   10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)

Nəhayət, Jessica birləşənlərin hamısına bir neçə kiçik dəyişiklik etmək istəyə bilər, buna görə də bu dəyişiklikləri etmək, local featureA branch-na tapşırmaq və nəticəni yenidən serverə push etmək pulsuzdur.

$ git commit -am 'Add small tweak to merged content'
[featureA 774b3ed] Add small tweak to merged content
 1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
   3300904..774b3ed  featureA -> featureA

Jessica’nın commit tarixi indi belə görünəcək:

Jessica’nın bir xüsusiyyət branch-na commit etdikdən sonra tarixi
Figure 67. Jessica’nın bir xüsusiyyət branch-na commit etdikdən sonra tarixi

Bir anda Jessica, Josie və John inteqratorlara serverdəki featureAfeatureBee branch-larının ana xəttə inteqrasiyaya hazır olduqlarını bildirirlər. İnteqrasiya edənlər bu branch-ları ana xəttə birləşdirdikdən sonra getch yeni birləşdirmə commit-ni aşağı çəkəcək və tarix belə görünəcəkdir:

Hər iki mövzu branch-nı birləşdirdikdən sonra Jessica’nın tarixi
Figure 68. Hər iki mövzu branch-nı birləşdirdikdən sonra Jessica’nın tarixi

Bir çox qrup Git-ə keçdi, çünki bu müddətdə çox sayda komandanın paralel işləməsi, müddətin sonunda fərqli iş xətlərini birləşməsi mümkündür. Bir komandanın kiçik alt qruplarının bütün branch-ı cəlb etməməsi və maneə olmadan uzaq branch-larla işləmək bacarığı Git’in böyük bir faydalarından biridir. Burada gördüyünüz iş axınının ardıcıllığı belə olacaqdır:

İdarə olunan komandanın iş axınının əsas ardıcıllığı
Figure 69. İdarə olunan komandanın iş axınının əsas ardıcıllığı

Forked Public Layihəsi

Public layihələrə töhfə vermək bir az fərqlidir. Layihə üzrə branch-ları birbaşa yeniləmək icazəniz olmadığına görə işinizi başqa yollarla təmirçilərə verməlisiniz. Bu ilk nümunə asan forking dəstəyini dəstəkləyən Git hostlarında forking vasitəsilə töhfəni təsvir edir. Bir çox hosting saytları (GitHub, BitBucket, repo.or.cz və başqaları daxil olmaqla) bunu dəstəkləyir və bir çox layihə aparıcısı bu töhfə tərzini gözləyirlər. Növbəti bölmə, e-poçt vasitəsilə töhfə patch-larını qəbul etməyi üstün edən layihələr haqqındadır.

Birincisi, ehtimal ki, əsas depo klonlaşdırmaq, töhfə verməyi planlaşdırdığınız patch və ya patch seriyası üçün bir mövzu branch-ı yaratmaq və orada işlərinizi etmək istəyəcəksiniz. Ardıcıllıq əsasən belə görünür:

$ git clone <url>
$ cd project
$ git checkout -b featureA
  ... work ...
$ git commit
  ... work ...
$ git commit
Note

İşinizi bir commit-ə endirmək üçün və ya təmirçinin nəzərdən keçirməsini asanlaşdırmaq məqsədi ilə işi yenidən düzəltmək üçün rebase -i istifadə edə bilərsiniz - interaktiv reabilitasiya haqqında daha çox məlumat üçün Tarixi Yenidən Yazmaq-a baxın.

Branch-nızın işini bitirdikdə və onu yenidən təmin edənlərə töhfə verməyə hazır olduğunuzda, orijinal layihə səhifəsinə keçin və layihənin öz yazıla bilən fork-unu yaradaraq “Fork” düyməsini basın. Daha sonra bu depo URL-ni local depo üçün yeni bir remote kimi əlavə etməlisiniz; bu misalda onu myfork adlandıraq:

$ git remote add myfork <url>

Daha sonra yeni işinizi bu depoya köçürməlisiniz. Üzərində işlədiyiniz mövzu branch-nı forked deponuza push etmək, bu işi master branch-nızla birləşdirib onu push etmək yerinə daha asandır.

Səbəb, işinizin qəbul edilmədiyi və ya cherry-picked olduğu təqdirdə, master branch-nızı geri çevirməyiniz lazım deyil (Git cherry-pick əməliyyatına daha ətraflı Rebasing və Cherry-Picking İş Axınları baxa bilərsiniz). Əgər işçiləriniz merge, rebase, və ya cherry-pick işlərini görsələr, nəhayət öz depolarından pulling edərək geri qaytaracaqsınız. Hər halda işinizi aşağıdakılarla push edə bilərsiniz:

$ git push -u myfork featureA

İşləriniz deponuzun fork-na push edildikdən sonra orijinal layihənin aparıcılarını birləşdirmək istədikləri iş barədə xəbərdar etməlisiniz. Buna genel olaraq pull request adlanır və ümumiyyətlə veb sayt vasitəsilə belə bir sorğu yaradırsınız - GitHub-un GitHub -dan keçəcəyimiz “Pull Request” mexanizmi var. - ya da git request-pull əmrini işlədərək sonrakı nəticəni layihə aparıcısına manual olaraq e-poçt ilə göndərə bilərsiniz.

git request-pull əmri mövzu branch-nızın pull edildiyini və Git depozit URL-nin pull edilməsini istədiyiniz əsas bölməni götürür və pull edilməsini xahiş etdiyiniz bütün dəyişikliklərin xülasəsini hazırlayır. Məsələn, Jessica John’a bir sorğu göndərmək istəsə və o, yalnız push etdiyi mövzu branch-da iki əmr yerinə yetirirsə, bunu edə bilər:

$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
Jessica Smith (1):
        Create new function

are available in the git repository at:

  git://githost/simplegit.git featureA

Jessica Smith (2):
      Add limit to log function
      Increase log output to 30 from 25

 lib/simplegit.rb |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

Bu çıxışı texniki işçiyə göndərmək olar - bu, işin haradan qaynaqlandığını, comiit-ləri ümumiləşdirir və yeni işin haradan pull ediləcəyini müəyyənləşdirir.

Təminatçı olmadığınız bir layihədə, ümumiyyətlə, master kimi bir branch-ın olması, origin/master kimi bir branch-ın olması və rədd edildiyi təqdirdə asanlıqla atıla biləcəyiniz mövzu branch-larında işlərinizi etmək daha asandır. İş temalarını mövzu branch-larına ayırmaq həm də əsas deponun ucu bu vaxt tərpənibsə və artıq təmiz tətbiq olunmadığı təqdirdə işinizi yenidən yazmağı asanlaşdırır. Məsələn, ikinci bir iş mövzusunu layihəyə təqdim etmək istəyirsinizsə, yalnız pushed up etdiyiniz mövzu şöbəsində işləməyin - əsas deponun master branch-ından başlayın:

$ git checkout -b featureB origin/master
  ... work ...
$ git commit
$ git push myfork featureB
$ git request-pull origin/master myfork
  ... email generated request pull to maintainer ...
$ git fetch origin

İndi mövzularınızın hər biri silos içərisindədir - patch növbəsinə bənzər - mövzuları bir-birinə qarışan və ya bir-birinə qarışmadan yenidən yaza, yenidən istifadə edə və dəyişdirə bilərsiniz:

İlkin `featureB` işinin  commit tarixi
Figure 70. İlkin featureB işinin commit tarixi

Layihə aparıcısı bir dəstə başqa patch pulled etdi və ilk branch-nızı sınadı, amma artıq təmiz birləşmə olmadı. Bu vəziyyətdə, bu branch-ı origin/master-in üstünə qaytarmağa, təmirçi üçün olan münaqişələri həll etməyə və dəyişikliklərinizi yenidən göndərməyə cəhd edə bilərsiniz:

$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA

İndi bu tarixiniz featureA işindən sonra commit tarixi kimi görünməsi üçün yenidən yazır.

`featureA` işindən sonra commit tarixi
Figure 71. featureA işindən sonra commit tarixi

Branch-ı rebase etdiyinizə görə serverdəki featureA branch-nı bir nəsil olmayan bir commit ilə əvəz edə bilmək üçün -f seçimini əmrdə göstərməlisiniz. Alternativ bu yeni işi serverdəki fərqli bir branch-a (bəlkə də featureAv2 adlandırmaq olar) yönəltmək olar. Gəlin daha bir ssenariyə baxaq: təmirçi ikinci branch-ınızdakı işə baxdı və konsepsiyanı bəyəndi, ancaq bir icra detalını dəyişdirməyinizi istədi. Layihənin indiki master branch-dan kənara qoyulacaq işi köçürmək üçün bu fürsətdən istifadə edəcəksiniz. Mövcud origin/master branch-na əsaslanan yeni bir branch açırsınız, featureB dəyişikliklərini sıxışdırırsınız, hər hansı bir münaqişəni həll edirsiniz, tətbiqetməni dəyişdirirsiniz və sonra yeni bir branch olaraq push edirsiniz:

$ git checkout -b featureBv2 origin/master
$ git merge --squash featureB
  ... change implementation ...
$ git commit
$ git push myfork featureBv2

--squash seçimi birləşdirilmiş branch-dakı bütün işləri alır və bir birləşmə əməliyyatı etmədən həqiqi birləşmə baş vermiş kimi bir depo vəziyyətini yaradan bir dəyişiklik halına gətirir. Bu, gələcək commit-inizin yalnız bir valideynə sahib olacağını və yeni bir commiti qeyd etməzdən əvvəl bütün dəyişiklikləri başqa bir branch-a təqdim etməyinizi və daha sonra daha çox dəyişiklik etməyinizi təmin edəcək deməkdir. Qeyri-adi birləşmə prosesi halında birləşməni təxirə salmaq üçün --no-commit seçimi faydalı ola bilər. Bu anda, tələb olunan dəyişiklikləri etdiyiniz barədə təmirçiyə xəbər verə bilərsiniz və bu dəyişiklikləri featureBv2 branch-nızda tapa bilər.

`featureBv2` işindən sonra commit tarixi
Figure 72. featureBv2 işindən sonra commit tarixi

E-poçt Üzərindən Public Layihə

Bir çox layihədə patch-ları qəbul etmək üçün prosedurlar qurulmuşdur - hər bir layihə üçün xüsusi qaydaları yoxlamaq lazımdır, çünki onlar fərqli olurlar. Bir developer poçt siyahısı vasitəsilə patch-ları qəbul edən bir neçə daha köhnə, daha böyük layihələr olduğundan indi bir nümunəyə baxacağıq.

İş axını əvvəlki istifadə vəziyyətinə bənzəyir - işlədiyiniz hər patch seriyası üçün mövzu branch-ları yaradırsınız. Fərq onları layihəyə necə təqdim etməyinizdir. Layihəni forking etmək və öz yazıla bilən versiyanıza push etmək əvəzinə hər bir sıra seriyasının e-poçt versiyasını hazırlayır və onları developer poçt siyahısına göndərirsiniz:

$ git checkout -b topicA
  ... work ...
$ git commit
  ... work ...
$ git commit

İndi poçt siyahısına göndərmək istədiyiniz iki əmr var. Siyahıya e-poçt göndərə biləcəyiniz mbox formatlı faylları yaratmaq üçün git format-patch istifadə edirsiniz - hər bir tapşırığı mövzu mesajının birinci sətri olan bir e-poçt mesajına və mesajın qalan hissəsini əlavə edir commit etdiyi patch body kimi təqdim olunur. Bunun xoş tərəfi budur ki, format-patch ilə yaradılan bir e-poçtdan bir patch tətbiq etmək bütün commit məlumatlarını düzgün saxlayır.

$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch

format-patch əmri yaratdığı patch fayllarının adlarını yazdırır. -M seçimi Git-ə adları axtarmağı tapşırır. Fayllar belə görünür:

$ cat 0001-add-limit-to-log-function.patch
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] Add limit to log function

Limit log functionality to the first 20

---
 lib/simplegit.rb |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
   end

   def log(treeish = 'master')
-    command("git log #{treeish}")
+    command("git log -n 20 #{treeish}")
   end

   def ls_tree(treeish = 'master')
--
2.1.0

Göndərmə mesajında göstərmək istəmədiyiniz e-poçt siyahısı üçün daha çox məlumat əlavə etmək üçün bu patch fayllarını düzəldə bilərsiniz. --- sətri ilə patch-ın əvvəlində ( diff --git xətti) arasında mətn əlavə etsəniz, developerlər onu oxuya bilər, amma patch prosesi tərəfindən yox sayılacaqdır.

Bunu bir poçt siyahısına göndərmək üçün faylı e-poçt proqramınıza yapışdıra və ya komanda xətti proqramı vasitəsilə göndərə bilərsiniz. Mətnin yapışdırılması tez-tez formatlaşdırma problemlərinə səbəb olur.Xüsusən də yeni sətirləri və digər boş yerləri lazımi qaydada saxlamayan “smarter” müştərilərlə belə problemlər yaranır. Xoşbəxtlikdən, Git sizin üçün daha asan ola bilən IMAP vasitəsilə düzgün formatlı patch-lar göndərməyinizə kömək edəcək bir vasitə təqdim edir. Gmail vasitəsilə necə bir yollama göndərəcəyimizi göstərəcəyik, bu da ən yaxşı tanıdığımız e-poçt agenti olur; Git mənbə kodunda yuxarıda göstərilən Documentation/SubmittingPatches faylının sonunda bir sıra poçt proqramları üçün ətraflı təlimatları oxuya bilərsiniz.

Əvvəlcə imap bölməsini ~/.gitconfig faylınızda qurmalısınız. Hər bir dəyəri ayrıca bir sıra git config əmrləri ilə təyin edə bilərsiniz və ya onları manual əlavə edə bilərsiniz, lakin sonda konfiqurasiya faylınızda bu kimi bir şey görünməlidir:

[imap]
  folder = "[Gmail]/Drafts"
  host = imaps://imap.gmail.com
  user = user@gmail.com
  pass = YX]8g76G_2^sFbd
  port = 993
  sslverify = false

Əgər IMAP serveriniz SSL istifadə etmirsə, son iki sətir, ehtimal ki, lazım deyil və host dəyəri imap:// yerinə imaps:// olacaqdır. Qurulduqda patch seriyasını göstərilən IMAP serverinin Drafts folder-nə yerləşdirmək üçün git imap-send istifadə edə bilərsiniz:

$ cat *.patch |git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done

Bu anda, Drafts folder-nə gedə, Kimə hissəsini patch-ı göndərdiyiniz poçt siyahısına dəyişdirə, bəlkə CC-ə bu bölməyə cavabdeh olan şəxsə göndərə biləsiniz.

Patch-ları bir SMTP serveri vasitəsilə də göndərə bilərsiniz. Əvvəllər olduğu kimi hər bir dəyəri ayrıca bir sıra git config əmrləri ilə müəyyənləşdirə bilərsiniz və ya onları manual olaraq ~/.gitconfig sənədinizdəki göndərmə poçt bölməsinə əlavə edə bilərsiniz:

[sendemail]
  smtpencryption = tls
  smtpserver = smtp.gmail.com
  smtpuser = user@gmail.com
  smtpserverport = 587

Bu iş bitdikdən sonra patch-larınızı göndərmək üçün git send-email istifadə edə bilərsiniz:

$ git send-email *.patch
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y

Sonra Git göndərdiyiniz hər bir patch üçün bu kimi bir şey axtaran bir dəst log məlumatı verir:

(mbox) Adding cc: Jessica Smith <jessica@example.com> from
  \line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] Add limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>

Result: OK

Nəticə

Bu bölmə, qarşınıza çıxa biləcəyiniz bir çox fərqli Git layihəsi ilə məşğul olmaq üçün bir sıra ümumi iş axınlarını əhatə etdi və bu prosesi idarə etməyə kömək edəcək bir neçə yeni vasitə təqdim etdi. Sonra, coin-nin digər tərəfini necə işləyəcəyinizi görəcəksiniz: Git layihəsini qorumaq. Xeyirxah bir diktator və ya inteqrasiya meneceri olmağı öyrənəcəksiniz.