Git 101

Burç Akbaş
KoçSistem
8 min readAug 8, 2019

--

TL;DR

Bu bölümde Git ile ilgili kısa bilgi verip, temel kavramlar üzerine bir özet oluşturacağız. Amacımız en basit düzeyde bilgi sahibi olup, nasıl kullanılabileceğini görmek. Derinlemesine incelemek isteyenler Scott Chacon ve Ben Straub’un Pro Git kitabını edinebilirler.

Git nedir?

Git açık kaynak kodlu, dağıtık (distributed) bir mimariye sahip olan versiyon kontrol sistemidir (VCS). Basitlik ve hız odaklıdır; CLI üzerinden her platformda rahatça çalışabilir.

Git’in en güçlü yanları;

  • Dağıtık çalışabilmesi: Sunucuya bağımlılık şart değil. Yüklenen her ortam sunucu görevi görebilir.
  • Hız odaklı tasarımı. (Easy to branch)
  • Kaynak tüketiminin düşük olması.

Git üzerinde branch açmaktan korkmayın. Git branch dosyalarını kopyalamaz, sadece referanslarını tutar.

Tarihçe

Git ilk olarak Linus Torvalds tarafından 2005 yılında Linux kernel’in geliştirmelerini takip edebilmek adına C ile yazılarak hayata geçirilmiştir. Linux çekirdeğinin farklı developer’lar tarafından geliştirilmesi konusu git’in ortaya çıkmasını hızlandırmıştır.

Nasıl çalışır?

Git’in distributed yapısı, rakip merkezileştirilmiş (centralized) ürünlere göre büyük avantaj sağlar. Neredeyse tüm işlemler yerel (local) makina üzerinde gerçekleştiğinden performansı çok daha iyidir. Çeşitli benchmark’larda en yakın rakiplerine ciddi farklar ortaya koymuştur.

Benchmarks

Bu özellikleri ile geliştirici dünyasında popülerliği hızla arttı. Stackoverflow’un her yıl düzenlediği insight’lara baktığımızda kullanım oranının ne kadar yüksek olduğunu görüyoruz.

Popularity of Git:

2017 → 69.2%

2018 → 87.2%

2019'da ise artık bir de facto standardı haline geldi.

Centralized vs Decentralized

Centralized Version Control Systems (CVCS)

Decentralized Version Control Systems (DVCS)

CVCS: Merkezileştirilmiş versiyon sistemlerini şöyle düşünebilirsiniz; örneğin bir merge isteği veya bir push (check-in) nerede yapılıyor? Eğer sorunun cevabı sunucu ise bu sistem merkezileştirilmiştir.

Örnek ürünler: Apache Subversion (SVN), Team Foundation Server, Concurrent Versions System (CVS)

Git yöneteceği dosyaları Repository’lerde tutar. Repository’i fiziksel dosyalar gibi düşünebiliriz. Oluşturulan branchler fiziksel olarak kopyalanmaz, sadece ilgili referanslar tutulur; bu kolay ve performanslı branch yönetimini sağlamaktadır.

Temel Komutlar

git config

Git repository veya global bilgilerin (username & password by Repository or Global) yönetilmesinde yardımcı olur.

Examples:--user config'inin mail adreslerini dönergit config user.email--global settingsgit config --global user.email "your_email@example.com"

git clone

Var olan bir git repository’sine erişmek, kopyalamak için kullanılır. Bir projeyi indirmek için clone’la başlarız. Erişim çeşitli protokollerle gerçekleşir; ssh, http

Examples:--clone a repositorygit clone git://git.kernel.org/pub/scm/.../linux.git

clone, var olduğunuz klasör üzerine repository ismi ile aynı yeni bir klasör açar ve dosyaları buraya kopyalar. Örneğin bu işlemi ismi WebSample olan bir repository’de ve dizin olarak C:\Git\ altında yapıyor olsaydık C:\Git\WebSample isimli bir klasör oluşturup altına dosyaları çekecekti.

git init

Yeni ve boş bir repository oluşturup, git’in çalışabilmesi için gerekli olan ayarlamaları yapar. Yeni bir projeye başlarken init ile başlarız.

git status

Git üzerinde dosyaların çeşitli durumları vardır. “Tracked, untracked, staged, modified, added gibi..” dosyaların hangi durumda olduğu, hangi branch üzerinde çalıştığımız gibi bilgilere erişmemizi sağlar.

git pull

Çalışılan repository’nin bilgilerini ve yapılan son değişiklikleri local branch’e çeker, merge eder. Git pull içinde fetch ve merge barındırır.

pull → fetch + merge

git fetch

