Git verisini ağ üzerinden aktarmanın yaygın yollarını (HTTP, SSH, vb.) öğrendik, ancak aslında pek kullanılmayan fakat oldukça yararlı olabilen başka bir yol daha vardır.
Git, verisini tek bir dosya halinde "demetleyebilir" ve bu, çeşitli senaryolarda faydalı olabilir.
Belki ağınız kapalıdır ama değişikliklerinizi iş arkadaşlarınıza göndermek istiyorsunuz.
Belki dışarıda bir yerde çalışıyorsunuz ve güvenlik nedeniyle yerel ağa erişiminiz yoktur.
Belki sadece kablosuz/eternet kartınız bozulmuştur.
Belki şu anda paylaşılan bir sunucuya erişiminiz yok ve birine güncellemeleri e-posta ile göndermek istersiniz ama format-patch
ile 40 değişikliği aktarmak istemiyorsunuzdur.
İşte burada git bundle
komutunun yardımcı olabileceği yer vardır.
bundle
komutu, bir git push
komutuyla normalde ağ üzerinden gönderilecek her şeyi ikilik (binary) bir dosya demeti haline getirecektir.
Bu dosyayı birine e-posta ile gönderebilir veya bir taşınabilir sürücüye koyup, ardından başka bir repoda açabilirsiniz.
Basit bir örnek görelim. İki katkı işlenmiş olan bir repoya sahip olduğunuzu varsayalım:
$ git log
commit 9a466c572fe88b195efd356c3f2bbeccdb504102
Author: Scott Chacon <schacon@gmail.com>
Date: Wed Mar 10 07:34:10 2010 -0800
second commit
commit b1ec3248f39900d2a406049d762aa68e9641be25
Author: Scott Chacon <schacon@gmail.com>
Date: Wed Mar 10 07:34:01 2010 -0800
first commit
Eğer o repoyu birine göndermek istiyorsanız ama gönderilecek repoya erişiminiz yoksa veya hemen bir tane kurmak istemiyorsanız, git bundle create
ile demetleyebilirsiniz.
$ git bundle create repo.bundle HEAD master
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 441 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
Artık, repoyu yeniden oluşturmak için gereken tüm verilere sahip repo.bundle
adında bir dosyanız var.
bundle
komutu ile dahil edilmesini istediğiniz her referansı veya belirli bir değişiklik aralığını belirtmeniz gerekir.
Eğer bunu başka bir yere kopyalamak niyetindeyseniz, burada yaptığımız gibi HEAD’i de bir referans olarak eklemelisiniz.
Bu repo.bundle
dosyasını başka birine e-posta ile gönderebilir veya USB sürücüsüne koyarak ulaştırabilirsiniz.
Bunun yanında, diyelim ki bu repo.bundle
dosyası size gönderildi ve projede çalışmak istiyorsunuz.
Bu ikilik dosyayı, sanki URL’den klonlama yapar gibi, bir dizine kopyalayabilirsiniz.
$ git clone repo.bundle repo
Cloning into 'repo'...
...
$ cd repo
$ git log --oneline
9a466c5 second commit
b1ec324 first commit
Eğer referanslara HEAD’i dahil etmezseniz, -hangi dala geçileceğini bilemeyeceği için- -b master
veya içerilen herhangi bir dalı belirtmeniz gerekir.
Şimdi diyelim ki üç adet değişiklik yaptınız ve bunları bir USB sürücüsü veya e-posta ile geri göndermek istiyorsunuz.
$ git log --oneline
71b84da last commit - second repo
c99cf5b fourth commit - second repo
7011d3d third commit - second repo
9a466c5 second commit
b1ec324 first commit
Öncelikle, demete dahil etmek istediğimiz değişiklik aralığını belirlememiz gerekiyor. Ağ üzerinde aktarılacak minimum veri kümesini otomatik olarak belirleyen ağ protokollerinin aksine, bunu manuel olarak kendimiz belirlememiz gerekecek. Şimdi, doğrudan tüm repoyu demetlemek işe yarayacak olsa da lokal olarak yaptığımız üç değişikliği içeren farkı demetlemek daha iyidir.
Bunu yapabilmek için farkı hesaplamanız gerekecek.
ch07-git-tools.asc bölümünde açıkladığımız gibi, bir dizi değişiklik aralığını belirtmek için birkaç yol vardır.
Başta kopyaladığımız dalda bulunmayıp, artık master dalımızda olan üç değişikliği almak için origin/master..master
veya master ^origin/master
gibi bir şey kullanabilirsiniz.
Bu işlemi log
komutuyla test edebilirsiniz.
$ git log --oneline master ^origin/master
71b84da last commit - second repo
c99cf5b fourth commit - second repo
7011d3d third commit - second repo
Şimdi demete dahil etmek istediğimiz değişikliklerin listesine sahip olduğumuza göre, onları demetleyelim. Bunu, git bundle create` komutunu kullanarak yaparız; bunu yaparken demetimizin dosya adını ve eklemek istediğimiz katkıların aralığını veririz.
$ git bundle create commits.bundle master ^9a466c5
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), 775 bytes, done.
Total 9 (delta 0), reused 0 (delta 0)
Şimdi dizinimizde bir commits.bundle
dosyasına sahibiz.
Bu dosyayı alıp arkadaşımıza gönderirsek, geçen zaman zarfında dosya üzerinde daha fazla çalışma yapılmış olsa bile, bunu orijinal repoya aktarabilir.
Arkadaşımız bu demeti aldığında, onu reposuna aktarmadan önce içerdiğini görmek için inceleyebilir.
İlk komut, dosyanın gerçekten geçerli bir Git demeti olduğundan ve bunu doğru şekilde yeniden oluşturmak için gerekli tüm eklere sahip olduğunuzdan emin olmak için bundle verify
komutudur.
$ git bundle verify ../commits.bundle
The bundle contains 1 ref
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
The bundle requires these 1 ref
9a466c572fe88b195efd356c3f2bbeccdb504102 second commit
../commits.bundle is okay
Eğer demetleyici, tüm üç değişiklik yerine, yalnızca yaptıkları son iki değişikliğin bir demetini oluşturmuş olsaydı, gerekli tarihlerden biri eksik olacağı için, orijinal repo bunu alamazdı.
verify
komutu ise şu şekilde görünecekti:
$ git bundle verify ../commits-bad.bundle
error: Repository lacks these prerequisite commits:
error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 third commit - second repo
Ancak, ilk demetimiz geçerlidir, bu yüzden ondaki değişiklikleri çekebiliriz. İçeri aktarılabilen demette hangi dalların olduğunu görmek isterseniz, yalnızca uçları (HEAD) listelemek için bir komutumuz da mevcuttur:
$ git bundle list-heads ../commits.bundle
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
verify
alt komutu aynı zamanda başlıkları da size söyleyecektir.
Amacımız içe aktarılabilenleri görmektir, haliyle bu demetten değişiklikleri almak için fetch
veya pull
komutlarını kullanabilirsiniz.
Şimdi demetin 'master' dalını, repomuzdaki 'other-master' adlı bir dala almak için fetch
komutunu kullanıyoruz:
$ git fetch ../commits.bundle master:other-master
From ../commits.bundle
* [new branch] master -> other-master
Şimdi, 'other-master' dalında alınan değişiklikleri, kendi 'master' dalımızda yaptığımız tüm değişikliklerle birlikte görebiliriz.
$ git log --oneline --decorate --graph --all
* 8255d41 (HEAD, master) third commit - first repo
| * 71b84da (other-master) last commit - second repo
| * c99cf5b fourth commit - second repo
| * 7011d3d third commit - second repo
|/
* 9a466c5 second commit
* b1ec324 first commit
Gördüğünüz gibi, git bundle
uygun ağa veya paylaşılan bir repoya sahip olmadığınızda paylaşım yapmak veya ağ benzeri işlemler gerçekleştirmek için gerçekten yararlı olabilir.