├── README.md └── assets ├── 1.png └── 2.png /README.md: -------------------------------------------------------------------------------- 1 | # İçindekiler 2 | - [İçindekiler](#i̇çindekiler) 3 | - [Giriş](#giriş) 4 | - [Git Nedir?](#git-nedir) 5 | - [Temel Git Terimleri](#temel-git-terimleri) 6 | - [Kurulum](#kurulum) 7 | - [Temel Terminal/Komut İstemcisi Bilgisi](#temel-terminalkomut-i̇stemcisi-bilgisi) 8 | - [Git CLI (Command Line Interface / Komut İstemcisi) Test Edelim](#git-cli-command-line-interface--komut-i̇stemcisi-test-edelim) 9 | - [Git'e Giriş](#gite-giriş) 10 | - [Ufak Bir Not](#ufak-bir-not) 11 | - [Branch](#branch) 12 | - [Branch Nedir?](#branch-nedir) 13 | - [Peki Neden Branch'lere İhtiyaç Duyarız?](#peki-neden-branchlere-i̇htiyaç-duyarız) 14 | - [Ufak Bir Not](#ufak-bir-not-1) 15 | - [Ufak Bir Not](#ufak-bir-not-2) 16 | - [Branch'leri Silmek](#branchleri-silmek) 17 | - [Conflicts (Çakışmalar)](#conflicts-çakışmalar) 18 | - [Rebasing](#rebasing) 19 | - [Reset (Dosyaları Eski Hallerine Döndürme)](#reset-dosyaları-eski-hallerine-döndürme) 20 | - [STASH](#stash) 21 | - [Ufak Bir Not](#ufak-bir-not-3) 22 | - [Gitignore (Dosyaları Yok Saymak)](#gitignore-dosyaları-yok-saymak) 23 | - [Değiştirilemeyen Dosyalar](#değiştirilemeyen-dosyalar) 24 | - [Ufak Bir Not](#ufak-bir-not-4) 25 | - [Dosyaları Silmek](#dosyaları-silmek) 26 | - [Commit'leri Kopyalamak (git-cherry)](#commitleri-kopyalamak-git-cherry) 27 | - [Alias (Takma Adlar)](#alias-takma-adlar) 28 | - [Uzak Sunucu](#uzak-sunucu) 29 | - [Push - Pull Nedir?](#push---pull-nedir) 30 | - [Ufak Bir Not](#ufak-bir-not-5) 31 | - [GitHub ile devam edelim](#github-ile-devam-edelim) 32 | - [Clone Nedir](#clone-nedir) 33 | - [Temel Git ve GitHub Bilgileri İçin Video](#temel-git-ve-github-bilgileri-i̇çin-video) 34 | # Giriş 35 | Git kullanımımı daha efektif hale getirebilmek için **okumalar yaptım ve aldığım notları derleyerek** bu dökümanı 18/05/2020 tarihinde hazırladım. 36 | # Git Nedir? 37 | Kısaca **Git** bir versiyon kontrol sistemidir diyebiliriz. Bu **açık kaynaklı** versiyon kontrol sistemi sayesinde; projelerimizin versiyon kontrol takibini yapabilir, dünya çapında projelere katkıda bulunabilir, kendi projelerimizi dünya ile paylaşabilir ve projelerimizin mobilitesini artırabiliriz. Bu sistem sayesinde, bir projede aynı anda birden fazla kişi ile çalışabilir ve bir dosyada yapılan tüm değişiklikleri görüntüleyebiliriz. 38 | **Unutmamakta fayda var, Git != GitHub || GitLab** 39 | 40 | # Temel Git Terimleri 41 | - **Repository** 42 | - Bir diğer adıyla **Kod Deposu**. Tüm kodlarımızın tarihçelerinin barındırıldığı depodur. Proje dizinimizde ``` git init``` diyerek bir repository oluşturabiliriz. 43 | - **Working Directory** 44 | - Kısaca **Çalışma Alanı**. Projemizin ana dizinidir. Bir dosyanın/klasörün **Working Directory**'de bulunması o dosyanın **Git** tarafından takip edildiği anlamına gelmez. Sadece **Staging Area**'daki dosyalar **Git** tarafından takip edilir. 45 | - **Staging Area** 46 | - **Git** tarafından **takip edilen** dosyalar burada bulunur. Gerçek manada **fiziki bir alan değildir**. Dosyalarımızın durumunu belirten hayali bir ortam olarak düşünebiliriz. 47 | - **Commit** 48 | - Kısaca **Taahhüt** veya **Sözleşme** diyebiliriz. Bir dosyada yaptığımız değişikliklerin kalıcı değişiklikler olduğunun taahhüdünü vermemiz, sözleşmeyi imzalamamız gerekmektedir. Böyle ilgili dosya/dizinde yaptığımız değişiklikler **repository**'mize kaydedilir. 49 | 50 | # Kurulum 51 | [Git](https://git-scm.com/)'in official web sitesi üzerinden kurulum dosyasını indirebiliriz. Eğer ki Linux kullanıcısı isek (Debian tabanlı dağıtımlar için) `apt-get install git` diyerek sistemimize Git'i kurabiliriz. 52 | - Git versiyon kontrol sisteminin yine Git ile kontrol edildiğini de belirtmekte fayda var :blush: 53 | 54 | 55 | # Temel Terminal/Komut İstemcisi Bilgisi 56 | - **Terminal Nasıl Açılır?** 57 | - **Linux** Dağıtımlar: 58 | - **CTRL + ALT + T** tuş kombinasyonu ile Terminal açılabilir (Gnome masaüstünü kullananlar için). Uygulamalar penceresinden de Terminal'i seçerek açabilirsiniz 59 | - **OS X**: 60 | - **cmd + space(boşluk)** tuş kombinasyonu ile Spotlight'ı açtıktan sonra **Terminal** yazıp Enter'a basarak açabilirsiniz. 61 | - **Windows**: 62 | - **ALT + R** tuş kombinasyonu sayesinde açılan pencerede **cmd** yazarak erişebilirsiniz. 63 | - **Terminal** Nedir? 64 | - Kısaca Terminal; kullanıcıların **sadece** klavye ve ekran yardımıyla işletim sistemi veya yazılımları kontrol etmesini veya yönetmesine yardım eden **komut ekranı**dır. 65 | - `mkdir` 66 | - Komut ekranımızda `mkdir dizin_adi` komutunu çalıştırır ve argüman olarak **dizin_adi** 'nı yollarsak bulunduğumuz dizinde '**dizin_adi**' adında bir klasör oluşturacaktır. 67 | - `ls` 68 | - Komut ekranımızda `ls` komutunu çalıştırırsak bize bulunduğumuz dizindeki mevcut dizinleri, dosyaları listeleyecektir. 69 | ``` 70 | ls 71 | >>> Desktop Documents Downloads go Music node Pictures Postman Public pycharm Templates Videos 'VirtualBox VMs' 72 | ``` 73 | - `pwd` 74 | - Komut ekranımızda `pwd` komutunu çalıştırırsak bize hangi dizinde bulunduğumuzu verecektir. 75 | ``` 76 | pwd 77 | >>> /root/Desktop/GIT-EL-KITAP 78 | ``` 79 | ### Git CLI (Command Line Interface / Komut İstemcisi) Test Edelim 80 | Git'i sistemimize kurduktan sonra, komut istemcimizde `git --version` komutunu çalıştırdığımızda bize sistemimizde yüklü olan Git'in versiyonunu döndürecektir.(Versiyonlarda farklılık olabilir. Herhangi bir versiyonu döndürüyorsa tebrik ederim, Git'i başarılı bir şekilde kurdunuz demektir :sunglasses:) 81 | ``` 82 | git --version 83 | >>> git version 2.26.2 84 | ``` 85 | 86 | # Git'e Giriş 87 | - Bir projemiz olduğunu varsayalım. `cd` komutu sayesinde Git reposu (repository) oluşturmak istediğimiz dizine gidiyoruz. 88 | ``` 89 | cd Desktop/projedizinim/ 90 | ``` 91 | - Ardından `ls` komutu sayesinde dizinimizdeki dosyaları/klasörleri listeleyebiliriz. 92 | ``` 93 | ls 94 | >>> intro.py 95 | ``` 96 | - `git init` komutu sayesinde mevcut dizinimizde bir Git Repository'si oluşturabiliriz ve sonrasında boş bir Git Reposu oluşturuldu şeklinde çıktı alacağız. 97 | ``` 98 | git init 99 | >>> Initialized empty Git repository in /root/Desktop/projedizinim/.git/ 100 | ``` 101 | - Artık **projedizinim** altındaki dosyalar Git ile takip edilebilirler. Fakat **henüz takip edilmiyorlar**:exclamation: Bunun sebebini aslında yukarıda belirtmiştik. **projedizinim** bizim Working Directory'miz yani çalışma alanımız. Fakat biz ne demiştik? Bir dosyanın veya klasörün Working Directory'de olması Git tarafından takip edildiği anlamına gelmez. Bu sebeple dosyalarımızı Staging Area'ya yani Git'in takip ettiği sanal ortama **sözleşme/taahhüt** imzalayarak tanıtmamız gerekli. Bu kısa bilgiyi verdikten sonra bizim elimiz kolumuz olacak olan `git status` komutuna bakalım :muscle: 102 | - Git reposunu oluşturduğumuz dizin altında `git status` komutunu çalıştıralım. Git status bizim elimiz kolumuz olacak. Bize repomuzun durumunu anlatırken aynı zamanda yapmak isteyeceğimiz işlemlerin komutlarını da hatırlatır :innocent: 103 | ``` 104 | git status 105 | >>> On branch master 106 | 107 | No commits yet 108 | 109 | Untracked files: 110 | (use "git add ..." to include in what will be committed) 111 | intro.py 112 | 113 | nothing added to commit but untracked files present (use "git add" to track) 114 | ``` 115 | - Git `intro.py` adlı dosyamızı gördü fakat henüz takip etmiyor. Bu sebeple **Untracked files** yani **Takip edilmeyen dosyalar** altında listeledi. Şimdi Git'e bu dosyayı takip et, yani **Staging Area**'ya al dememiz gerekiyor. 116 | - `git add dosya_adi` komutunu kullandığımızda ilgili dosyayı Staging Area'ya ekler ve takip etmeye başlar. 117 | ``` 118 | git add intro.py # benim repoma eklemek istediğim dosyanın adı intro.py siz de kendi dosyanızı argüman olarak yollamalısınız ^^ 119 | ``` 120 | - Şimdi tekrar Git repomuzun durumuna bakalım 121 | ``` 122 | git status 123 | >>> On branch master 124 | 125 | No commits yet 126 | 127 | Changes to be committed: 128 | (use "git rm --cached ..." to unstage) 129 | new file: intro.py 130 | ``` 131 | - Git artık dosyalarımızı takip ediyor fakat bu sefer de bize diyorki 'Bu dosyada değişiklikler var ama henüz **commit** edilmemiş'. Yani yaptığımız değişiklikler için sözleşme imzalamamızı istiyor. Bunu da `git commit -m "ilk commit"` komutu sayesinde yapabiliriz. `git commit -m` komutuna argüman olarak yolladığımız string bizim sözleşmemizin açıklama metni olacaktır. Log kayıtlarında bu şekilde görüntülenecek. Bizim ilk denememiz olduğu için "ilk commit" şeklinde bir açıklama yaptık. Tabii ki gerçek bir proje üzerinde çalışsaydık takım arkadaşlarımızın bilgilenmesi için yaptığımız değişikliği açıklayan nitelikte bir açıklama yazmamız daha hoş olurdu. 132 | ``` 133 | git commit -m "ilk commit" 134 | >>> [master (root-commit) 62cf9b5] ilk commit 135 | 1 file changed, 1 insertion(+) 136 | create mode 100644 intro.py 137 | ``` 138 | - Eğer Git'i ilk defa kurduysak bu aşamada git bizden kendimizi tanıtmamızı isteyecektir. Bunun sebebi ise oluşturduğumuz **commitler**i (sözleşmeleri) bizim adımıza oluşturacak ve Repository üzerinde kimin değişiklik/güncelleme yaptığının bilgisini tutacaktır. Sistemimizde **tek seferlik** bu konfigürasyonu yapmamız gerekmekte. Gerçek bilgiler olması önemlidir :exclamation: 139 | ``` 140 | git config --global user.name "ad soyad" 141 | git config --global user.email "mail adresi" 142 | ``` 143 | - Konfigürasyonları yaptıktan sonra tekrar commit etmeyi deniyoruz (eğer kendimizi tanıtmamız istenmişse). Ve hayırlı olsun ilk commitiniz başarıyla sonuçlandı :innocent: 144 | ``` 145 | git commit -m "ilk commit" 146 | >>> [master (root-commit) 62cf9b5] ilk commit 147 | 1 file changed, 1 insertion(+) 148 | create mode 100644 intro.py 149 | ``` 150 | #### Ufak Bir Not 151 | - Commit'ler ile ilgili; her bir commit'in tek bir göreve hizmet etmesi daha hoş olacaktır. `intro.py` dosyasıyla ilgili bir commit yaptığımızda bu commit `intro2.py` dosyasıyla ilgili commiti içermemesi gerekir. İçerse hata alır mıyız? Tabii ki hayır, fakat yönetilebilirlik ve kontrol açısından her commit'in kendi amacına hizmet etmesi daha hoş olacaktır. 152 | - Demiştik ki `git status` bizim elimiz kolumuz olacak. Şimdi `intro.py` dosyamızda rastgele değişiklik yapalım ve ardından `git status` komutunu çalıştıralım. 153 | ``` 154 | git status 155 | >>> On branch master 156 | Changes not staged for commit: 157 | (use "git add ..." to update what will be committed) 158 | (use "git restore ..." to discard changes in working directory) 159 | modified: intro.py 160 | 161 | no changes added to commit (use "git add" and/or "git commit -a") 162 | ``` 163 | - Gördüğümüz gibi Git bize hangi dosyalarda değişiklik olmuş, repomuzda neler olmuş bitmiş bunların raporunu vermekte. Buradan anladığımız kadarıyla da `intro.py` değiştirilmiş/güncellenmiş fakat **henüz commit edilmemiş**. `git status` komutu zaten bize ne yapmamız gerektiğini söylüyor. Biz `git add` komutunu zaten görmüştük. Dilerseniz bir de `git restore dosya_adi` komutunu görelim. Bu komut argüman olarak verdiğimiz dosyadaki değişiklikleri **bir önceki commit**teki haline çevirecektir. 164 | ``` 165 | git restore intro.py 166 | git status 167 | >>> On branch master 168 | nothing to commit, working tree clean 169 | ``` 170 | - `intro.py` dosyamızdaki değişiklikleri bir önceki committeki haline çevirdik ve tekrar `git status` ile repomuzun durumunu sorguladık. Bize herhangi bir değişiklik olmadığını söyledi. Çünkü `git restore intro.py` ile dosyamızı bir önceki committeki haline çevirmiştik. 171 | - Şimdi tekrar dosyamızda değişiklik yapalım ve farzedelim ki kodlarımızda her şey yolunda ve bunu prod'a yollayabiliriz. Değişikliklerden sonra tekrar **staging area**'ya ekleyelim ve **commit (sözleşme/taahhüt)** edelim. 172 | ``` 173 | git status 174 | >>> On branch master 175 | On branch master 176 | Changes not staged for commit: 177 | (use "git add ..." to update what will be committed) 178 | (use "git restore ..." to discard changes in working directory) 179 | modified: intro.py 180 | 181 | no changes added to commit (use "git add" and/or "git commit -a") 182 | 183 | git add intro.py 184 | 185 | git commit -m "hello world fonksiyonu eklendi" 186 | 187 | >>> [master 000d29e] hello world fonksiyonu eklendi 188 | 1 file changed, 1 insertion(+), 1 deletion(-) 189 | 190 | ``` 191 | - Siz de takdir edersiniz ki dosyalarımızın sadece çalışır ve olmasını istediğimiz hallerini commit ettik. **Her zaman dosyalarımızın en son, çalışır hallerini commit etmeliyiz.** Aksi takdirde prod kısmında kodlarımızı güncellediğimizde kötü sonuçlar ile karşılaşmamız kaçınılmazdır :anguished: 192 | - Şimdi bir de repository'miz üzerinde daha önce neler olmuş bitmiş, hangi tarihte ne değişiklikler yapmışız dilerseniz bunları görelim. Bunun için `git log` komutunu kullanmamız yeterlidir. 193 | ``` 194 | git log 195 | >>> commit 000d29e2fa8d89a98336f3be97d08e45a450769f (HEAD -> master) 196 | Author: mebaysan 197 | Date: Sun May 17 19:45:31 2020 +0300 198 | 199 | hello world fonksiyonu eklendi 200 | 201 | commit 62cf9b59f0380115aaea2201c36d6a8a2d781455 202 | Author: mebaysan 203 | Date: Sun May 17 19:20:47 2020 +0300 204 | 205 | ilk commit 206 | 207 | ``` 208 | - Hangi commit'te ne gibi değişiklikler olmuş dilersek bunları görebiliriz. `git diff commit_id` komutunu `git log` komutunun çıktısında gelen commit loglarının yanındaki id'leri argüman olarak yollayarak kullanabiliriz. Gelin **ilk commit**'ten sonra ne gibi değişiklikler olmuş onları görelim. ` git diff 62cf9b59f0380115aaea2201c36d6a8a2d781455` komutunu kullanacağım. Çünkü **ilk commit**'imin id'si bende bu şekilde. 209 | ``` 210 | git diff 62cf9b59f0380115aaea2201c36d6a8a2d781455 211 | >>> diff --git a/intro.py b/intro.py 212 | index 8eb74cf..416a5e7 100644 213 | --- a/intro.py 214 | +++ b/intro.py 215 | @@ -1 +1,3 @@ 216 | -print('Hello world') 217 | \ No newline at end of file 218 | +print('Hello world') 219 | + 220 | +print('Hello World 2') 221 | root@covid-x:~/Desktop/pr 222 | 223 | ``` 224 | - Gördüğümüz gibi sildiğimiz satırlar satır başlarında '`-`' ile ifade edilirken, eklediğimiz satırlar ise satır başlarında '`+`' ile ifade ediliyor. 225 | - İlk committeki haline geri dönmek istediğimizi varsayalım. `git log` ile ilgili commit'in id'sini aldıktan sonra `git checkout 62cf9b59f0380115aaea2201c36d6a8a2d781455` komutunu dönmek istediğimiz commit'in id'sini argüman olarak yollayarak kullanalım. 226 | ``` 227 | git checkout 62cf9b59f0380115aaea2201c36d6a8a2d781455 228 | >>> Warning: you are leaving 1 commit behind, not connected to 229 | any of your branches: 230 | 231 | 382cfe1 ds1 232 | 233 | If you want to keep it by creating a new branch, this may be a good time 234 | to do so with: 235 | 236 | git branch 382cfe1 237 | 238 | HEAD is now at 62cf9b5 ilk commit 239 | ``` 240 | - Şimdi repository'miz id'sini verdiğimiz (`62cf9b59f0380115aaea2201c36d6a8a2d781455`) commit'teki haline geri döndü. Tekrar son commit'teki haline çevirmek istersek aynı komutu ilgili commit id'sini argüman olarak yollayarak kullanabiliriz. 241 | 242 | # Branch 243 | 244 | ## Branch Nedir? 245 | Git commit'lerimizi şimdiye kadar hep lineer bir yapıda tuttuk. Fakat Git'in yetenekleri bundan daha fazlasını yapmasına yardım ediyor. Git, commit'leri sadece tek bir dalda değil, birden fazla dal içerebilen bir **ağaç** yapısında tutabilir. Böylece iki ayrı dal (iki ayrı modül) üzerinde çalışabilir ve işimiz bittiğinde bu dalları birleştirerek tek bir dala sahip olabiliriz. 246 | - Default olarak gelen branch'imizin adı `master`'dır. 247 | 248 | ## Peki Neden Branch'lere İhtiyaç Duyarız? 249 | Projelerimiz çoğu zaman tek bir çizgi üzerinde ilerlemez. Eş zamanlı olarak projemizin farklı modülleri üzerinde çalışmak isteyebiliriz, farklı bug fix'leri üzerinde aynı anda çalışmak isteyebiliriz veya web sayfalarımızın birden fazla versiyonunu hazırlayıp test etmek isteyebiliriz. Bu gibi durumlarda projemizin sağlıklı çalışır bir versiyonunu (**branch**) elimizde bulundurmak isteriz. Default olarak gelen `master` branch'imizi **ana** branch'imiz olarak düşünelim. İki farklı dala ayırıp Modül1 üzerinde ve Modül2 üzerinde eş zamanlı olarak çalışabiliriz. Modül2'nin yazımı bittikten sonra Modül1'in yazımını beklemeden yapılan değişiklikleri master branch'e aktarabiliriz. Bu işleme ise `merge` denmektedir. Artık **master branch**'imize Modül2'de dahil olmuş oldu. 250 | #### Ufak Bir Not 251 | Master branch'imizde her zaman projemizin prod'a çıkabilecek bir versiyonunu bulundurmamız bizim yararımıza olacaktır. 252 | 253 | - Bir branch oluşturmak için `git branch branch_adi` komutunu oluşturmak istediğimiz branch'in adını argüman olarak yollayarak kullanmamız gerekmektedir. Ardından `git status` ile repomuzun durumunu kontrol edelim ve hangi branch'te olduğumuza bakalım. Demiştik ki ilk git reposu oluşturulduğunda default olarak `master` branch açılır. 254 | ``` 255 | git branch haber-listele # haber listele adında branch oluştuduk 256 | git branch musteri-listele # müşteri listele adında branch oluştuduk 257 | git status 258 | >>> On branch master 259 | nothing to commit, working tree clean 260 | ``` 261 | - Branch değiştirmek için `git checkout branch_adi` komutunu, geçmek istediğimiz branch'in adını argüman olarak vererek kullanabiliriz. Ardından tekrar `git status` ile hangi branch'te olduğumuzu görebiliriz. 262 | ``` 263 | git checkout haber-listele 264 | >>> Switched to branch 'haber-listele' 265 | 266 | git status 267 | >>> On branch haber-listele 268 | nothing to commit, working tree clean 269 | ``` 270 | - Ardından `haber_getir.py` adında bir dosyayı `haber-listele` adlı branch'ime ekleyeceğim ve sonrasında commit ettikten sonra `git log` komutu ile branch'imde yapılmış olan değişiklikleri göreceğim. 271 | ``` 272 | cat > haber_listele.py 273 | 274 | .def haber_getir(): 275 | . print('Haberler getiriliyor...') 276 | . 277 | . 278 | 279 | git add haber_listele.py 280 | 281 | git commit -m 'haber listeleme modulu eklendi' 282 | >>> [haber-listele 287f583] haber listeleme modulu eklendi 283 | 1 file changed, 3 insertions(+) 284 | create mode 100644 haber_listele.py 285 | 286 | git log 287 | >>> commit 287f5835608c07fd0569f2d371f5769e76950984 (HEAD -> haber-listele) 288 | Author: mebaysan 289 | Date: Mon May 18 01:44:56 2020 +0300 290 | 291 | haber listeleme modulu eklendi 292 | 293 | commit c374c7b8837d2e84b85e41413902898709c1d7b9 (musteri-listele, master) 294 | Author: mebaysan 295 | Date: Mon May 18 01:34:30 2020 +0300 296 | 297 | proje olusturuldu 298 | 299 | ``` 300 | - Şimdi `master` branch'imize geçelim. Ardından da bu branch'te ne gibi değişiklikler olmuş ona bakalım. 301 | ``` 302 | git checkout master 303 | >>> Switched to branch 'master' 304 | 305 | git log 306 | >>> commit c374c7b8837d2e84b85e41413902898709c1d7b9 (HEAD -> master, musteri-listele) 307 | Author: mebaysan 308 | Date: Mon May 18 01:34:30 2020 +0300 309 | 310 | proje olusturuldu 311 | 312 | ``` 313 | - Gördüğümüz gibi az önce yaptığımız commit ('haber listeleme modulu eklendi') gözükmüyor. Bunun sebebi ise o commit'in `haber-listele` branch'inde olması. Henüz master branch'i ile **merge** edilmedi. 314 | - Şimdi `musteri-listele` branch'imize geçelim ve biraz değişiklik yapalım ve commit edelim. 315 | ``` 316 | git checkout musteri-listele 317 | >>> Switched to branch 'musteri-listele' 318 | 319 | cat > musteri_getir.py 320 | 321 | . def musteri_getir(): 322 | . print('Musteriler getiriliyor..') 323 | . 324 | . 325 | 326 | git add musteri_getir.py 327 | 328 | git commit -m 'musteri getirme modulu eklendi' 329 | >>> [musteri-listele f4b4584] musteri getirme modulu eklendi 330 | 1 file changed, 3 insertions(+) 331 | create mode 100644 musteri_getir.py 332 | ``` 333 | - `haber-listele` branch'inin prod'a çıkmaya hazır olduğunu varsayalım. Ve prod branch'imiz olan master ile birleştirelim (**merge**). İki branch'i **merge** etmek için önce güncelleme yapmak istediğimiz (bu proje için master) branch'e geçelim. Ardından `git merge branch_adi` komutunu merge (birleştirmek) istediğimiz branch adını argüman olarak yollayarak kullanabiliriz. Bu işlemden sonra mevcut (master) branch'imizde ne gibi değişiklikler olmuş görelim. 334 | ``` 335 | git checkout master # güncelleme yapmak istediğimiz branch'e geçiyoruz 336 | >>> Switched to branch 'master' 337 | 338 | git merge haber-listele # birleştirmek istediğimiz branch'i söylüyoruz 339 | >>> Updating c374c7b..287f583 340 | Fast-forward 341 | haber_listele.py | 3 +++ 342 | 1 file changed, 3 insertions(+) 343 | create mode 100644 haber_listele.py 344 | 345 | 346 | git log 347 | >>> commit 287f5835608c07fd0569f2d371f5769e76950984 (HEAD -> master, haber-listele) 348 | Author: mebaysan 349 | Date: Mon May 18 01:44:56 2020 +0300 350 | 351 | haber listeleme modulu eklendi 352 | 353 | commit c374c7b8837d2e84b85e41413902898709c1d7b9 354 | Author: mebaysan 355 | Date: Mon May 18 01:34:30 2020 +0300 356 | 357 | proje olusturuldu 358 | ``` 359 | 360 | #### Ufak Bir Not 361 | `git log` komutunu `--oneline` parametresi ile birlikte kullanırsak daha temiz bir çıktı alabiliriz 362 | ``` 363 | git log --oneline 364 | >>> 287f583 (HEAD -> master, haber-listele) haber listeleme modulu eklendi 365 | c374c7b proje olusturuldu 366 | ``` 367 | - Gördüğümüz gibi `master` branch'imizde artık `haber-listele` branch'indeki kodlar da gelmiş bulunmakta. 368 | - `musteri-listele` branch'i ile de işimiz bittiğini varsayalım ve onu da master branch'imiz ile merge edelim. Ardından yapılan değişiklikleri görmek için `git log` komutunu kullanalım. 369 | ``` 370 | git merge musteri-listele 371 | >>> Merge made by the 'recursive' strategy. 372 | musteri_getir.py | 3 +++ 373 | 1 file changed, 3 insertions(+) 374 | create mode 100644 musteri_getir.py 375 | 376 | git log --oneline 377 | 378 | >>> 7b0af94 (HEAD -> master) Merge branch 'musteri-listele' 379 | f4b4584 (musteri-listele) musteri getirme modulu eklendi 380 | 287f583 (haber-listele) haber listeleme modulu eklendi 381 | c374c7b proje olusturuldu 382 | 383 | ``` 384 | - `musteri-listele` branch'indeki değişiklikleri, diğer branch'lerimizdeki değişikleri **umursamadan** merge ettik. Fakat bu sefer bir kaç farklı değişikliğin olduğu hemen gözümüze çarpmakta. `Merge branch ...` de neyin nesi? Bu ekstra commit Git tarafından oluşturulan, iki branch'in merge işlemleriyle ilgili **boş bir commit**. 385 | 386 | ## Branch'leri Silmek 387 | `musteri-listele` ve `haber-listele` branch'lerini `master` branch'imize taşıdığımza göre artık bu branch'leri silebiliriz. Bunun için `git branch -d branch_adi` komutunu silmek istediğimiz branch'in adını argüman olarak yollayarak kullanabiliriz. Adını yolladığımız branch **silinecektir**. Eğer oluşturduğumuz branch'leri unuttuysak `git branch` komutu ile oluşturduğumuz branchleri ve hangi branch'te olduğumuzu görebiliriz. 388 | ``` 389 | git branch 390 | >>> haber-listele 391 | * master # yanında yıldız olan branch, üzerinde çalıştığımız branch'dir 392 | musteri-listele 393 | 394 | 395 | git branch -d haber-listele 396 | >>> Deleted branch haber-listele (was 287f583) 397 | 398 | git branch -d musteri-listele 399 | >>> Deleted branch musteri-listele (was f4b4584) 400 | ``` 401 | - Branch'leri silerken endişelenmemize gerek yok. Eğer silmek istediğimiz branch başka bir branch'e merge edilmediyse git bizi uyaracaktır :innocent: 402 | 403 | # Conflicts (Çakışmalar) 404 | Yukarıda branch'leri **merge** ederken hep farklı dosyalar üzerinde çalıştık ve bunları merge ederken çakışma (conflict) olmadı. Git üç branch'teki üç commit'i birleştirdi. Peki ya **2 farklı branch**'te **aynı dosya/lar** üzerinde değişiklik yapsaydık? 405 | 406 | - 2 adet branch oluşturacağım ve ikisinde de musteri.py üzerinde değişiklikler yapacağım. 407 | ``` 408 | git branch musteri-listele 409 | git branch musteri-getir # 2 adet branch oluşturdum 410 | 411 | git checkout musteri-listele # mevcut branch'imi değiştirdim 412 | >>> Switched to branch 'musteri-listele' 413 | 414 | cat >> musteri.py 415 | . def musteri_listele(): 416 | . print('Müşteriler listeleniyor..') 417 | . 418 | . 419 | 420 | git add musteri.py 421 | 422 | git commit -m 'musteri_listele func eklendi' 423 | >>> [musteri-listele 42632e0] musteri_listele func eklendi 424 | 1 file changed, 3 insertions(+) 425 | 426 | ``` 427 | - `musteri-listele` branch'imizde değişiklikleri yaptık. Şimdi `musteri-getir` branch'inde değişiklik yapalım. 428 | ``` 429 | git checkout musteri-getir 430 | >>> Switched to branch 'musteri-getir' 431 | 432 | cat >> musteri.py 433 | . def musteri_getir(): 434 | . print('Müşteriler getiriliyor..') 435 | . 436 | . 437 | 438 | git add musteri.py 439 | 440 | git commit -m 'musteri getir func eklendi' 441 | >>> [musteri-getir 1cf8c90] musteri getir func eklendi 442 | 1 file changed, 3 insertions(+) 443 | 444 | ``` 445 | - 2 farklı branch'de `musteri.py` dosyası üzerinde değişiklik yaptık. Şimdi `master` branch'imize geçip `musteri-listele` branch'ini **merge** edelim. 446 | ``` 447 | git checkout master 448 | >>> Switched to branch 'master' 449 | 450 | git merge musteri-listele 451 | >>> Updating 9a39d7a..42632e0 452 | Fast-forward 453 | musteri.py | 3 +++ 454 | 1 file changed, 3 insertions(+) 455 | ``` 456 | - `master` ve `musteri-listele` branch'lerini başarılı bir şekilde **merge** ettik. Şimdi de `master` ve `musteri-getir` branch'lerini merge etmeyi **deneyelim** 457 | ``` 458 | git merge musteri-getir 459 | >>> Auto-merging musteri.py 460 | CONFLICT (content): Merge conflict in musteri.py 461 | Automatic merge failed; fix conflicts and then commit the result. 462 | ``` 463 | - Evet hayırlı olsun ilk **conflict (çakışma)** hatamızı aldık :blush: Git bize `musteri.py` içerisinde bir çakışma (conflict) olduğunu, bu sebeple otomatik birleştirme işlemini (merge) gerçekleştiremediğini söylüyor. Dosyamızı açarsak Git bize çakışma hakkında daha detaylı bilgi verecektir. Halihazırda Linux bir sistem kullandığım için `cat` komutu ile dosyamın içeriğini görüntüleyeceğim. 464 | ``` 465 | cat musteri.py 466 | >>> print('Musteriler getiriliyor') 467 | 468 | <<<<<<< HEAD 469 | def musteri_listele(): 470 | print('Müşteriler listeleniyor..') 471 | ======= 472 | def musteri_getir(): 473 | print('Müşteriler getiriliyor..') 474 | >>>>>>> musteri-getir 475 | ``` 476 | - Gördüğümüz gibi Git bize hangi satırlarda çakışma olduğunun bilgisini veriyor. `<<<` ve `>>>` işaretleri ile gösteriyor. 477 | - `<<<<<<< HEAD` ile `=======` işaretleri arasındaki kısım `master` branch'ine ait mevcut durumu gösteriyor. 478 | - `=======` ile `>>>>>>>` **merge** etmek istediğimiz branch'teki yani `musteri-getir` branch'indeki halini gösteriyor. 479 | - Bu noktada `<<<<<<<` ve `>>>>>>>` işaretlerini silip dosyamızı istediğimiz, çalışır haline getiriyoruz ve `conflict`'i çözmüş oluyoruz. Ardından tekrar değişen dosyayı `staging area`'ya ekliyoruz ve commit ediyoruz. 480 | ``` 481 | nano musteri.py # düzenleyeceğim dosyamı açıyorum ve içeriği aşağıdaki gibi düzenliyorum 482 | 483 | . def musteri_listele_getir(): 484 | . print('Müşteriler listeleniyor..') 485 | . print('Müşteriler getiriliyor..') 486 | . 487 | . 488 | 489 | git add musteri.py # dosyamızı staging area'ya ekliyoruz 490 | git commit -m 'conflict cozuldu' # commit ediyoruz 491 | >>> [master 34463c6] conflict cozuldu 492 | git status # durumu gözden geçiriyoruz 493 | >>> On branch master 494 | nothing to commit, working tree clean 495 | ``` 496 | - Dilersek `git log --oneline` ile neler yaptığımıza bakabiliriz. 497 | ``` 498 | git log --oneline 499 | >>> 34463c6 (HEAD -> master) conflict cozuldu 500 | 1cf8c90 (musteri-getir) musteri getir func eklendi 501 | 42632e0 (musteri-listele) musteri_listele func eklendi 502 | 9a39d7a proje olusturuldu ve musteriler.py eklendi 503 | ``` 504 | # Rebasing 505 | Kısaca Rebase işlemi commit tarihçemizin daha temiz gözükmesini sağlar. Daha iyi anlamak için boş bir git projesi açacağım ve sırasıyla bir txt içerisine 3 adet commit atacağım. 506 | ``` 507 | cat > rebasing 508 | . 1 509 | . 510 | 511 | git add rebasing 512 | 513 | git commit -m 'commit 1' # dosya içeriğini değiştirdim ve commit1 attım 514 | >>> [master (root-commit) 631d1fd] commit 1 515 | 1 file changed, 1 insertion(+) 516 | create mode 100644 rebasing 517 | 518 | cat >> rebasing 519 | . 2 520 | . 521 | 522 | git add rebasing 523 | 524 | git commit -m 'commit 2' # dosya içeriğini değiştirdim ve commit2 attım 525 | >>> [master 1247fc8] commit 2 526 | 1 file changed, 1 insertion(+) 527 | 528 | 529 | cat >> rebasing 530 | . 3 531 | . 532 | 533 | git add rebasing 534 | 535 | git commit -m 'commit 3' # # dosya içeriğini değiştirdim ve commit3 attım 536 | >>> [master ad28eba] commit 3 537 | 1 file changed, 1 insertion(+) 538 | ``` 539 | - Şu anda sıralamamız şu şekilde oldu `commit1 -> commit2 -> commit3`. Bunu kanıtlamak için hemen `git log` komutunu kullanabiliriz. Ve commit3 varken `gelecek` adında bir branch açıp bu branch'te `commit4`'ü atalım 540 | ``` 541 | git log --oneline 542 | >>>ad28eba (HEAD -> master) commit 3 543 | 1247fc8 commit 2 544 | 631d1fd commit 1 545 | 546 | git branch gelecek 547 | git checkout gelecek 548 | >>> Switched to branch 'gelecek' 549 | 550 | cat >> rebasing 551 | . 4 552 | . 553 | 554 | git add rebasing 555 | 556 | git commit -m 'commit 4' 557 | >>> [gelecek 3d467a3] commit 4 558 | 1 file changed, 1 insertion(+) 559 | ``` 560 | - Şu anda `gelecek` branch'imizde `commit1 -> commit2 -> commit3 -> commit4` şeklinde bir yapı oluştu. 561 | - Tekrar `master` branch'imize geçelim ve `commit5` ile `commit6`'yı atalım. 562 | ``` 563 | git checkout master 564 | >>> Switched to branch 'master' 565 | 566 | cat >> rebasing 567 | . 5 568 | . 569 | 570 | git add rebasing 571 | 572 | git commit -m 'commit 5' 573 | >>> [master 8199a6d] commit 5 574 | 1 file changed, 1 insertion(+) 575 | 576 | 577 | cat >> rebasing 578 | . 6 579 | . 580 | 581 | git add rebasing 582 | 583 | git commit -m 'commit 6' 584 | >>> [master 1c16f6b] commit 6 585 | 1 file changed, 1 insertion(+) 586 | ``` 587 | - Şimdi `master` branch'imizde şu şekilde bir yapı oldu: `commit1 -> commit2 -> commit3 -> commit5 -> commit6`. Bunu da hemen `git log` ile görelim. 588 | ``` 589 | git log --oneline 590 | >>> 1c16f6b (HEAD -> master) commit 6 591 | 8199a6d commit 5 592 | ad28eba commit 3 593 | 1247fc8 commit 2 594 | 631d1fd commit 1 595 | ``` 596 | - Peki oluşturduğumuz `commit4` nerede? Siz de takdir edersiniz ki 2 branch'i `merge` etmediğimiz için `commit4` `master` branch'inde gözükmüyor. Eğer ki `git merge gelecek` komutunu çalıştırırsak `master` ve `gelecek` branch'leri birleşmiş olacak. Unutmamalıyız ki `merge` işlemi commit'leri **tarih sırasına** göre merge eder :exclamation: Bu sebeple şöyle bir sıkıntımız olacak; yeni commit sırası `commit1 -> commit2 -> commit3 -> commit4 -> commit5 -> commit6` olacak. Fakat bizim yaptığımız commit işlemlerine göre sıramızın şu şekilde olması gerekli: `commit1 -> commit2 -> commit3 -> commit5 -> commit6 -> commit4`. İşte tam bu noktada `rebasing` imdadımıza yetişiyor ve ~~`git merge branch_adi`~~ yerine `git rebase branch_adi` komutunu kullanmamız gerekiyor. 597 | ``` 598 | git rebase gelecek 599 | >>> Successfully rebased and updated refs/heads/master. 600 | ``` 601 | - Şimdi yeni yapımız bu şekilde oldu; `commit1 -> commit2 -> commit3 -> commit5 -> commit6 -> commit4`. Yani `gelecek` branch'inden gelen `commit4` commit'lerin en sonuna eklendi. Böylelikle ilgili commitler (1-2-3-5-6) bir arada kalmış oldu. 602 | 603 | # Reset (Dosyaları Eski Hallerine Döndürme) 604 | - `intro.py` adında bir dosyam var. Bunu staging area'ya ekledim ve içerisine yeni kodlar ekliyorum. Bunları da `ilk commit` olarak commit ediyorum. Ardından `haber_ekle` adında bir fonksiyon ekliyorum. Şimdi de `git diff` komutu ile neler değişmiş bir bakalım. 605 | ``` 606 | git log --oneline 607 | >>> diff --git a/intro.py b/intro.py 608 | index 0fad725..555701a 100644 609 | --- a/intro.py 610 | +++ b/intro.py 611 | @@ -1,2 +1,5 @@ 612 | print('İlk hal') 613 | 614 | +def haber_getir(): 615 | + print('Haber getir') 616 | + 617 | 618 | ``` 619 | - `haber_getir` fonksiyonumuzda bir sıkıntı olduğunu görüyoruz (varsayalım) ve bunu **bir önceki** commit'teki haline geri çevirmek istiyoruz. Bunun için `git reset --hard` komutunu kullanmamız yeterlidir. Yaptığımız tüm değişiklikler **bir önceki** commit'teki haline döner. 620 | ``` 621 | git reset --hard 622 | >>> HEAD is now at f5eb00f ilk commit 623 | 624 | cat intro.py # projemin ilk haline döndüğünü görüyorum 625 | >>> print('İlk hal') 626 | ``` 627 | - YAptığımız tüm değişiklikler silindi ve dosyamız `ilk commit` haline geri döndü. 628 | - `--hard` ifadesi **reset'in 2 modundan biri olan** **hard**'ı temsil eder. **hard** denilen mod repomuzdaki **tüm dosyalardaki** değişiklikleri iptal ederek son commit'teki haline geri getirir. 629 | - **soft** denilen mod ise; reset dosyalarını staging area'dan working directory'e çeker. Yani dosyamızı commit edilecekler listesinden çıkartır fakat değişikliklerimize dokunmaz. Tekrar `intro.py` içerisine `selamla` adında bir func ekliyorum. Sonrasında sırasıyla; dosyamı staging area'ya ekliyorum ve repomun durumuna bakıyorum ardından `git reset` komutu ile **soft** reset gerçekleştiriyorum ve tekrar repomun durumuna bakıyorum. 630 | ``` 631 | cat >> intro.py 632 | >>> def selamla(): 633 | print('NABER NASILSIN') 634 | 635 | git add intro.py 636 | 637 | git status 638 | >>> On branch master 639 | Changes to be committed: 640 | (use "git restore --staged ..." to unstage) 641 | modified: intro.py 642 | 643 | git reset 644 | >>> Unstaged changes after reset: 645 | M intro.py 646 | 647 | git status 648 | >>> On branch master 649 | Changes not staged for commit: 650 | (use "git add ..." to update what will be committed) 651 | (use "git restore ..." to discard changes in working directory) 652 | modified: intro.py 653 | 654 | ``` 655 | - Gördüğümüz gibi dosyamızda yapılan değişiklikler kaybolmadı fakat dosyamız staging area'dan çıkarıldı. 656 | # STASH 657 | Branch'imizde bir iş üzerinde çalışırken bir anda acil bir işimiz çıkarsa, onu commit etmemiz gerekebilir fakat henüz üzerinde çalıştığımız dosyalar henüz bitmediği için bunları commit etmek istemeyebiliriz. Tam bu aşamada imdadımıza `git stash` yetişecektir. Türkçe meali şudur -> **Şimdilik diğer işlerime dönmem gerekiyor, onları bitirip commit edeceğim bu dosyalara daha sonra döneceğim. Bunları commit etme ama yine de bir kenara kaydet ki geri döndüğümde kaldığım yerden devam edebileyim** 658 | - `modul1.py` ve `modul2.py` adında 2 dosya oluşturup bu dosyaları **staging area**'ya alalım. 659 | ``` 660 | git add . # '.' ile bulunduğumuz dizin altındaki her şeyi staging area'ya ekleyebiliriz. 661 | git status 662 | >>> On branch master 663 | Changes not staged for commit: 664 | (use "git add ..." to update what will be committed) 665 | (use "git restore ..." to discard changes in working directory) 666 | modified: modul1.py 667 | modified: modul2.py 668 | 669 | no changes added to commit (use "git add" and/or "git commit -a") 670 | ``` 671 | - Senaryomuz şu şekilde devam edecek. Henüz `modul1.py` ve `modul2.py` ile işimiz bitmedi fakat `modul3.py` dosyasını ekleyip **commit** etmemiz gerekecek. Hemen `git stash` komutunu kullanabiliriz. Git bizim için `modul1.py` ve `modul2.py` içerisindeki değişiklikleri **bir önceki commit**'teki haline çevriecektir. 672 | ``` 673 | git stash 674 | >>> Saved working directory and index state WIP on master: 08fb51c ilk commit 675 | ``` 676 | - Şimdi `modul3.py` oluşturup commit edebiliriz. Çünkü diğer dosyalardaki değişiklikler bir kenara kaydedildi ve henüz prod'a gitmeye hazır olmadığından `modul3.py` ile işlerimizi bitirip tekrar onlara bakabiliriz. 677 | ``` 678 | git add modul3.py 679 | git commit -m 'modul3 eklendi' 680 | >>> [master 2bb3c93] modul3 eklendi 681 | 1 file changed, 2 insertions(+) 682 | create mode 100644 modul3.py 683 | ``` 684 | - `git status` ile bakarsak çalışma alanımızın temiz olduğunu, `git log` ile bakarsak da en son attığımız commit'i görebiliriz. 685 | - Yarıda bıraktığımız işleri gözlemlemek için `git stash list` komutunu kullanabiliriz. 686 | ``` 687 | git stash list 688 | >>> stash@{0}: WIP on master: 08fb51c ilk commit 689 | ``` 690 | - Bu komutun çıktısı bize `stash@{0}` (0) numaralı bir stash'imizin olduğunu söylüyor. Bu stash'i tekrar repomuza çekmek için `git stash apply stash_numarasi` komutunu çekmek istediğimiz **stash_numarasi**'nı argüman olarak yollayarak kullanabiliriz. Ardından dilersek `git status` komutunu kullanarak `modul1.py` ve `modul2.py` dosyalarının içeriklerinin değiştiğini, geri geldiğini görebiliriz. 691 | ``` 692 | git stash apply stash@{0} 693 | >>> On branch master 694 | Changes not staged for commit: 695 | (use "git add ..." to update what will be committed) 696 | (use "git restore ..." to discard changes in working directory) 697 | modified: modul1.py 698 | modified: modul2.py 699 | 700 | no changes added to commit (use "git add" and/or "git commit -a") 701 | 702 | ``` 703 | ### Ufak Bir Not 704 | Git stash'e attığımız değişiklikleri `Last In First Out (LIFO)` bir stack yapısında tutar. Stash'e bir şey attığımızda bu `stash@{0}`'da tutulurken yeni bir stash daha eklediğimizde `stash@{0}` 1 kaydırılarak `stasth@{1}`'e geçmiş olur. **Yeni gelen stash ise `stash@{0}`'a yerleşmiş olur**
705 | `git stash appyl stash_numarasi` komutunu çalıştırarak değişiklikleri repomuza uygulayabiliriz fakat bu değişiklikler stash'den **silinmez** :exclamation: 706 | 707 | - Peki stash'e en son attığımız değişikliği (**stash@{0}**) repomuza uygulamak istersen ne yapacağız? Tam bu noktada devreye `git stash pop` komutu devreye giriyor. **En son** stash'e atılan değişikliği repomuza uygular ve bunu stash'ten **siler** 708 | ``` 709 | git stash pop 710 | >>> On branch master 711 | Changes not staged for commit: 712 | (use "git add ..." to update what will be committed) 713 | (use "git restore ..." to discard changes in working directory) 714 | modified: modul1.py 715 | modified: modul2.py 716 | 717 | no changes added to commit (use "git add" and/or "git commit -a") 718 | Dropped refs/stash@{0} (1289d26b06503c78b0c04eefe4c0d677f7bff926) 719 | ``` 720 | - Peki stash'lere de commit'ler gibi mesaj eklememiz mümkün değil mi? Tabii ki mümkün. `git stash save "stash mesaji"` komutu ile birlikte stash'imize mesaj ekleyebiliriz. Bu komutu kullanmadan yukarıdaki gibi sadece `git stash` komutunu kullanırsak Git bizim için kendisi mesaj oluşturacaktır: `WIP on master` -> hangi branch'te çalışıyoruz, `08fb51c` -> en son ki commit'in numarası, `ilk commit` -> en son commit'in mesajı 721 | ``` 722 | git stash save "modul4 olusturuldu fakat yarida kaldi" 723 | >>> Saved working directory and index state On master: modul4 olusturuldu fakat yarida kaldi 724 | 725 | git stash list 726 | >>> stash@{0}: On master: modul4 olusturuldu fakat yarida kaldi 727 | ``` 728 | # Gitignore (Dosyaları Yok Saymak) 729 | Git otomatik olarak repo klasörümüz içerisindeki **bütün dosyaları** takip eder. Peki biz local'de farklı çalışan dosyaları uzak sunucuya göndermek istemezsek? Bu noktada da imdadımıza `.gitignore` adlı dosya yetişiyor. Başında '`.`' olmasının sebebi bu dosyanın gizli bir dosya olmasından kaynaklanmaktadır. Bu dosya içerisine yazılan **dosya/dizin** isimleri Git tarafından takip edilmez ve repolarımıza eklenmez. Bu dosya içerisinde `regex` kullanmamız mümkündür. 730 | - Temiz bir repo oluşturalım ve içine `global.py`,`local.py`,`deneme.txt` ve `deneme2.txt` adında dosyaları ekleyelim. Ardından `.gitignore` adında bir dosya oluşturup içerisine `local.py` ve `*txt` satırlarını ekleyip `git status` ile repomuzun durumuna bakalım. 731 | ``` 732 | git status # dosyalarımı ilk eklediğim anda repo durumu sorguluyorum 733 | >>> On branch master 734 | 735 | No commits yet 736 | 737 | Untracked files: 738 | (use "git add ..." to include in what will be committed) 739 | deneme1.txt 740 | deneme2.txt 741 | global.py 742 | local.py 743 | 744 | nothing added to commit but untracked files present (use "git add" to track) 745 | 746 | touch .gitignore # dosyamı oluşturdum 747 | vim .gitignore 748 | . local.py 749 | . *.txt 750 | . 751 | . 752 | 753 | git status 754 | >>> On branch master 755 | 756 | No commits yet 757 | 758 | Untracked files: 759 | (use "git add ..." to include in what will be committed) 760 | .gitignore 761 | global.py 762 | 763 | nothing added to commit but untracked files present (use "git add" to track) 764 | ``` 765 | - Gördüğümüz gibi Git working directory'de sadece `.gitignore` ve `global.py` dosyalarını görmekte. `.gitignore` dosyası içine yazdığımız `local.py` satırı o isimdeki dosyanın Git tarafından takip edilmemesini sağladı. Aynı şekilde `*.txt` satırı ise sonu '**.txt**' ile bütün dosyaların takip edilmemesini sağladı. 766 | 767 | # Değiştirilemeyen Dosyalar 768 | Düşünelimki bir Django projesi geliştiriyoruz ve PostgreSQL kullanıyoruz. Local'imizdeki ve uzak sunucumuzdaki database ayarları muhtemelen farklı olacaktır. Ve `settings.py` dosyamızın içeriğinin localde ve uzak sunucuda farklı olmasını bu sebeple local repodaki `settings.py`'ın uzak sunucuya gönderilmemesini istiyoruz. İlgili dosyamızı **commit** ettikten sonra `git update-index --assume-unchanged dosya_adi` komutunu ilgili dosyanın adını argüman olarak yollayarak kullanabiliriz. **En son commit**'teki halinin üzerine hiç bir değişiklik yapılmasına izin vermez. 769 | ``` 770 | cat > settings.py 771 | . username = 'USERNAME' 772 | . password = 'PASSWORD' 773 | . 774 | . 775 | 776 | git add . 777 | git commit -m 'settings eklendi' 778 | 779 | git update-index --assume-unchanged settings.py # bir üstteki commit'teki haliyle kalacak dosyamız. İşaretledik 780 | 781 | cat >> settings.py # dosyama veri ekliyorum 782 | . provider='pgsql' 783 | . 784 | . 785 | 786 | git status 787 | >>> On branch master 788 | nothing to commit, working tree clean 789 | ``` 790 | Gördüğümüz gibi `settings.py`'a veri eklemiş olmamıza rağmen repo durumunu sorguladığımızda her hangi bir değişiklik algılamadı. Bunun sebebi ise `settings.py`'ın değiştirilemez olarak işaretledik ve en son commit'teki halini aldı.
791 | Dosyamız üzerinden işareti kaldırmak istersek ise `git update-index --no-assume-unchanged dosya_adi` komutunu ilgili `dosya_adi`'ni argüman olarak göndererek kullanmamız yeterlidir. 792 | ``` 793 | git update-index --no-assume-unchanged settings.py 794 | git status 795 | 796 | >>> On branch master 797 | Changes not staged for commit: 798 | (use "git add ..." to update what will be committed) 799 | (use "git restore ..." to discard changes in working directory) 800 | modified: settings.py 801 | 802 | no changes added to commit (use "git add" and/or "git commit -a") 803 | ``` 804 | ### Ufak Bir Not 805 | Beraber çalıştığımız tüm geliştiricilerin de işaretlenmesi gereken bir dosya varsa `--assume-unchanged` komutunu çalıştırması gerekiyor. Aksi takdirde local'de ve uzak sunucuda ayrı tutulması gereken verileri commit edebilirler. 806 | 807 | # Dosyaları Silmek 808 | Git ile dosyaları sildiğimiz zaman bu değişikliği de normalde kullandığımız ~~`git add`~~ komutu ile değil `git rm` komutu ile Git'e bildirmemiz gerekiyor. 809 | ``` 810 | rm settings.py # dosyayı bilgisayardan sildim 811 | git status 812 | >>> On branch master 813 | Changes not staged for commit: 814 | (use "git add/rm ..." to update what will be committed) 815 | (use "git restore ..." to discard changes in working directory) 816 | deleted: settings.py 817 | 818 | no changes added to commit (use "git add" and/or "git commit -a") 819 | 820 | git rm settings.py # silme işlemimizi de commit edilecekler listesine ekliyoruz 821 | >>> rm 'settings.py' 822 | 823 | git status 824 | >>> On branch master 825 | Changes to be committed: 826 | (use "git restore --staged ..." to unstage) 827 | deleted: settings.py 828 | 829 | ``` 830 | 831 | # Commit'leri Kopyalamak (git-cherry) 832 | Commit'leri `reset` ile silebileceğimizi biliyoruz. Peki nasıl kopyalayabiliriz? `git cherry-pick commit_id` komutunu kopyalamak istediğimiz commit'in id'sini argüman olarak yollayarak kullanabiliriz. 833 | - Şu anda şöyle bir yapım var. `commit1 -> commit2 -> commit3`. Ben `commit3` üzerindeyken `commit1`'in kopyasını almak istersem, `git cherry-pick commi1_id` komutunu kullanmalıyım. Bu sayede yeni yapı şu şekilde olacak `commit1 -> commit2 -> commit3 -> commit1` 834 | ``` 835 | git cherry-pick 313de84 836 | git log --oneline 837 | >>> 9db5a41 (HEAD -> master) commit 1 838 | b79a76d commit 3 839 | 700d1c0 commit 2 840 | 313de84 commit 1 841 | ``` 842 | # Alias (Takma Adlar) 843 | Git ile ilgili komutları dilersek kısaltabiliriz. Bunlara **alias** denmektedir. Mesela `git checkout master` komutunu yazmak yerine sadece `git cm` komutunu yazabiliriz. Bunu ise `git config --global alias.cm 'checkout master'` komutu ile yapabiliriz. `--global` mevcut sistem üzerindeki her git reposu için geçerli olmasını söyledi. `alias.cm` ile `cm` adında bir takma komut ismi oluşturduk ve `'checkout master'` ile `cm` komutunun ne yapması gerektiğini belirttik. 844 | ``` 845 | git config --global alias.cm 'checkout master' 846 | git cm 847 | >>> Already on 'master' 848 | ``` 849 | # Uzak Sunucu 850 | Şimdiye kadar hep local makinamızda repolar oluşturduk ve işlemler gerçekleştirdik. Git'in kullanıldığı uzak sunucular vardır ve buralarda birden fazla geliştirici bir proje üzerinde aynı anda çalışmalar yapabilir. En başta dediğimiz gibi **Git != GitHub || GİtLab** :upside_down_face: Bu uzak sunuculardan en çok bilinenleri: 851 | - [GitHub](https://github.com/) 852 | - [GitLab](https://about.gitlab.com/) 853 | - [Açık Kaynak Kod Platformu](https://kod.acikkaynak.gov.tr/explore/projects/starred) (Belki de henüz pek bilinmese de yerli ve milli bu hizmeti de listeye eklemek istedim, bence bakmakta fayda var :innocent:) 854 | 855 | ## Push - Pull Nedir? 856 | Yerel (local) makinadaki commit'leri uzak sunucuya göndermek (itmek) demektir. `git push` komutu sayesinde local commit'lerimizi uzak sunucuya gönderebiliriz. Aynı zamanda uzak sunucudaki commit'leri yerel (local) makinamıza çekmek için ise `git pull` komutunu kullanmamız gerekiyor. 857 | ### Ufak Bir Not 858 | Herhangi bir uzak sunucu ile çalışırken commit'leri `push` etmeden önce `pull` etmemiz gerekmektedir. Bunun sebebi ise farklı geliştiricilerle çalışıyorsak veya birden fazla commit varsa, commit'lerin ebeveyn (parent - child) sırasının bozulmaması gerekmektedir. 859 | 860 | Git repomuza birden fazla uzak sunucu ekleyebiliriz. İlk eklenen uzak sunucu her zaman `origin` olarak adlandırılır. `git remote` komutuyla repomuza bir uzak sunucu eklerken isimlendirmemiz mümkündür. 861 | ``` 862 | git remote add uzak-sunucu1 UZAK_SUNUCU_ADRESI 863 | ``` 864 | Ve uzak-sunucu1 adındaki uzak sunucumuza repomuzu tanımladık. Bu uzak sunucuya dosyalarımızı,commit'lerimizi `push` ederken şu komutu çalıştırabiliriz. `git push uzak-sunucu1 master` Şu manaya gelmektedir: `git push` -> localdeki commit'leri gönder, `uzak-sunucu1` -> uzak sunucu adı / hangi uzak sunucuya gönderileceği, `master` uzak-sunucu1'deki master branch'ine push et.
865 | 866 | Peki eklediğimiz uzak sunucuları nasıl göreceğiz? Bunun için ise `git remote` komutunu kullanmamız yeterlidir. 867 | ``` 868 | git remote 869 | >>> akkp # açık kaynak kod platformu 870 | origin # ilk eklediğimiz uzak sunucu (github) 871 | ``` 872 | 873 | ## GitHub ile devam edelim 874 | GitHub üzerinden bir repo açtığımızı varsayalım. Ve repo'muzu ilk açtığında bizi böyle bir ekran karşılayacaktır. 875 | ![GitHubNewRepo](./assets/1.png) 876 | 877 | Eğer hali hazırda bir Git repomuz yok ise ilk bloktaki kodlara tabi olacağız, kodlarımız başka bir uzak sunucuda ise 3. bloğa tabi olacağız. Local'de bir repomuz var fakat henüz bunu bir uzak sunucuya atmamışsak 2. bloğa tabi olacağız ki ben burada 2. blok üzerinden çalışmalarıma devam edeceğim. 878 | ``` 879 | git remote add origin https://github.com/mebaysan/Deneme.git 880 | git push -u origin master 881 | ``` 882 | Şimdi bu komutları inceleyecek olursak;
883 | `git remote add origin` -> **origin** adında bir uzak sunucuyu repomuza ekler, `https://github.com/mebaysan/Deneme.git` -> uzak sunucumuzun adresidir.
884 | `git push -u` -> local'deki commit'leri push et, `origin` -> repoma tanıttığım **origin** isimli sunucuya, `master` -> origin isimli sunucumdaki **master branch**'ine.
885 | `git remote add SUNUCU_ADI SUNUCU_ADRESI` -> bu komut yapısı ile repo'ya uzak sunucu ekleyebiliriz
886 | `git push -u SUNUCU_ADI BRANCH_ADI` -> bu komut yapısı ile istediğimiz uzak sunucuda istediğimiz branch'e local commit'leri push edebiliriz. 887 | 888 | ## Clone Nedir 889 | ![Git Clone](./assets/2.png) 890 | 891 | Projelerimizi uzak sunucuya `push` ettikten sonra, bu repoyu o uzak sunucudan herhangi bir başka sisteme çekmek için `git clone repo_adresi` komutunu clone'lamak istediğimiz repo'nun adresini argüman olarak yollayarak kullanabiliriz. Ardından uzak sunucudaki repo'muz yerel (local) sistemimize kopyalanmış olacaktır. Bu işleme **clone** denmektedir. GitHub için **clone** adresine repo'muzun detayına girdikten sonra sağ üst köşeden erişebiliriz. Ardından şu şekilde komutu kullanabiliriz. 892 | ``` 893 | git clone https://github.com/mebaysan/TemelGitElKitabi.git 894 | >>> Cloning into 'TemelGitElKitabi'... 895 | remote: Enumerating objects: 17, done. 896 | remote: Counting objects: 100% (17/17), done. 897 | remote: Compressing objects: 100% (12/12), done. 898 | remote: Total 17 (delta 4), reused 17 (delta 4), pack-reused 0 899 | Receiving objects: 100% (17/17), 63.19 KiB | 681.00 KiB/s, done. 900 | Resolving deltas: 100% (4/4), done. 901 | ``` 902 | Hayırlı olsun, uzak sunucudaki repo'muzu yerel (local) sistemimize clone'lamış (kopyalamış) olduk. 903 | 904 | # Temel Git ve GitHub Bilgileri İçin Video 905 | Temel Git ve GitHub Bilgileri İçin Hazırladığım Video'ya [buradan](https://youtu.be/RT8LFtyilsU) erişebilirsiniz. Umarım Faydalı olur. -------------------------------------------------------------------------------- /assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mebaysan/TemelGitElKitabi/7c4fc1073d4a7e815dc7da1cb9a58819ddf63c95/assets/1.png -------------------------------------------------------------------------------- /assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mebaysan/TemelGitElKitabi/7c4fc1073d4a7e815dc7da1cb9a58819ddf63c95/assets/2.png --------------------------------------------------------------------------------