Çalışılan repository’nin bilgileri (referanslarını) günceller. Git pull’dan farklı; bilgileri çeker fakat merge yapmaz.

git add

Dosyaların durumunu (status) staged yapar. Git’in commit yapabilmesi için dosyaları hazırlar.

Examples:-- tüm dosyaları stage durumuna getirirgit add *-- spesifik dosyaları stage durumuna getirirgit add hede.txt

git commit

Yapılan değişiklikleri tek bir commit için sıkıştırır ve repository’e eklenecek hale getirir. Her commit’in bir hash adresi vardır; git dosyaları kıyaslarken bu commit hash’ler üzerinden ilerler.

Examples:--commit'i mesajı ile birlikte oluştururgit commit -m "(WorkItemId|IssueId): hede feature reordered for client calls"

git push

Uzak sunucuya değişikliklerin gönderildiği komuttur. Push yapılmadan uzak sunucuda hiç bir değişiklik yansımaz, tüm işlemler local ortamda gerçekleşir. Performanslı olmasının sebebi bu tip tasarım yaklaşımlarıdır.

Examples:-- origin isimli remote'daki master branch'ine push yapar, dosyaları gönderir.git push origin master-- hangi branch'de iseniz branch ismi vermeden git push ile dosya push'layabilirsiniz.git push-- remote üzerinden branch silmegit push -d origin myFeature

git merge

İki veya daha çok commit’i bir araya getirir, birleştirir. Bu işlemin yapılış sırası şöyledir: A ve B isimli iki branch’imiz olsun. A’ ve B’ ise geldikleri son halleri, değişiklik yapılmış halleri.

Merge komutu ile git aşağıdaki üç commit’i tespit eder:

  • İki branch’in ortak commit’i: A’dan yeni branch alındığı an; yani B.
  • Branch’lerin son commit’leri: A’ ve B’

Git bu üç commit’i birleştirir.

Fast-Forward Merge: Feature branch’iniz master’a merge olacağı anda eğer master üzerinde bir değişiklik (commit) olmamışsa, git varsayılan olarak master hattının son commit hash’i olarak, feature branch’in hash’ini alır. Bu duruma Fast-Forward Merging denir.

Bu işlem sonrasında sanki değişiklikler master branch’inde yapılmış gibi bir history oluşur. Geçmiş history’i daha anlaşılabilir tutmak için merge işlemi sırasında git’e “ — no-ff” opsiyonu ile gidilir; bu git’in fast-forward yapmamasını ve yeni bir merge commit ile ilerlemesini sağlar.

https://nvie.com/posts/a-successful-git-branching-model

git rebase

Merge gibi farklı commitleri bir araya getirir. Merge’den farkı rebase uygulandığı branch’in üzerinde yeni bir merge commit oluşturmaz.

- Önce her iki branch’inde ortak commit’ini belirler. (Bir önceki örnekten A ve B üzerinden gidelim)

- Sonrasında A → A’ arasını çıkarır, geçici bir yere taşır.

- Yeni branch’i B → B’ arasını ana hatta çeker

- Geçici olarak taşıdığı A → A’ arasını tekrar ana hatta ekler.

git branch

Yeni branch oluşturmak, listelemek veya silmek için kullanılır.

Examples:-- branch bilgilerini gösterirgit branch -a-- yeni branch oluştururgit branch myFeature-- branch'i local'den silergit branch -d myFeature

git checkout

Branch’ler arasında geçiş için kullanılır. Aynı zamanda dosyaların durumlarını da değiştirebiliriz.

Examples:-- branchler arası geçişi sağlar; dev branch'ine geçmek içingit checkout dev-- local tracked durumundaki dosyaları geri alır.git checkout *

git clean

Local untracked durumundaki dosyaları siler, geri alır.

Examples:-- hangi dosyaların silineceğini gösterirgit clean -n-- silme işlemi -f ile force edilir.git clean -fgit clean -f -d

git stash

Yapılan değişiklikleri geçici olarak saklamak için kullanılır. (TFS → shelve)

stash, branchler arasında geçiş yapacağımız zaman çok kullanışlı oluyor. Git branch dosyalarını kopyalamadığı için örneğin; dev branch’inde bir değişiklik yaptınız fakat işiniz bitmedi ve master branch’ine bir hotfix atmanız gerekiyor fakat dev üzerindeki değişiklikleri kaybetmek istemiyorsunuz.

Bu durmda dev kodunu stash’a alıp, master’a geçip hotfix’i uyguladıktan sonra tekrar “stash apply” ile kaldığınız yerden devam edebilirsiniz.

