-
1. Başlanğıc
- 1.1 Versiyaya Nəzarət Haqqında
- 1.2 Git’in Qısa Hekayəsi
- 1.3 Git Nədir?
- 1.4 Əmr Sətiri
- 1.5 Git’i Quraşdırmaq
- 1.6 İlk Dəfə Git Quraşdırması
- 1.7 Kömək Almaq
- 1.8 Qısa Məzmun
-
2. Git’in Əsasları
-
3. Git’də Branch
- 3.1 Nutshell’də Branch’lar
- 3.2 Sadə Branching və Birləşdirmə
- 3.3 Branch İdarəedilməsi
- 3.4 Branching İş Axınları
- 3.5 Uzaq Branch’lar
- 3.6 Rebasing
- 3.7 Qısa Məzmun
-
4. Server’də Git
- 4.1 Protokollar
- 4.2 Serverdə Git Əldə Etmək
- 4.3 Sizin öz SSH Public Key’nizi yaratmaq
- 4.4 Server qurmaq
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Üçüncü Tərəf Seçimləri
- 4.10 Qısa Məzmun
-
5. Paylanmış Git
-
6. GitHub
-
7. Git Alətləri
- 7.1 Reviziya Seçimi
- 7.2 Interaktiv Səhnələşdirmə
- 7.3 Stashing və Təmizləmə
- 7.4 İşinizin İmzalanması
- 7.5 Axtarış
- 7.6 Tarixi Yenidən Yazmaq
- 7.7 Reset Demystified
- 7.8 İnkişaf etmiş Birləşmə
- 7.9 Rerere
- 7.10 Git ilə Debugging
- 7.11 Alt Modullar
- 7.12 Bundling
- 7.13 Dəyişdirmək
- 7.14 Etibarlı Yaddaş
- 7.15 Qısa Məzmun
-
8. Git’i Fərdiləşdirmək
- 8.1 Git Konfiqurasiyası
- 8.2 Git Atributları
- 8.3 Git Hook’ları
- 8.4 Git-Enforced Siyasət Nümunəsi
- 8.5 Qısa Məzmun
-
9. Git və Digər Sistemlər
- 9.1 Git Müştəri kimi
- 9.2 Git’ə Miqrasiya
- 9.3 Qısa Məzmun
-
10. Git’in Daxili İşləri
- 10.1 Plumbing və Porcelain
- 10.2 Git Obyektləri
- 10.3 Git Referansları
- 10.4 Packfile’lar
- 10.5 Refspec
- 10.6 Transfer Protokolları
- 10.7 Maintenance və Məlumatların Bərpası
- 10.8 Mühit Dəyişənləri
- 10.9 Qısa Məzmun
-
A1. Appendix A: Digər Mühitlərdə Git
- A1.1 Qrafik interfeyslər
- A1.2 Visual Studio’da Git
- A1.3 Visual Studio Code’da Git
- A1.4 Eclipse’də Git
- A1.5 Sublime Text’də Git
- A1.6 Bash’da Git
- A1.7 Zsh’də Git
- A1.8 PowerShell’də Git
- A1.9 Qısa Məzmun
-
A2. Appendix B: Proqramlara Git Daxil Etmək
- A2.1 Əmr-sətri Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Appendix C: Git Əmrləri
- A3.1 Quraşdırma və Konfiqurasiya
- A3.2 Layihələrin Alınması və Yaradılması
- A3.3 Sadə Snapshotting
- A3.4 Branching və Birləşmə
- A3.5 Layihələrin Paylaşılması və Yenilənməsi
- A3.6 Yoxlama və Müqayisə
- A3.7 Debugging
- A3.8 Patching
- A3.9 E-poçt
- A3.10 Xarici Sistemlər
- A3.11 İdarəetmə
- A3.12 Plumbing Əmrləri
7.7 Git Alətləri - Reset Demystified
Reset Demystified
Daha ixtisaslaşmış alətlərə keçməzdən əvvəl Git reset
və checkout
əmrləri barədə danışaq.
Bu əmrlər, Git-lə ilk qarşılaşdığınız zaman ən çaşdırıcı hissələrindən biridir.
Onlar o qədər şeylər edirlər ki, onları həqiqətən başa düşmək və düzgün işlətmək ümidsiz görünür.
Bunun üçün sadə bir metafora tövsiyə edirik.
The Three Trees
reset
və checkout
barədə düşünməyin daha asan yolu üç fərqli ağac məzmun meneceri olmaq üçün Git’in zehni çərçivəsindədir.
Buradakı “tree” ilə, həqiqətən, məlumatların quruluşunu deyil, “files toplusunu” nəzərdə tuturuq.
Bir neçə hal var ki, indeks tam olaraq bir ağac kimi davranmır, amma məqsədlərimiz üçün bu gün bu şəkildə düşünmək daha asandır.
Sistem olaraq Git normal işləmə rejimində üç ağac idarə edir və manipulyasiya edir:
Tree | Rol |
---|---|
HEAD |
Son commit-i çəkmək, növbəti valideyn |
Index |
Təklif olunan növbəti commit snapshot-u |
Working Directory |
Sandbox |
The HEAD
HEAD, öz növbəsində həmin branch-da edilən son commit-ə göstərici olan cari branch arayışına işarədir. Demək ki, HEAD yaradılan növbəti commit-in valideyni olacaq. HEAD bu branch-dakı son commit-nizin snapshot-u kimi düşünmək ümumiyyətlə ən sadədir. Əslində bunun necə göründüyünə baxmaq çox asandır. Budur HEAD anlıq görüntüsündə hər bir fayl üçün faktiki qovluq siyahısının və SHA-1 yoxlama cədvəlinin alınmasına dair bir nümunə:
$ git cat-file -p HEAD
tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
author Scott Chacon 1301511835 -0700
committer Scott Chacon 1301511835 -0700
initial commit
$ git ls-tree -r HEAD
100644 blob a906cb2a4a904a152... README
100644 blob 8f94139338f9404f2... Rakefile
040000 tree 99f1a6d12cb4b6f19... lib
Git cat-file
və ls-tree
əmrləri aşağı səviyyə işlər üçün istifadə olunan və həqiqətən gündəlik işlərdə istifadə edilməyən “plumbing” əmrləridir, lakin bunlar burada nələrin baş verdiyini görməyə kömək edir.
Index
Index təklif olunan növbəti commit-dir. Biz də bu anlayışa Git’in “Staging Area” olaraq müraciət etdik, çünki Git git commit
işlətdiyiniz zaman bu hissə Git-in baxdığı yerdir.
Git, bu indeks iş sənədlərinizdə son yoxlanılan və əvvəlcə yoxlanıldıqda göründüyü bütün fayl məzmunlarının siyahısı ilə doldurulur.
Daha sonra həmin faylların bəzilərini yeni versiyaları ilə əvəz edirsiniz və git commit
onları yeni bir commit üçün ağaca çevirir.
$ git ls-files -s
100644 a906cb2a4a904a152e80877d4088654daad0c859 0 README
100644 8f94139338f9404f26296befa88755fc2598c289 0 Rakefile
100644 47c6340d6459e05787f644c2447d2595f5d3a54b 0 lib/simplegit.rb
Yenə də, burada indeksinizin göründüyünü göstərən pərdə arxasında daha çox olan git ls-files
istifadə olunur.
İndeks texniki cəhətdən bir ağac quruluşunda deyil - əslində sadə bir təzahür şəklində tətbiq olunur - lakin məqsədlərimiz üçün kifayət qədər yaxındır.
İş Qovluğu
Nəhayət, bir iş qovluğunuz var (ümumiyyətlə “working tree” adlandırılır).
Digər iki ağac, məzmunlarını səmərəli, lakin əlverişsiz bir şəkildə, .git
qovluğu içərisində saxlayır.
İşçi qovluq onları faktiki fayllara ayırır, bu da onları redaktə etməyi asanlaşdırır.
İşçi qovluğu bir sandbox olaraq düşünün, burada dəyişiklikləri sahəyə (indeks) və sonra tarixə verməzdən əvvəl sınaqdan keçirə bilərsiniz.
$ tree
.
├── README
├── Rakefile
└── lib
└── simplegit.rb
1 directory, 3 files
Workflow
Git-in tipik workflow-u bu üç ağacı manipulyasiya etməklə layihənizin görüntülərini ardıcıl olaraq daha yaxşı vəziyyətlərdə qeyd etməkdir.
Bu prosesi görüntüləyək: sizin bir sənədlə yeni bir qovluğa girdiyinizi fərz edək.
Bunu faylın v1-i adlandıracağıq və göy rəngdə göstərəcəyik.
İndi biz doğmamış master
brancha-a işarə edən bir HEAD arayışı ilə Git depo yaradacaq və git init
-i işlədəcəyik.
Bu anda yalnız iş qovluğu ağacı hər hansı bir məzmuna malikdir.
İndi bu faylı yerinə yetirmək istəyirik, buna görə işçi qovluğunda məzmun götürmək və indeksə kopyalamaq üçün git add
istifadə edirik.
Sonra indeksin məzmununu götürən və onu daimi şəkli kimi saxlayan, həmin görüntüyə işarə edən bir commit obyekti yaradan və həmin commit-ə işarə etmək üçün master
yeniləyən git commit
-i işə salırıq.
git status
-u işə salsaq, heç bir dəyişiklik görməyəcəyik, çünki hər üç ağac eyni qalacaq.
İndi həmin fayla bir dəyişiklik etmək və onu yerinə yetirmək istəyirik. Eyni prosesdən keçəcəyik; əvvəlcə iş sənədlərindəki faylı dəyişdiririk. Ona faylın v2-si deyək və qırmızı ilə göstərək.
Hal-hazırda git status
-u işlədiriksə, faylı qırmızı rəngdə “Changes not staged for commit” şəklində görəcəyik, çünki bu giriş indeks və işçi qovluq arasında fərqlidir.
Sonra biz onu indeksimizə daxil etmək üçün git add
-ı işə salırıq.
Bu nöqtədə, əgər biz git status
-u işlədiriksə, faylı “Changes to be committed” altında yaşıl rəngdə görəcəyik, çünki indeks və HEAD fərqlənir - yəni təklif olunan növbəti commit-imiz artıq son commit-mizdən fərqlənir.
Nəhayət, commit-i yekunlaşdırmaq üçün git commit
-i işlədirik.
İndi git status
bizə heç bir output verməyəcək, çünki hər üç ağac yenə eynidir.
Branch-ları dəyişdirmə və ya klonlama oxşar bir prosesdən keçir. Bir branch-ı çıxartdıqda, yeni branch-ı ref-ə işarələmək üçün HEAD-ı dəyişdirir, commit-in görüntüsü ilə indeksinizi doldurur, sonra indeksin məzmununu iş qovluğunuza kopyalayır.
Reset-in Rolu
reset
əmri bu kontekstdə baxıldıqda daha mənalı olur.
Bu nümunələrin məqsədləri üçün deyək ki, file.txt
-ı yenidən dəyişdirdik və üçüncü dəfə tətbiq etdik.
İndi tariximiz belə görünür:
İndi başlatdığınız zaman reset
-in nə etdiyini araşdıraq.
Bu üç ağacı birbaşa sadə və proqnozlaşdırılan şəkildə manipulyasiya edir.
Üç əsas əməliyyatı yerinə yetirir.
Addım 1: Move HEAD
Yenidən qurmağın ilk işi, HEAD-in göstərdiyi şeyi hərəkət etdirməkdir.
Bu, HEAD-ın özünü dəyişdirməklə eyni deyil (bu da yoxlama
qaydasındadır); reset, rəhbərin işarə etdiyi branch-ı hərəkət etdirir.
Bu, HEAD master
branch-na (yəni hazırda master
branch-a) təyin olunarsa, 9e5e6a4
git reset 9e5e6a4
səviyyəsinə master
nöqtəsi ilə başlayacaq deməkdir.
Commit ilə hər hansı bir reset
formasından asılı olmayaraq, bu daima etməyə çalışacağı ilk şeydir. reset --soft
ilə isə, sadəcə orada dayanacaq.
İndi bu diaqrama nəzər salmaq və nəyin baş verdiyini anlamaq üçün bir addım ataq: bu, son git commit
-i ləğv etdi.
git commit
-i işə saldığınız zaman, Git yeni bir commit yaradır və rəhbərlik etdiyi branch-ı ona doğru istiqamətləndirir. HEAD~
-a reset
etdikdə (HEAD-ın valideyni), sənədi və ya iş qovluğunu dəyişdirmədən branch-ı olduğu yerə aparırsan.
İndi indeksini yeniləyə bilər və git commit --amend
-in nə edəcəyini yerinə yetirmək üçün yenidən git commit
işlədə bilərsiniz (Son Commit Dəyişdirilməsi-a bax)
Addım 2: İndeksin yenilənməsi (-- mixed)
Qeyd edək ki, indi git status
-u işləsəniz, indekslə yeni HEAD-in fərqini yaşıl rəngdə görəcəksiniz.
Reset
-in sonrakı işi, indiyə kimi HEAD-ın qeyd etdiyi hər şeyi məzmunu ilə yeniləməkdir.
--mixed
seçimi göstərsəniz, reset
bu nöqtədə dayanacaq.
Bu da standartdır, buna görə heç bir seçim etməmisinizsə (bu vəziyyətdə git reset HEAD~
edin), əmr dayanacaq.
İndi bu diaqrama baxmaq və nəyin baş verdiyini anlamaq üçün başqa bir saniyə ayırın: bu hələ də son commit
-nizi ləğv etdi, lakin, eyni zamanda hər şeyi dayandırdı.
Bütün git add
və git commit
əmrlərinizi yerinə yetirmədən əvvəl geri döndünüz.
Adım 3: İş Qovluğu Yeniləmə (--hard)
reset
-in edəcəyi üçüncü şey, işləyən qovluğu indeksə bənzətməkdir.
--hard
seçimindən istifadə edirsinizsə, o, bu mərhələyə davam edəcəkdir.
Beləliklə, nə baş verdiyini düşünək.
Sonuncu əmrinizi, git add
və git commit
əmrlərini və iş qovluğunuzda etdiyiniz bütün işləri ləğv etdiniz.
Qeyd etmək vacibdir ki, bu bayraq (--hard
) reset
əmrini təhlükəli hala gətirməyin yeganə yoludur və Git-in məlumatları məhv edəcəyi çox az hallardan biridir.
reset
-in hər hansı bir başqa çağırışı asanlıqla geri qaytarıla bilər, lakin --hard
seçimi, işləyən qovluqdakı faylları çətinliklə yazacaq.
Bu vəziyyətdə, hələ də Git DB-də commit-də v3 versiyamız var və onu reflog-muza baxaraq geri ala bilərdik, amma əgər commit etməsəydik, Git yenə də faylın üstünə yazacaqdı və o bərpaedilməz olardı.
Recap
reset
əmri bu üç ağacı müəyyən bir qaydada ləğv edir, bunu söylədikdə dayandırır:
-
Branch HEAD nöqtələrini hərəkətə gətirin (
--soft
olduqda dayanın). -
İndeksi HEAD kimi göstərin (
--hard
olduqda dayandırın). -
İş qovluğunu indeks kimi göstərin.
Path ilə Reset
Bu, əsas formada reset
-in davranışını əhatə edir, eyni zamanda hərəkət etmək üçün path ilə təmin edə bilərsiniz.
Path-i təyin etsəniz, reset
1-ci addımı atlayacaq və hərəkətlərinin qalan hissəsini müəyyən bir fayl və ya fayllar dəsti ilə məhdudlaşdıracaqdır.
Bu, həqiqətən bir növ məna kəsb edir — HEAD sadəcə bir göstəricidir və bir commit-in bir hissəsini və digərinin hissəsini göstərə bilməzsiniz.
Lakin indeks və işləyən qovluq qismən yenilənə bilər, buna görə reset 2 və 3 addımlarla davam edir.
Beləliklə, git reset file.txt
-u işlətdiyimizi fərz edək.
Bu forma (bir SHA-1 və ya branch-ı göstərmədiyinizə və --soft
və ya --hard
göstərmədiyinizə görə) git reset --mixed HEAD file.txt
üçün stenoqramdır:
-
Branch-ı HEAD nöqtələrinə köçürün (atıldı).
-
İndeksi HEAD kimi göstərin (burada dayanın).
Beləliklə, bu, yalnız file.txt
-ı HEAD-dan indeksə köçürür.
Bu, faylı unstaging etməyə təsir göstərir.
Bu əmrin diaqramına baxsaq və git add
-ın nə etdiyini düşünsək, onlar tam əkslərdir.
Buna görə git status
əmrinin nəticəsi bir faylın açılmaması üçün işə başlamağınızı təklif edir (bu barədə daha çox məlumat üçün Mərhələli Bir Faylın Mərhələlərə Ayrılmaması-a baxın).
Git-in bu versiyasını çıxarmaq üçün müəyyən bir commit-i göstərərək “pull the data from HEAD” dediyini asanlıqla edə bilərik.
Sadəcə git reset eb43bf file.txt
kimi bir şey işlədərdik.
Bu, işin içindəki faylın məzmunu v1-ə qaytardığımız, üzərinə git add
işlədib yenidən v3-ə qaytardığımız kimi eyni şeyi edir (həqiqətən bütün bu addımlardan keçmədən).
İndi git commit-i işə salırıqsa, bu işi yenidən v1-ə qaytaran bir dəyişiklik qeyd edəcək, baxmayaraq ki, bu, heç işlədiyimiz qovluqda heç olmamışdır.
git add
kimi, reset
əmri, bir hunk-by-hunk əsasında məzmunu açmaq üçün --patch
seçimini qəbul edəcəyi də maraqlıdır.
Beləliklə, məzmunu seçmə şəkildə dayandıra və ya geri qaytara bilərsiniz.
Squashing
Gəlin bu yeni güc ilə necə maraqlı bir iş görəcəyimizə nəzər salaq.
“oops.”, “WIP” və “forgot this file” kimi bir sıra commit-niz olduğunu düşünək.
Həqiqətən ağıllı görünməyinizi təmin edən reset
-i tez və asanlıqla bir vahid commit halına gətirə bilərsiniz.
Squashing Commits bunun başqa bir yolunu göstərir, lakin bu nümunədə reset
tətbiq etmək daha asandır.
Deyək ki, birinci commit-in bir sənəd olduğu bir layihə var, ikincisi yeni bir fayl əlavə etdi və birincisini dəyişdirdi, üçüncü commit isə ilk sənədini yenidən dəyişdirdi. İkinci commit davam edən bir iş idi və siz onu squash istəyirsiniz.
HEAD branch-nı köhnə bir commit-ə (davam etdirmək istədiyiniz ən yeni commit-ə) köçürmək üçün git reset --soft HEAD~2
tətbiq edə bilərsiniz.
Və sonra sadəcə yenidən git commit
-i işə salın:
İndi əlçatan tarixçənizi, push edəcəyiniz tarixin indi bir fayl-a.txt
v1 ilə iş görməyinizə, sonra da hər ikisinin file-a.txt
faylını v3-ə dəyişdirib fayl-b.txt
əlavə etməyinə bənzəyirsiniz.
Faylın v2 versiyası ilə commit artıq tarixdə yoxdur.
Yoxlama
Nəhayət, checkout
və reset
arasındakı fərqin nə olduğunu düşünə bilərsiniz.
reset
kimi, checkout
da üç ağacı idarə edir və əmrə bir fayl path verib verməməyinizə görə bir az fərqlidir.
Path-lar Olmadan
git checkout [branch]
işlətməsi git reset --hard [branch]
işlətməsinə bənzəyir, çünki [branch]
kimi görünməyiniz üçün üç ağacı da yeniləyir, ancaq burada iki mühim fərq var.
Birincisi, reset --hard
-dan fərqli olaraq, checkout
iş üçün təhlükəsizdir; bu dəyişikliklər olan faylları üzə vurmadığından əmin olacaq.
Əslində, o bundan bir az daha ağıllıdır - iş qovluğunda əhəmiyyətsiz bir birləşmə etməyə çalışır, belə ki dəyişdirmədiyiniz bütün fayllar yenilənəcəkdir.
reset --hard
, əksinə, lövhədə hər şeyi yoxlamadan əvəz edəcəkdir.
İkinci önəmli fərq, checkout
-un HEAD-i necə yeniləməsidir.
HEAD-ın göstərdiyi branch-ı yenidən hərəkət etdirərkən, checkout
başqa bir branch-a işarə etmək üçün HEAD-ı özünə aparacaqdır.
Məsələn, deyək ki, fərqli commit-lərə işarə edən master
və develop
branch-larımız var və hazırda develop
-dayıq (ona görə də HEAD buna işarə edir).
git reset master
işləsək, develop
özü indi master
-in etdiyi eyni commit-ə işarə edəcəkdir.
Bunun əvəzinə git checkout master
işlətsək, develop
hərəkət etmir, HEAD özü edir.
HEAD indi master
-ə işarə edəcəkdir.
Beləliklə, hər iki vəziyyətdə də HEAD-i A commit-ni göstərməyə yönəldirik, amma bunu necə etdiyimiz çox fərqlidir.
reset
, HEAD nöqtələrini hərəkətə gətirəcək, checkout
HEAD-in özünü hərəkət etdirəcəkdir.
Path-larla Birlikdə
checkout
-u işlətmənin başqa yolu, reset
kimi HEAD hərəkət etməyən bir file path-dır.
Eynilə git reset [branch] file
faylına bənzəyir, indeksi həmin sənədlə həmin faylda yeniləyir, eyni zamanda iş qovluğundakı faylın üzərinə yazır.
Tam olaraq git reset --hard [branch] file
kimi olardı (reset
onu işlətməyinizə imkan verərsə) - iş qovluğu təhlükəsiz deyil və HEAD hərəkət etmir.
Ayrıca, git reset
və git add
kimi, checkout
seçilmiş şəkildə bir hunk-by-hunk əsasında fayl məzmununu geri qaytarmağınız üçün bir --patch
seçimi qəbul edəcəkdir.
Məzmun
Ümid edirik ki, indi reset
əmri başa düşürsünüz və daha rahat hiss edirsiniz, amma bunun yəqin ki, checkout
-dan nə dərəcədə fərqləndiyinə dair bir az qarışıq və bəlkə də fərqli çağırışların bütün qaydalarını xatırlaya bilmirsiniz.
Burada əmrlərin hansı ağaclara təsir etdiyini göstərən bir cheat-sheet var. “HEAD” sütununda, əmr, rəhbərin göstərdiyi istinadı (branch-ı) hərəkət etdirərsə, “HEAD” ifadəsini işlədiyi təqdirdə, “REF” və oxunuşunu özü idarə edərsə “HEAD” oxuyur. WD Safe? mövzusuna xüsusi diqqət yetirin. sütun - əgər YOX deyirsə, bu əmri işə salmadan əvvəl düşünün.
HEAD | Index | Workdir | WD Safe? | |
---|---|---|---|---|
Commit Level |
||||
|
REF |
NO |
NO |
YES |
|
REF |
YES |
NO |
YES |
|
REF |
YES |
YES |
NO |
|
HEAD |
YES |
YES |
YES |
File Level |
||||
|
NO |
YES |
NO |
YES |
|
NO |
YES |
YES |
NO |