Her komut ile ilgili yardımı komut satırından alabilirsiniz:
git help
git help add # git-add hakkında yardım
git help merge # git-merge hakkında yardım
git help KOMUT
git --version # kullandığınız git versiyonu
3 tip konfigürasyon şekli var. local
, global
, system
.
Repository bazında konfigürasyon. İlgili dizin altında geçerlidir.
/repo/dizini/.git/config
git config --local user.email "kiş[email protected]"
Kullandığınız bilgisayar bazında, sadece kendi kullanıcınız seviyesinde tüm repo’lar için geçerli olandır.
~/.gitconfig
git config --global user.name "Ad Soyad"
git config --global user.email "adsoyad@şirketeposta.com"
İlgili bilgisayardaki tüm kullanıcıları etkileyen konfigürasyondur. Örneğin build işlemleri için ayrı bir bilgisayar var ve her user buraya push edebiliyor.
/etc/gitconfig
git config --system color.ui true
Yaptığınız tüm konfigürasyon ayarını örnekteki gibi kontrol edebilirsiniz:
git config --global user.name # Girdiğiniz değeri verir
git config --global user.email # Girdiğiniz değeri verir
ya da ~/.gitconfig
dosyasını açıp içine bakabilirsiniz.
git
log için e-posta adresinize ve adınıza ihtiyaç duyar. Bu bakımdan önce
bu ayarları yapmak gerekiyor:
git config --global user.name "Adınız Soyadınız"
git config --global user.email "E-Posta Adresiniz"
git init PROJE_ADI # PROJE_ADI isminde bir dizin oluşturur.
# Diğer yöntem
mkdir /dizin/yolu/proje_adi
cd /dizin/yolu/proje_adi
git init
git status # uzun versiyon
git status -s # kısa versiyon
git status -sb # branch’leri de göster
git add DOSYA_ADI # ya da
git add . # tüm modifiye edilenler ve takip dışında olanları ekle!
git add -u # tüm silinen -deleted- dosyaları ekle
git commit -m "Mesaj"
git commit -am "update" # Track edilen, modiye olmuş dosyalar içindir!
git commit --amend # Son commit mesajını düzenlemek için
git commit --amend -m "Yeni mesaj" # Son commit mesajını yeniden girmek için
git reset --soft HEAD^
# Son commit’i undo yapmak / HEAD’i geri almak
# Dikkat edin, bu soft olduğu için oluşmuş dosyaları silmez!
git reset --hard HEAD^
# Son commit’i undo yapmak / HEAD’i geri almak
# hard olduğu için aynen bir önceki yere döner ve oluşmuş dosya vs bırakmaz.
git log # uzun versiyon
git log --graph --decorate --oneline
git log --graph --decorate --oneline --all
git log --graph --decorate --pretty=oneline --abbrev-commit --all
git log --graph --decorate --oneline --pretty=format':%C(yellow)%h%Cblue%d%Creset %s %C(white) %an, %ar%Creset'
Aynı komut-satırındaki gibi rm
ve mv
komutlarını başına git
koyarak
kullanıyoruz:
git rm dosya.txt
# dosya.txt’yi silmek için
git mv dosya1.txt dosya_yeni1.txt
# dosya1.txt’nin adını dosya_yeni1.txt yaptık
İnteraktif ekleme.
@wip
Çeşitli durumlarda (commit, merge, rebase vb...) ilgili konu için mesaj yazmak
gerekir. Bunların başında commit mesajı gelir. Text Editor olarak hangi
tool’u kullanmak istiyorsanız shell environment’ınızda $EDITOR
değişkenini
ya da $GIT_EDITOR
değişkenini ayarlamanız gerekir.
export $EDITOR="mate -w" # TextMate
export $EDITOR="emacs" # Emacs
export $EDITOR="vim" # Vim
export $EDITOR="atom --wait" # Atom
export $EDITOR="subl -n -w" # Sublime Text
Bu ayarlamalardan sonra, önerilen:
- İlk satırda (50 karakteri geçmeden) özet bilgi vermek,
- Eğer detay varsa, bir boş satır bırakıp detaylı bilgiyi vermek.
Örnek commit
ekranı:
Sitemizin yeni bölümü için index sayfası oluşturuldu.
Yaptığımız projede, ABCD bölümü için yeni statik bir html sayfası
gerekiyordu, bunun için index.html dosyasını oluşturdum ve
front-end’i yazacak arkadaşlara gerekli bilgiyi verdim.
Yeni bir paragdı aynı markdown kullanır gibi kullandım.
- Bu şekilde list item yaptım,
- Araya mutlaka 1 satır boşluk verdim liste için.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
#
# Initial commit
#
# Changes to be committed:
# new file: index.html
#
Eğer git commit
dedikten sonra, gelen ekranda hiçbir şey yazmadan çıkarsanız
commit yapmaktan vazgeçmiş sayılırsınız:
Aborting commit due to empty commit message.
mesajını alırsınız. #
ile başlayan satırlar yorum satırıdır, kaydedilmez.
git remote -v # fetch/push bilgisi
git remote show origin # origin ile ilgili bilgi
git remote add İSİM URL # Uzaktaki bir repo...
git remote remove İSİM
git remote prune origin
# remote’daki silinmiş branch’ler bazen local’de görünür, bunu fixler...
git clone URL
git clone URL PROJE_ADI
git clone --mirror URL [İSİM]
# ilgili git reposunu bare-repo olarak kopyalarsınız.
Üzerinde çalıştığınız yerel repo’yu artık uzaktaki bir yere (GitHub, BitBucket ya da
kendi sunucunuza) atmak için remote
bilgisi eklemeniz gerekir.
git remote add origin [email protected]:vigo/my-custom-textmate1-bundle.git
git push -u origin master # ya da
git push -u origin --all # origin’e local’deki tüm branch’leri push et.
SSH ile bağlandığınız sunucunuzda (git de kurulu olmalı);
cd /kendi/git/repom/
mkdir proje.git
cd proje.git
git init --bare # burası artık bare-repo oldu!
git repo-config core.sharedRepository true # makinedeki diğer user’lar da kullanabilir
Şimdi, kendi makinenizde;
git clone git+ssh://sunucum/kendi/git/repom/proje.git
şeklinde kullanabilirsiniz.
@wip
@wip
Aynı konfigürasyon dosyası gibi local
ya da global
olabilir. Repo bazında
kullanmak için (local), proje dizini içinde .gitignore
dosyası olurşturmak
yeterlidir. Örnek:
# .gitignore
.DS_Store
.Spotlight-V100
.Trashes
.sass-cache
.bundle
*.log
Eğer daha genel bir kullanım istiyorsanız önce global konfig’e ek yapmanız
gerekir. Örnekte bu dosyanın ~/.gitignore
olduğunu varsayıyorum.
git config --global core.excludesfile ~/.gitignore
~/.gitignore
dosya içine yazılanlar takip dışı kalacaktır. Buradaki sıralama
çok önemlidir. Örneğin *.log
yani tüm log dosyalarını takip dışı bırakmak
ama sadece test.log
dosyasını takipte tutmak istiyorsunuz:
# .gitignore
*.log
!test.log
Önce *.log
ile tipi .log
olan tüm dosyalar takip dışında kalacak, sonraki
satırda ise !
sayesinde test.log
dosyası bu kuralın dışında kalacak. Eğer
bu sıra ters olsaydı, git
, önce; test.log
dosyasını kuralın dışında tutmaya
çalışacak, zaten *.log
gibi bir direktifi görmediği için bunu pas geçecek,
sonraki satırda ise tüm *.log
dosyalarını takip dışı alacak bu yüzden de
test.log
da takip dışı kalacaktı!
Varolan yerel/uzak branch’ler hakkında bilgi almak için;
git branch # İçinde bulunduğun branch
git branch -v # branch kısa_sha commit_mesajı
git branch -va # remote’lar dahil; branch kısa_sha commit_mesajı
Ayrıca;
git checkout BRANCH_ADI # BRANCH_ADI branch’e geçmek
için kullanılır.
git branch YENİ_BRANCH
# o an içinde bulunduğunuz branch’den yeni bir branch oluşturmak
git checkout YENİ_BRANCH
# yeni oluşturduğunuz branch’e geçiş
# ya da
git checkout -b YENİ_BRANCH
# YENİ_BRANCH oluştur ve içine gir.
Hemen örnek bir repo yapalım:
git init example_repo
cd example_repo/
touch README.md
git commit -m "init"
git log log --graph --decorate --oneline
Log bize, an itibariyle bulunduğumuz branch’in master
olduğunu gösterir.
Bizi ifade eden şey HEAD
dir. HEAD
neredeyse biz an itibariyle orada
işlem yapıyoruz anlamına gelir.
Tam anlamıyla HEAD aktif bulunduğunuz branch’deki son commit’i gösteren bir işaretçidir.
* b3e825d (HEAD, master) init
Şimdi, test için feature1
branch’i açalım:
git checkout -b feature1
touch feature1.txt
git add .
git commit -m "feature1"
Şimdi log’a bakalım:
git log --graph --decorate --oneline
* 03741e9 (HEAD, feature1) feature1
* b3e825d (master) init
Bulunduğumuz yer (HEAD) feature1
branch’i. Şimdi tekrar master
branch’e
geçiyoruz ve log’a baktığımızda aynen ilk andaki gibi;
git log --graph --decorate --oneline
* b3e825d (HEAD, master) init
gördük. Şimdi feature1
branch’ini master’a merge
edip, oradaki yeni özellikleri
ana branch’imiz olan master
a aktarmak istiyoruz. An itibariyle, master
da
hiçbir değişiklik yapmadığımız için, git
bakacak ve direk ilere sarma yöntemi
yani Fast-Forward ile olduğu gibi feature1
i master
’ın önüne takacak:
git merge feature1
Updating b3e825d..03741e9
Fast-forward
feature1.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 feature1.txt
Şimdi log’a bakalım:
git log --graph --decorate --oneline
* 03741e9 (HEAD, master, feature1) feature1
* b3e825d init
Hem master
hem de feature1
aynı noktada duruyor. merge
öncesinde, master
branch’de hiçbir değişiklik olmadığı için git
strateji olarak Fast-Forward’ı
uygun gördü. Şimdi feature1
ile işimiz kalmadığı için silebiliriz:
git branch -d feature1
git log --graph --decorate --oneline
* 03741e9 (HEAD, master) feature1
* b3e825d init
Aynı örnekten devam edelim. feature2
branch’i yapalım:
git checkout -b feature2
touch feature2.txt
git add .
git commit -m "feature2.txt eklendi"
# şimdi master branch’e geçip orada da değişiklikler yapacağız
git checkout master
touch sample.txt
git add sample.txt
git commit -m "sample.txt eklendi"
git merge feature2
Karşımıza ilgili commit mesajı yazacağımız ekran geldi. Fast-Forward esnasında böyle bir olayla karşılaşmamıştık. Mesajı yazıp kaydettik;
Merge made by the 'recursive' strategy.
feature2.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 feature2.txt
Şimdi log’a bakalım
git log --graph --decorate --oneline
* 0d0bc24 (HEAD, master) Merge branch 'feature2'
|\
| * 4606e77 (feature2) feature2.txt eklendi
* | f8f4d33 sample.txt eklendi
|/
* 03741e9 feature1
* b3e825d init
Buradan görülen 4606e77
ile f8f4d33
birleşti ve 0d0bc24
commit’i
oluştu. Şimdi feature2
ile işimiz bittiği için silelim:
git branch -d feature2
git log --graph --decorate --oneline
* 0d0bc24 (HEAD, master) Merge branch 'feature2'
|\
| * 4606e77 feature2.txt eklendi
* | f8f4d33 sample.txt eklendi
|/
* 03741e9 feature1
* b3e825d init
Fast-Forward’da sanki neyin neyle birleştiği kayboluyor gibi bir durum
çıkıyor ortaya. Bu bakımdan, merge
sırasında --no-ff
yani
No Fast Forward yapmak faydalı oluyor:
git merge --no-ff BRANCH_NAME
İlgili commit’in başlangıç noktasını değiştirmek, yani base commit’i değiştirmek,
yeniden set etmek yani rebase etmek! Bu kısmı lütfen git rebase -i
ile
yani Interactive Rebasing ile karıştırmayın o tamamen farklı bir konsept...
Amaç, karışık görünen log’u daha anlaşılır şekilde göstermek. Şimdi elimizde
içinde sadece index.html
olan bir repo olsun:
git log --graph --decorate --oneline
* b9b3a5b (HEAD, master) initial
Şimdi yeni bir özellik eklemek için feature1
branch’i açıp içine dosya
ekleyelim:
git checkout -b feature1
touch feature1.html
git add .
git commit -m "feature1 tamamlandı"
$ git log --graph --decorate --oneline
* cbb078b (HEAD, feature1) feature1 tamamlandı
* b9b3a5b (master) initial
Şimdi, master
’a geçip başka bir özellik ekleyelim. Düşününki feature1
başka sizin tarafınızdan, feature2
de başka bir developer tarafından
yapılıyor:
git checkout master
git log --graph --decorate --oneline
* b9b3a5b (HEAD, master) initial
git checkout -b feature2
touch feature2.html
git add .
git commit -m "feature2 tamamlandı"
git log --graph --decorate --oneline
* dec92b9 (HEAD, feature2) feature2 tamamlandı
* b9b3a5b (master) initial
Normal şartlarda master
’a geçip önce feature1
’i merge, sonra da feature2
’yi
merge etseydik log şu şekilde görünecekti:
git merge --no-ff feature1
git merge --no-ff feature2
git log --graph --decorate --oneline
Log’a baktığınızda, sırayla önce feature1 sonra feature2 nin merge yapıldığını görüyoruz:
* 489999b (HEAD, master) Merge branch 'feature2'
|\
| * dec92b9 (feature2) feature2 tamamlandı
* | 69f74c8 Merge branch 'feature1'
|\ \
| |/
|/|
| * cbb078b (feature1) feature1 tamamlandı
|/
* b9b3a5b initial
Aslında gayet karmaşık bir history durumu var. Halbuki şu şekilde olsa:
git checkout master
git merge --no-ff feature1
git branch -d feature1 # işi biten branch silindi
git checkout feature2
git rebase master # feature2’in base branch’i master oldu!
git checkout master
git merge --no-ff feature2 # feature2’in değişiklikler master’a geçti
git branch -d feature2 # işi biten branch silindi
git log --graph --decorate --oneline
* fb6d3be (HEAD, master) Merge branch 'feature2'
|\
| * 1eb8d24 feature2 tamamlandı
|/
* 21325b2 Merge branch 'feature1'
|\
| * cbb078b feature1 tamamlandı
|/
* b9b3a5b initial
Başka bir değişle, ilk başta şu şekilde duran commit yapısı var, HEAD, commit1’deyken yeni bir branch oluşturulup, hem master’da hem de yeni oluşturulan branch’de development devam etmiş.
---master---
:
: branch
commit1 -------------> commit x1
: :
commit2 commit x2
:
commit3
Daha sonra bu yeni branch, master’a rebase edilmiş ve aşağıdaki yapı oluşmuş:
---master---
:
:
commit1
:
commit2
:
commit3
: rebase
: ----------------> commit x1
:
commit x2
ve son olarak yeni branch, master’a merge edilmiş ve lineer history elde edilmiş.
---master---
:
:
commit1
:
commit2
:
commit3
: ------- m
commit x1 e
: r
commit x2 g
e
@wip
Release versiyonu çıkartmak ya da o anın bir snapshot’ını (kopyasını) almak için kullanılır.
git tag # var olan tag’leri listeler
git tag VERSIYON_MAJOR_MINOR_PATCH # yeni versiyon çıkartmak
git tag v0.0.1
git tag -a v0.0.1 -m "Başlangıç versiyonu" # commit mesajı ile beraber
tag
hakkında bilgi:
git show v0.0.1
tag v0.0.1
Tagger: Uğur Özyılmazel <[email protected]>
Date: Tue Feb 17 22:25:04 2015 +0200
Başlangıç versiyonu
commit 0d0bc24bc72d46bf9f1ca7d64fd250edf63ccc9f
Merge: f8f4d33 4606e77
Author: Uğur Özyılmazel <[email protected]>
Date: Tue Feb 17 21:57:59 2015 +0200
Merge branch 'feature2'
gibi...
git describe # en son yapılan tag’i göster
Değişiklikleri geçici olarak kaydetmek için kullanılır. Bitmemiş işi commit etmemek gerekiyor.
git stash # yerel değişiklikleri saklar / zulalar :)
git stash list # listeler
git stash apply # stash listesinden silmeden saklı olanı geri getirir.
git stash apply stash@{1} # stash@{1}’i devreye al
git stash clear # stash’deki komple uçurur / siler
git stash pop # apply gibi ama ilgili stash’i listeden drop eder
# Dropped refs/stash@{0} (74b47bb468379704997d5bb944661f0ac7d4aaad)
# gibi...
git stash save "MESAJINIZ"
Örnekten devam edelim. Önce index.html
dosyasını oluşturalım ve çeşitli
düzenlemeler yapalım:
touch index.html
git commit -m "index.html dosyası eklendi"
echo "merhaba" > index.html
git diff
diff --git a/index.html b/index.html
index e69de29..e995d8e 100644
--- a/index.html
+++ b/index.html
@@ -0,0 +1 @@
+merhaba
+merhaba
: "merhaba" eklendi anlamında. index.html
de bir-iki değişiklik
daha yapıp:
git diff
diff --git a/index.html b/index.html
index df1f22a..c771688 100644
--- a/index.html
+++ b/index.html
@@ -1,2 +1,2 @@
merhaba
-dünya
+insanlar
-dünya
: "dünya" çıktı, +insanlar
: "insanlar" eklendi... eğer bakarsak
dosyaya:
cat index.html
merhaba
insanlar
yazdığını görürüz. Commit edelim:
git status -s
M index.html # M: Modified anlamında, yani değişiklik var.
git add .
git commit -m "index.html değiştirildi."
git status
On branch master
nothing to commit, working directory clean
Şimdi yeni bir satır daha ekleyip diff
bakalım:
echo "commodore 64" > index.html
git status -s
M index.html
git add .
# şimdi diff bakalım
git diff
# hiçbir şey gelmedi, çünkü artık değişiklik staged durumda
# bunun için --staged kullanmamız gerekir
git diff --staged # ya da
git diff HEAD # pointer’ın durduğu yerdeki durum
diff --git a/index.html b/index.html
index c771688..17290c0 100644
--- a/index.html
+++ b/index.html
@@ -1,2 +1 @@
-merhaba
-insanlar
+commodore 64
Şimdi tekrar değişiklik yapalım. Bir satır daha ekleyelim, halen commit yapmadık unutmayın!
echo "amiga 1200" > index.html
git status -s
MM index.html
# İlk M: Modified (Staged)
# İkinci M: Modified (Unstaged)
# Yani aynı dosyada hem staged hem de unstaged değişiklikler var :)
# şimdi şunları deneyin farkı görün:
git diff --staged # staged
git diff # unstaged
git diff HEAD # staged + unstaged
git diff --stat # sadece özet (summary) diff
# şimdi;
git add .
git status -s
M index.html
git commit -m "index değiştirildi"
Diğer kullanım şekilleri:
git diff --staged DOSYA
git diff --cached
git diff --cached DOSYA
git diff HEAD
# son commit ile şu anki durum arasında diff
git diff HEAD^ # son commit’in parent’ı
git diff HEAD^ HEAD # son commit’le bir öncesini
git diff HEAD^^ # son commit’in grand parent’ı
git diff HEAD~5 # 5 commit önce
git diff HEAD^..HEAD # 2.en son commit ile son commit arası
git diff SHA..SHA # İki HASH arası
git diff BRANCH BRANCH # İki branch’i diff’le
git diff BRANCH...master # BRANCH’in başladığı tarihten itibaren
# master’daki değişikliği göster
git diff --since=1.week.ago --until=1.minute.ago
# 1 hafta öncesi ile son 1 dakika arası
git diff HEAD~2 HEAD
# iki commit önce ile son commit arasındaki diff
git diff HEAD~2:DOSYA HEAD:DOSYA
# iki commit önce ile son arasındaki diff, DOSYA bazında...
git diff --diff-filter=MRC
# Modification, Rename, ve Copy haricini gösterme
git diff --name-status
# sadece değişen dosyanın adını göster, aynı git status gibi...
git diff -R
# reverse yani çıktıyı tersten göster
@wip
git config --global pack.windowMemory "100m"
git config --global pack.SizeLimit "100m"
git config --global pack.threads "1"
git config --global tar.tar.xz.command "xz -c"
git config --global push.default current
git config --global apply.whitespace nowarn
# chmod / filemod değişikliklerini ignore et!
git config --global core.filemode false
Uzaktakileri rename
etmek yerine silip, yenisini push ediyoruz.
git branch -d BRANCH_ADI # local branch’i sil
git push origin :BRANCH_ADI # remote branch’i sil
git branch -m <ESKİ_BRANCH> <YENİ_BRANCH> # local rename
git tag -d TAG # local tag’i sil
git ls-remote --tags # remote’daki tag’leri listele
git push origin :refs/tags/TAG # remote tag’i sil
git tag YENİ_TAG ESKİ_TAG # local rename
Tüm revizyon kontrol hareketi buradan görüntülenir. git’in en büyük özelliği, hiçbirşeyi kaybetmemenizdir!
git reflog
@wip
Genel olarak --soft
opsiyonu, hiçbirşeyi silmeden, değişiklikleri kaybetmeden
anlamındadır. --hard
ise, adından da anlaşılacağı gibi, hiç acımadan,
gözünün yaşına bakmadan kafayı kopartır.
Unutmayin ki, hiçbir zaman, hiçbirşey asla silinmez. Her daim reflog
imdada
yetişir!
git reset --soft HEAD^
# son yaptığın commit’i geri al, eksik birşeyler varsa ekle,
# git commit --amend -m "unuttuğum file" gibi ek bişi yapmadan
# tamamla...
git reset --soft HASH
# bu versiyona (HASH’e) dönüldü, yapılan değişiklikler de korundu.
git reset --hard HEAD
# yaptığın herşeyi geri al, değişiklikleri de uçur.
git reset --hard HEAD^
# son commit’i ve tüm değişiklikleri geri al!
git checkout -- DOSYA
# DOSYA üzerinde yaptığınız değişiklikleri geri alır
git checkout HEAD DOSYA
# DOSYA’nın son commitlenmiş haline döner
git checkout master~2 DOSYA
# DOSYA’nın master branch’deki 2 commit önceki haline döner
git rm --cached DOSYA
git reset HEAD FILE
# bir dosyayı unstage etmek, "git add DOSYA" dediniz ve vazçetiniz...
git checkout HASH FILE # belli bir commit’deki DOSYA’ya dönmek
# git checkout 550af33 test.txt
git checkout HASH^ -- DOSYA
# ilgili DOSYA’yı istediğin HASH’ten geri getir,
# git rm ile sildiğin bir dosyayı geri getirmek için :)
git archive -o ~/Desktop/latest.zip HEAD
# son durumu zip olarak yedekle
git archive -o ~/Desktop/latest.tar.gz HEAD
# son durumu tar.gz olarak yedekle
git archive -o ~/Desktop/latest.tar.gz --prefix=dizin_adi/ HEAD
# tar’ı açarken dizin_adi/ altında açar...
git bundle create ~/Desktop/repo.bundle master
# repo’yu klonla
git clone ~/Desktop/repo.bundle -b master ~/projects/xyz
# klon’u geri aç
git blame DOSYA --date short
# kim commit etmiş göster.
gitk # git ile gelen gui tool
gitk --all
git show tag # svn log --limit 1 URL
bu satır sanırım ,
git show v1.0 olacak hocam