-
1. Başlangıç
- 1.1 Sürüm Denetimi
- 1.2 Git’in Kısa Tarihçesi
- 1.3 Git Nedir?
- 1.4 Komut Satırı
- 1.5 Git’i Yüklemek
- 1.6 Git’i İlk Defa Kurmak
- 1.7 Yardım Almak
- 1.8 Özet
-
2. Git Temelleri
-
3. Git Dalları
- 3.1 Dallar
- 3.2 Kısaca Dallandırma ve Birleştirme Temelleri
- 3.3 Dal Yönetimi
- 3.4 İş Akışı Dallandırması
- 3.5 Uzak Dallar
- 3.6 Yeniden Temelleme (rebase)
- 3.7 Özet
-
4. Bir Sunucuda Git Kurma
- 4.1 İletişim Kuralları (Protocols)
- 4.2 Bir Sunucuda Git Kurma
- 4.3 SSH Ortak Anahtarınızı Oluşturma
- 4.4 Sunucu Kurma
- 4.5 Git Cini (Daemon)
- 4.6 Akıllı HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Üçüncü Taraf Barındırma (Hosting) Seçenekleri
- 4.10 Özet
-
5. Dağıtık Git
- 5.1 Dağıtık İş Akışları
- 5.2 Projenin Gelişiminde Rol Almak
- 5.3 Bir Projeyi Yürütme
- 5.4 Özet
-
6. GitHub
- 6.1 Bir Projeye Katkıda Bulunmak
- 6.2 Proje Bakımı
- 6.3 Kurumsal Yönetim
- 6.4 GitHub’ı otomatikleştirme
- 6.5 Özet
-
7. Git Araçları
- 7.1 Düzeltme Seçimi
- 7.2 Etkileşimli İzlemleme (Staging)
- 7.3 Saklama ve Silme
- 7.4 Çalışmanızı İmzalama
- 7.5 Arama
- 7.6 Geçmişi Yeniden Yazma
- 7.7 Reset Komutunun Gizemleri
- 7.8 İleri Seviye Birleştirme
- 7.9 Rerere
- 7.10 Git’le Hata Ayıklama
- 7.11 Alt Modüller
- 7.12 Demetleme (Bundling)
- 7.13 Git Nesnesini Değiştirme
- 7.14 Kimlik Bilgisi Depolama
- 7.15 Özet
-
8. Git’i Özelleştirmek
- 8.1 Git Yapılandırması
- 8.2 Git Nitelikleri
- 8.3 Git Kancaları (Hooks)
- 8.4 Bir Örnek: Mecburi Git Politikası
- 8.5 Özet
-
9. Git ve Diğer Sistemler
- 9.1 İstemci Olarak Git
- 9.2 Git’e Geçiş
- 9.3 Özet
-
10. Dahili Git Ögeleri
- 10.1 Tesisat ve Döşeme (Plumbing ve Porcelain)
- 10.2 Git Nesneleri
- 10.3 Git Referansları
- 10.4 Packfiles
- 10.5 Refspec
- 10.6 Transfer Protokolleri
- 10.7 Bakım ve Veri Kurtarma
- 10.8 Ortam Değişkenleri
- 10.9 Özet
-
A1. Ek bölüm A: Diğer Ortamlarda Git
- A1.1 Görsel Arayüzler
- A1.2 Visual Studio ile Git
- A1.3 Visual Studio Code ile Git
- A1.4 Eclipse ile Git
- A1.5 Sublime Text ile Git
- A1.6 Bash ile Git
- A1.7 Zsh ile Git
- A1.8 PowerShell ile Git
- A1.9 Özet
-
A2. Ek bölüm B: Git’i Uygulamalarınıza Gömmek
- A2.1 Git Komut Satırı
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Ek bölüm C: Git Komutları
- A3.1 Kurulum ve Yapılandırma Komutları
- A3.2 Proje Oluşturma Komutları
- A3.3 Kısaca Poz (Snapshot) Alma
- A3.4 Dallandırma ve Birleştirme Komutları
- A3.5 Projeleri Paylaşma ve Güncelleme Komutları
- A3.6 İnceleme ve Karşılaştırma Komutları
- A3.7 Hata Ayıklama (Debugging) Komutları
- A3.8 Yamalama (Patching)
- A3.9 E-Posta Komutları
- A3.10 Harici Sistemler
- A3.11 Yönetim
- A3.12 Tesisat (Plumbing) Komutları
10.6 Dahili Git Ögeleri - Transfer Protokolleri
Transfer Protokolleri
Git, iki repo arasında veri transferini iki ana şekilde yapabilir: "aptal" protokol ve "akıllı" protokol. Bu bölüm, bu iki ana protokolün nasıl çalıştığını kısaca ele alacaktır.
Aptal Protokol
Eğer bir reposunu HTTP üzerinden salt okunur olarak sunmak üzere kuruyorsanız, muhtemelen aptal protokol kullanılacaktır. Bu protokol taşıma sürecinde sunucu tarafında Git’e özgü herhangi bir kod gerektirmediği için "aptal" olarak adlandırılır; çekme işlemi, istemcinin sunucudaki Git reposunun düzenini üstlenebildiği bir dizi HTTP GET isteğidir.
Not
|
Aptal protokol bu günlerde oldukça nadiren kullanılmaktadır. Güvenliği sağlamak veya özel hale getirmek zor olduğu için çoğu Git ana bilgisayarı (hem bulut tabanlı hem de şirket içi) onu kullanmayı reddedecektir. Genel olarak, biraz ileride açıklayacağımız üzere, akıllı protokolün kullanılması tavsiye edilir. |
Simplegit kütüphanesi için http-fetch
sürecini takip edelim:
$ git clone http://server/simplegit-progit.git
Bu komutun yaptığı ilk şey info/refs
dosyasını aşağı çekmektir.
Bu dosya update-server-info
komutu tarafından yazılmıştır, bu nedenle HTTP aktarımının düzgün çalışması için bunu bir post-receive
(çekme sonrası) kancası olarak etkinleştirmeniz gerekir:
=> GET info/refs
ca82a6dff817ec66f44342007202690a93763949 refs/heads/master
Artık uzak referansların ve SHA-1’lerin bir listesine sahipsiniz. Sonra, HEAD referansının ne olduğuna bakarsınız, böylece işiniz bittiğinde neyi kontrol etmeniz gerektiğini bilirsiniz:
=> GET HEAD
ref: refs/heads/master
İşlemi tamamladığınızda master
şubesine göz atmanız gerekiyor.
Bu noktada yürüme sürecine başlamaya hazırsınız.
Başlangıç noktanız, info/refs
dosyasında gördüğünüz ca82a6
katkı nesnesi olduğundan, şunu çekerek başlarsınız:
=> GET objects/ca/82a6dff817ec66f44342007202690a93763949
(179 bytes of binary data)
Bir nesneyi geri alırsınız; bu nesne sunucuda gevşek biçimdedir ve onu statik bir HTTP GET isteği üzerinden getirdiniz. Sıkıştırılmış zlib’i açabilir, başlığı (header) çıkarabilir ve katkı içeriğine bakabilirsiniz:
$ git cat-file -p ca82a6dff817ec66f44342007202690a93763949
tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
author Scott Chacon <schacon@gmail.com> 1205815931 -0700
committer Scott Chacon <schacon@gmail.com> 1240030591 -0700
changed the version number
Daha sonra, almanız gereken iki nesne daha var: az önce aldığımız katkının işaret ettiği içerik ağacı olan cfda3b
ve öncel katkısı olan 085bb3
:
=> GET objects/08/5bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
(179 bytes of data)
Bu size bir sonraki katkı nesnenizi verir. Ağaç nesnesini alın:
=> GET objects/cf/da3bf379e4f8dba8717dee55aab78aef7f4daf
(404 - Not Found)
Hata! Görünüşe göre ağaç nesnesi sunucuda gevşek formatta olmadığı için 404 yanıtı alıyorsunuz. Bunun birkaç nedeni olabilir: nesne, alternatif bir repoda veya bu repodaki bir paket dosyasında olabilir. Git önce listelenen alternatifleri kontrol eder:
=> GET objects/info/http-alternates
(empty file)
Bu, alternatif URL’lerin bir listesiyle birlikte gelirse, Git oradaki gevşek dosyaları ve paket dosyalarını kontrol eder; bu diskteki nesneleri paylaşmak için birbirinden çatalı olan projeler için güzel bir mekanizmadır.
Ancak burada hiçbir alternatif listelenmediğinden nesnenizin bir paket dosyasında olması gerekir.
Bu sunucuda hangi paket dosyalarının mevcut olduğunu görmek için, bunların bir listesini içeren (ayrıca update-server-info
tarafından oluşturulan) objects/info/packs
dosyasını almanız gerekir:
=> GET objects/info/packs
P pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
Sunucuda yalnızca bir paket dosyası olduğu için nesneniz açıkça oradadır, ancak emin olmak için dizin dosyasını kontrol edeceksiniz. Bu aynı zamanda sunucuda birden fazla paket dosyanız varsa kullanışlıdır, böylece ihtiyacınız olan nesneyi hangi paket dosyasının içerdiğini görebilirsiniz:
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.idx
(4k of binary data)
Artık paket dosyası dizinine sahip olduğunuza göre, nesnenizin burada olup olmadığını görebilirsiniz; çünkü dizin, paket dosyasında bulunan nesnelerin SHA-1’lerini ve bu nesnelerin uzaklıklarını listeler. Nesneniz orada, o yüzden devam edin ve paket dosyasının tamamını alın:
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
(13k of binary data)
Ağaç nesneniz var, böylece katkılarınızı yürütmeye devam edersiniz.
Bunların hepsi aynı zamanda yeni indirdiğiniz paket dosyasının içindedir, dolayısıyla sunucunuza başka istekte bulunmanıza gerek yoktur.
Git başlangıçta indirdiğiniz HEAD referansının işaret ettiği master
dalının çalışan bir kopyasını kontrol eder.
Akıllı Protokol
Aptal protokol basit ama biraz verimsizdir ve istemciden sunucuya veri yazılmasını sağlayamaz. Akıllı protokol, veri aktarmanın daha yaygın bir yöntemidir ancak uzak uçta Git konusunda akıllı olan bir işlem gerektirir; yerel verileri okuyabilir, istemcinin neye sahip olduğunu ve neye ihtiyaç duyduğunu anlayabilir ve bunun için özel bir paket dosyası oluşturabilir. Veri aktarımı için iki süreç kümesi vardır: veri yüklemek için bir çift ve veri indirmek için bir çift.
Veri Yüklemek
Git uzak bir sürece veri yüklemek için send-pack
ve receive-pack
süreçlerini kullanır.
send-pack
süreci istemcide çalışır ve uzak tarafta bir receive-pack
sürecine bağlanır.
SSH
Örneğin, bir projede git push origin master
komutunu çalıştırdığınızı ve origin
'in SSH protokolünü kullanan bir URL olarak tanımlandığını varsayalım.
Git, sunucunuza bir SSH bağlantısı üzerinden başlatılan send-pack
sürecini çalıştırır.
Uzak sunucuda bir komut çalıştırmaya çalışır ve bunun için bir SSH çağrısı yapar.
Örnek olarak şöyle bir şey olabilir:
$ ssh -x git@server "git-receive-pack 'simplegit-progit.git'"
00a5ca82a6dff817ec66f4437202690a93763949 refs/heads/master□report-status \
delete-refs side-band-64k quiet ofs-delta \
agent=git/2:2.1.1+github-607-gfba4028 delete-refs
0000
git-receive-pack
komutu şu anda sahip olduğu her referans için bir satır ile hemen yanıt verir (burada sadece master
dalı ve onun SHA-1’ı).
İlk satır aynı zamanda sunucunun yeteneklerinin bir listesini de içerir (burada report-status
, delete-refs
ve istemci tanımlayıcısı da dahil, başkaları ).
Her satır geri kalan kısmın ne kadar uzun olduğunu belirten 4 karakterlik bir onaltılık değerle başlar. İlk satır 00a5 ile başlar, bu da geri kalan kısmın 165 bayt olduğunu belirtir. Bir sonraki satır 0000’dir, bu da sunucunun referans listelemesinin bittiğini belirtir.
Artık sunucunun durumunu bildiğine göre, send-pack
süreci sunucunun sahip olmadığı hangi katkıların olduğunu belirler.
send-pack
süreci bu bilgiyi, bu itişin güncelleyeceği her referans için receive-pack
sürecine bildirir.
Örneğin, master
dalını güncelliyor ve experiment
dalı ekliyorsanız, send-pack
'in yanıtı şöyle görünebilir:
0076ca82a6dff817ec66f44342007202690a93763949 15027957951b64cf874c3557a0f3547bd83b3ff6 \
refs/heads/master report-status
006c0000000000000000000000000000000000000000 cdfdb42577e2506715f8cfeacdbabc092bf63e8d \
refs/heads/experiment
0000
Git, güncellediğiniz her referans için satırın uzunluğunu, eski SHA-1’i, yeni SHA-1’i ve güncellenmekte olan referansı içeren bir satır gönderir. İlk satır aynı zamanda istemcinin yeteneklerine de sahiptir. Tüm sıfırların SHA-1 değeri, daha önce hiçbir şeyin olmadığı anlamına gelir; çünkü deneme referansı ekliyorsunuz. Bir referansı siliyorsanız tam tersini görürsünüz: tüm sıfırlar sağ tarafta.
Daha sonra istemci, sunucunun henüz sahip olmadığı tüm nesnelerin bir paket dosyasını gönderir. Son olarak sunucu bir başarı (veya başarısızlık) göstergesiyle yanıt verir:
000eunpack ok
HTTP(S)
Bu işlem çoğunlukla HTTP üzerinden aynıdır, ancak el sıkışma biraz farklıdır. Bağlantı şu istekle başlatılır:
=> GET http://server/simplegit-progit.git/info/refs?service=git-receive-pack
001f# service=git-receive-pack
00ab6c5f0e45abd7832bf23074a333f739977c9e8188 refs/heads/master□report-status \
delete-refs side-band-64k quiet ofs-delta \
agent=git/2:2.1.1~vmg-bitmaps-bugaloo-608-g116744e
0000
Bu, ilk istemci-sunucu değişiminin sonudur.
İstemci daha sonra send-pack
'in sağladığı verilerle bu sefer bir POST
olan başka bir istekte bulunur.
=> POST http://server/simplegit-progit.git/git-receive-pack
POST
isteği, yük olarak send-pack
çıktısını ve paket dosyasını içerir.
Sunucu daha sonra başarılı veya başarısız olduğunu HTTP yanıtı ile belirtir.
Veri İndirme
Veri indirdiğinizde, fetch-pack
ve upload-pack
süreçleri devreye girer.
İstemci, indirilecek verileri belirlemek için uzak tarafta upload-pack
sürecine bağlanan bir fetch-pack
süreci başlatır.
SSH
Eğer SSH üzerinden indirme yapıyorsanız, fetch-pack
şu şekilde çalışır:
$ ssh -x git@server "git-upload-pack 'simplegit-progit.git'"
fetch-pack
bağlandıktan sonra, upload-pack
şuna benzer bir şey gönderir:
00dfca82a6dff817ec66f44342007202690a93763949 HEAD□multi_ack thin-pack \
side-band side-band-64k ofs-delta shallow no-progress include-tag \
multi_ack_detailed symref=HEAD:refs/heads/master \
agent=git/2:2.1.1+github-607-gfba4028
003fe2409a098dc3e53539a9028a94b6224db9d6a6b6 refs/heads/master
0000
Bu receive-pack
'in yanıtına çok benzer, ancak yetenekler farklıdır.
Ayrıca bu bir kopya ise, HEAD’e ne işaret ettiğini (symref=HEAD:refs/heads/master
) geri gönderir, böylece istemci neyi klonlayacağını bilir.
Bu noktada fetch-pack
süreci sahip olduğu nesnelere bakar ve ihtiyaç duyduğu nesneleri want
ve ardından istediği SHA-1 ile göndererek yanıt verir.
Zaten sahip olduğu tüm nesneleri have
ve ardından SHA-1 ile gönderir.
Bu liste sonuna, ihtiyaç duyduğu veri paket dosyasını göndermeye başlamak için upload-pack
sürecini başlatmak için done
yazılır:
003cwant ca82a6dff817ec66f44342007202690a93763949 ofs-delta
0032have 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
0009done
0000
HTTP(S)
İndirme işlemi için anlaşma (handshake) iki HTTP isteği alır.
İlk olarak, aptal protokolde kullanılan aynı uç noktaya bir GET
isteği gönderilir:
=> GET $GIT_URL/info/refs?service=git-upload-pack
001e# service=git-upload-pack
00e7ca82a6dff817ec66f44342007202690a93763949 HEAD□multi_ack thin-pack \
side-band side-band-64k ofs-delta shallow no-progress include-tag \
multi_ack_detailed no-done symref=HEAD:refs/heads/master \
agent=git/2:2.1.1+github-607-gfba4028
003fca82a6dff817ec66f44342007202690a93763949 refs/heads/master
0000
Bu işlem bir SSH bağlantısı üzerinden git-upload-pack
'i çağırmaya çok benzer, ancak ikinci değişim ayrı bir istek olarak gerçekleştirilir:
=> POST $GIT_URL/git-upload-pack HTTP/1.0
0032want 0a53e9ddeaddad63ad106860237bbf53411d11a7
0032have 441b40d833fdfa93eb2908e52742248faf0ee993
0000
Yine yukarıdakiyle aynı formattadır. Bu isteğe yanıt, başarı veya başarısızlığı gösterir ve paket dosyasını içerir.
Özet Olarak Protokoller
Bu bölüm aktarım protokollerine çok temel bir genel bakış içerir.
Protokol multi_ack
veya side-band
yetenekleri gibi birçok başka özellik içerir, ancak bunlar bu kitabın kapsamı dışındadır.
Size istemci ile sunucu arasındaki genel gidiş-geliş hakkında bir fikir vermeye çalıştık; bundan daha fazla bilgiye ihtiyacınız varsa muhtemelen Git kaynak koduna bakmak isteyeceksiniz.