Examples:git status# On branch master# Changes to be committed:#   (use "git reset HEAD <file>..." to unstage)##      modified:   index.html## Changes not staged for commit:#   (use "git add <file>..." to update what will be committed)##      modified:   lib/simplegit.rb#git stashSaved working directory and index state \"WIP on master: 049d078 added the index file"HEAD is now at 049d078 added the index file(To restore them type "git stash apply")git status# On branch masternothing to commit, working directory cleangit stash liststash@{0}: WIP on master: 049d078 added the index filestash@{1}: WIP on master: c264051 Revert "added file_size"stash@{2}: WIP on master: 21d80a5 added number to loggit stash apply# On branch master# Changes not staged for commit:#   (use "git add <file>..." to update what will be committed)##      modified:   index.html#      modified:   lib/simplegit.rb#

git remote

Uzak sunucunun yönetimini sağlar. Remote ismi, branch listeleri, repository bilgileri gibi bilgilere erişebiliriz.

git remote show origin: Genel olarak branchler ve repository hakkında bilgi verir. Yeni bir branch veya repo yarattığınız zaman sıklıkla kullanıp, remote üzerinde ne gibi değişiklikler olduğunu takip edebilirsiniz.

git reset

Git’in her branch için dosya kopyalamadığından bahsetmiştik. Gerekli bilgileri tuttuğu bölüme HEAD ismi verilir. Git reset ile HEAD local değişikliklerden geri alınabilir (Undoing) veya belirli bir commite çekilebilir.

Local branch’te yapılan değişiklikleri (git add) geri almak için “git reset HEAD — hard” komutu kullanılabilir. Sonrasında kontrol için “git status” ile geri alındığını gözlemleyebilirsiniz.

Commit’leri geri almak için ise “git reset HEAD~” → Bu status’ü “not staged” e çekecektir. Buradan da geriye gitmek için “git checkout *” ile başladığınız noktaya dönebilirsiniz.

git diff

Commitler arasındaki farkları hesaplar, gösterir.

git log

Commit loglarını gösterir. Çok detay var burada ama sonra :)

git rm

Linux kullananlar tahmin edecektir; silme işlemleri için kullanabiliriz.

Examples:--commitli dosyalari silme *.dll *.pdb *.cachegit rm -r --cached */obj/*.dllgit rm -r --cached */obj/*.pdbgit rm -r --cached */obj/*.cache

Eğer git’e “.gitignore” dosyasını eklemeden push yaptıysanız, .dll veya .pdb gibi dosyaları da git’e track’lemesi için iletmişsiniz demektir. Bu da her build yaptığınızda dll’lerin “modified” durumuna geçmesine neden olur. Bu sorunu çözmek için commitli dosyaları silmeniz gerekir.

Hands-on: Örnek uygulama

Git’in bir çok komutu olmasına karşın toplamda 5–6 komut ile geliştirme yapılabilir. DevOps repo’su altında bir örnekle hızlıca üzerinden geçelim;

Yeni bir uygulamayı var olan repo’ya göndermek

STATUS → INIT → REMOTE ADD → ADD → COMMIT → PUSH

git initgit remote add origin https://{VCS-URL}/{REPONAME}.gitgit add .git commit -m "Initial commit"git push -u origin master

Var olan projeyi indirip, üzerinde çalışmak

CLONESTATUSADDCOMMITPUSH

git clone https://{VCS-URL}/{REPONAME}.gitcd {REPONAME}-- start developmentgit add .git commit -m "feature completed"git push

Kodların ilk defa gönderilmesi

Daha önceden bir SCM (Azure DevOps, GitHub, Bitbucket vb..) üzerinden oluşturulmuş repository’e push yapmak üzere .NetCore ile yeni bir proje yaratıyorum. Bir sonraki adımda clone ile düzgün bir yere taşındığını göstermek adına, projeyi masaüstünde, yeri önemli olmayan bir klasörde oluşturuyorum.

Git CLI, Windows CLI, PowerShell gibi bir command line üzerinden klasöre erişiyorum.

Projeyi oluşturalım

dotnet new mvc -au None -f netcoreapp2.0

Bir üst klasöre geçip init’leyip göndermeye başlıyoruz.

git init “.git” isimli, görünmez bir klasör oluşturur ve git ile ilgili verileri burada bulundurur.

Sırasıyla remote’a ilgili repository’i ekleyip, add, commit ve push ile dosyaları karşıya gönderiyorum.

SCM (Azure DevOps Server bu seferlik) üzerinden kontrol ettiğimde

--

--

Burç Akbaş
KoçSistem

A geek, curious, guitar player, motorcycle rider and a tennis lover who likes to code - Design, Art, Technology & Music