Skip to content

Latest commit

 

History

History
396 lines (333 loc) · 15.1 KB

File metadata and controls

396 lines (333 loc) · 15.1 KB

Git ve Mercurial

DVCS evreni yalnızca Git’ten ibaret değildir. Aslında bu alanda, dağıtılmış sürüm kontrolünün doğru şekilde nasıl yapılacağı konusunda her birinin kendi bakış açısı olan birçok sistem daha vardır. Git’ten sonra en popüler olanı Mercurial’dır ve bu ikisi birçok yönden çok benzer.

Git’in istemci tarafı davranışını tercih ediyorsanız ancak kaynak kodu Mercurial tarafından kontrol edilen bir projeyle çalışıyorsanız; iyi haber, Git’i Mercurial tarafından barındırılan bir reponun istemcisi olarak kullanmanın bir yolu vardır. Git’in sunucu repolarıyla iletişim kurma şekli uzak repolar aracılığıyla olduğu için, bu köprünün bir uzak yardımcı olarak uygulandığı şaşırtıcı olmamalıdır. Projenin adı git-remote-hg’dir ve https://github.com/felipec/git-remote-hg adresinde bulunabilir.

git-remote-hg

Öncelikle git-remote-hg’yi kurmanız gerekiyor. Bu, temel olarak dosyasını yolunuzun üzerinde bir yere bırakmayı gerektirir:

$ curl -o ~/bin/git-remote-hg \
  https://raw.githubusercontent.com/felipec/git-remote-hg/master/git-remote-hg
$ chmod +x ~/bin/git-remote-hg

…'~/bin' öğesinin '$PATH' dizininizde olduğunu varsayıyoruz. Git-remote-hg’nin başka bir bağımlılığı daha var: Python için "Mercurial" kütüphanesi. Python’u yüklediyseniz, bu şu kadar basittir:

$ pip install mercurial

(Python yüklü değilse https://www.python.org/ adresini ziyaret edin ve önce onu kurun.)

İhtiyacınız olan son şey Mercurial istemcisidir. https://www.mercurial-scm.org/ adresine gidin ve henüz yapmadıysanız yükleyin.

Artık dansa hazırsınız. İhtiyacınız olan tek şey, itebileceğiniz bir Mercurial reposudur. Neyse ki, her Mercurial reposu bu şekilde davranır, bu nedenle herkesin Mercurial’ı öğrenmek için kullandığı "merhaba dünya" reposunu kullanacağız:

$ hg clone http://selenic.com/repo/hello /tmp/hello
Başlarken

Artık uygun bir “sunucu tarafı” repomuz olduğuna göre, tipik bir iş akışını gerçekleştirebiliriz. Göreceğiniz üzere, bu iki sistem fazla sürtünme olmayacak kadar benzerdir.

Git’te her zaman olduğu gibi önce repoyu kopyalarız:

$ git clone hg::/tmp/hello /tmp/hello-git
$ cd /tmp/hello-git
$ git log --oneline --graph --decorate
* ac7955c (HEAD, origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master, master) Create a makefile
* 65bb417 Create a standard "hello, world" program

Mercurial reposuyla çalışmanın standart "git clone" komutunu kullandığını fark edeceksiniz. Bunun nedeni, git-remote-hg’nin Git’in HTTP/S protokolünün uygulanmasına (uzaktan yardımcılar) benzer bir mekanizma kullanarak oldukça düşük bir düzeyde çalışmasıdır. Git ve Mercurial’ın her ikisi de her kullanıcının repo geçmişinin tam bir kopyasına sahip olması için tasarlandığından, bu komut tüm projenin geçmişini içeren tam bir kopya oluşturur ve bunu çok hızlı bir şekilde yapar.

Log komutu, en sonuncusu bir dizi referans tarafından işaret edilen iki işlemi gösterir. Bunlardan bazılarının aslında orada olmadığı ortaya çıktı. .git dizininde gerçekte ne olduğuna bir bakalım:

$ tree .git/refs
.git/refs
├── heads
│   └── master
├── hg
│   └── origin
│       ├── bookmarks
│       │   └── master
│       └── branches
│           └── default
├── notes
│   └── hg
├── remotes
│   └── origin
│       └── HEAD
└── tags

9 directories, 5 files

Git-remote-hg işleri daha deyimsel olarak Git benzeri hale getirmeye çalışır, ancak aslında birbirinden biraz farklı iki sistem arasındaki kavramsal eşlemeyi yönetir. 'refs/hg' dizini gerçek uzak referansların saklandığı yerdir. Örneğin, "refs/hg/origin/branches/default", "master"ın işaret ettiği katkı olan "ac7955c" ile başlayan SHA-1’i içeren bir Git ref dosyasıdır. Yani 'refs/hg' dizini bir nevi sahte 'refs/remotes/Origin' gibidir, ancak yer imleri ve dallar arasında ek bir ayrım vardır.

'notes/hg' dosyası, git-remote-hg’nin Git katkı karmalarını Mercurial değişiklik kümesi kimlikleriyle nasıl eşlediğinin başlangıç noktasıdır. Hadi biraz araştıralım:

$ cat notes/hg
d4c10386...

$ git cat-file -p d4c10386...
tree 1781c96...
author remote-hg <> 1408066400 -0800
committer remote-hg <> 1408066400 -0800

Notes for master

$ git ls-tree 1781c96...
100644 blob ac9117f...	65bb417...
100644 blob 485e178...	ac7955c...

$ git cat-file -p ac9117f
0a04b987be5ae354b710cefeba0e2d9de7ad41a9

Yani 'refs/notes/hg', Git nesne veritabanında adları olan diğer nesnelerin listesi olan bir ağaca işaret eder. 'git ls-tree' bir ağacın içinde yer alan öğeler için: mod, tür, nesne karması ve dosya adını verir. Ağaç öğelerinden birini incelediğimizde, içinde ac9117f'' ("master" ile gösterilen katkının SHA-1 karması) adında ve 0a04b98'' içeriğine sahip bir blob olduğunu görürüz (bu, 'varsayılan' dalın ucundaki Mercurial değişiklik kümesinin kimliğidir).

Güzel olan şu ki, çoğunlukla tüm bunlar için endişelenmemize gerek yoktur. Tipik iş akışı Git uzaktan reposuyla çalışmaktan çok farklı olmayacaktır.

Devam etmeden önce ilgilenmemiz gereken bir şey daha var: yoksayılanlar. Mercurial ve Git bunun için çok benzer bir mekanizma kullanır, ancak muhtemelen bir .gitignore dosyasını Mercurial reposuna işlemek istemezsiniz. Neyse ki Git’in diskteki bir repoda yerel olan dosyaları yok saymanın bir yolu var ve bu Mercurial formatı Git ile uyumludur; dolayısıyla onu kopyalamanız yeterli:

$ cp .hgignore .git/info/exclude

.git/info/exclude dosyası tıpkı .gitignore gibi davranır ancak katkılara dahil edilmez.

İş Akışı

Diyelim ki 'master' dalında bazı değişiklikler yaptık ve bazı katkılar işledik ve siz de bunu uzak repoya göndermeye hazırsınız. Repomuz şu anda şöyle görünüyor:

$ git log --oneline --graph --decorate
* ba04a2a (HEAD, master) Update makefile
* d25d16f Goodbye
* ac7955c (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Create a makefile
* 65bb417 Create a standard "hello, world" program

Bizim 'master' dalımız, Origin/master 'dan iki katkı ileridedir, ancak bu iki katkı yalnızca yerel makinemizde mevcuttur. Bakalım aynı anda, başka biri de önemli işler yapıyor mu:

$ git fetch
From hg::/tmp/hello
   ac7955c..df85e87  master     -> origin/master
   ac7955c..df85e87  branches/default -> origin/branches/default
$ git log --oneline --graph --decorate --all
* 7b07969 (refs/notes/hg) Notes for default
* d4c1038 Notes for master
* df85e87 (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Add some documentation
| * ba04a2a (HEAD, master) Update makefile
| * d25d16f Goodbye
|/
* ac7955c Create a makefile
* 65bb417 Create a standard "hello, world" program

--all bayrağını kullandığımız için, git-remote-hg tarafından dahili olarak kullanılan notes referanslarını görüyoruz, ancak onları görmezden gelebiliriz. Gerisi beklediğimiz gibidir; 'Origin/master' tek bir katkı ilerledi ve artık geçmişimiz ayrıştı. Bu bölümde üzerinde çalıştığımız diğer sistemlerden farklı olarak; Mercurial, birleştirme işlemlerini gerçekleştirebilir, dolayısıyla havalı bir şey yapmayacağız.

$ git merge origin/master
Auto-merging hello.c
Merge made by the 'recursive' strategy.
 hello.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --oneline --graph --decorate
*   0c64627 (HEAD, master) Merge remote-tracking branch 'origin/master'
|\
| * df85e87 (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Add some documentation
* | ba04a2a Update makefile
* | d25d16f Goodbye
|/
* ac7955c Create a makefile
* 65bb417 Create a standard "hello, world" program

Mükemmel. Testleri yapıyoruz ve her şey başarılı oluyor, böylece çalışmalarımızı ekibin geri kalanıyla paylaşmaya hazırız:

$ git push
To hg::/tmp/hello
   df85e87..0c64627  master -> master

Bu kadar! Mercurial reposuna bakarsanız, bunun beklediğimiz şeyi yaptığını göreceksiniz:

$ hg log -G --style compact
o    5[tip]:4,2   dc8fa4f932b8   2014-08-14 19:33 -0700   ben
|\     Merge remote-tracking branch 'origin/master'
| |
| o  4   64f27bcefc35   2014-08-14 19:27 -0700   ben
| |    Update makefile
| |
| o  3:1   4256fc29598f   2014-08-14 19:27 -0700   ben
| |    Goodbye
| |
@ |  2   7db0b4848b3c   2014-08-14 19:30 -0700   ben
|/     Add some documentation
|
o  1   82e55d328c8c   2005-08-26 01:21 -0700   mpm
|    Create a makefile
|
o  0   0a04b987be5a   2005-08-26 01:20 -0700   mpm
     Create a standard "hello, world" program

2 numaralı değişiklik seti Mercurial tarafından, 3 ve 4 numaralı değişiklik seti ise Git-remote-hg tarafından Git ile yapılan katkıların itilmesiyle yapıldı.

Dallar ve Yer İmleri (Bookmarks)

Git’in yalnızca tek bir tür dalı vardır: katkılar işlendiğinde hareket eden bir referans. Mercurial’da bu tür bir referansa yer imi (bookmark) adı verilir ve Git dalıyla hemen hemen aynı şekilde davranır.

Mercurial’ın dal kavramı daha ağırdır. Değişiklik kümesinin yapıldığı dal, değişiklik kümesiyle birlikte kaydedilir. Bu da her zaman repo geçmişinde yeralacağı anlamına gelir. develop dalında yapılan bir katkı örneği:

$ hg log -l 1
changeset:   6:8f65e5e02793
branch:      develop
tag:         tip
user:        Ben Straub <ben@straub.cc>
date:        Thu Aug 14 20:06:38 2014 -0700
summary:     More documentation

branch ile başlayan satıra dikkat edin. Git bunu gerçekten kopyalayamaz (her iki dal türü de Git referansı olarak temsil edilebildiği için gerek de yoktur zaten), ancak Mercurial bunu önemsediği için git-remote-hg’nin farkı anlaması gereklidir.

Mercurial yer imleri oluşturmak Git dalları oluşturmak kadar kolaydır. Git tarafında:

$ git checkout -b featureA
Switched to a new branch 'featureA'
$ git push origin featureA
To hg::/tmp/hello
 * [new branch]      featureA -> featureA

Hepsi bu kadardır. Mercurial tarafında ise şöyle görünür:

$ hg bookmarks
   featureA                  5:bd5ac26f11f9
$ hg log --style compact -G
@  6[tip]   8f65e5e02793   2014-08-14 20:06 -0700   ben
|    More documentation
|
o    5[featureA]:4,2   bd5ac26f11f9   2014-08-14 20:02 -0700   ben
|\     Merge remote-tracking branch 'origin/master'
| |
| o  4   0434aaa6b91f   2014-08-14 20:01 -0700   ben
| |    update makefile
| |
| o  3:1   318914536c86   2014-08-14 20:00 -0700   ben
| |    goodbye
| |
o |  2   f098c7f45c4f   2014-08-14 20:01 -0700   ben
|/     Add some documentation
|
o  1   82e55d328c8c   2005-08-26 01:21 -0700   mpm
|    Create a makefile
|
o  0   0a04b987be5a   2005-08-26 01:20 -0700   mpm
     Create a standard "hello, world" program

Revizyon 5’teki yeni [featureA] etiketine dikkat edin. Bunlar, bir istisna dışında Git tarafındaki Git dalları gibi davranır (Git tarafından bir yer işaretini silemezsiniz: bu, uzak yardımcılara yönelik bir sınırlamadır).

Ayrıca ağır'' bir Mercurial dalı üzerinde de çalışabilirsiniz: branches`` ad alanına (namespace) bir dal koymanız yeterlidir:

$ git checkout -b branches/permanent
Switched to a new branch 'branches/permanent'
$ vi Makefile
$ git commit -am 'A permanent change'
$ git push origin branches/permanent
To hg::/tmp/hello
 * [new branch]      branches/permanent -> branches/permanent

Mercurial tarafın şöyle görünür:

$ hg branches
permanent                      7:a4529d07aad4
develop                        6:8f65e5e02793
default                        5:bd5ac26f11f9 (inactive)
$ hg log -G
o  changeset:   7:a4529d07aad4
|  branch:      permanent
|  tag:         tip
|  parent:      5:bd5ac26f11f9
|  user:        Ben Straub <ben@straub.cc>
|  date:        Thu Aug 14 20:21:09 2014 -0700
|  summary:     A permanent change
|
| @  changeset:   6:8f65e5e02793
|/   branch:      develop
|    user:        Ben Straub <ben@straub.cc>
|    date:        Thu Aug 14 20:06:38 2014 -0700
|    summary:     More documentation
|
o    changeset:   5:bd5ac26f11f9
|\   bookmark:    featureA
| |  parent:      4:0434aaa6b91f
| |  parent:      2:f098c7f45c4f
| |  user:        Ben Straub <ben@straub.cc>
| |  date:        Thu Aug 14 20:02:21 2014 -0700
| |  summary:     Merge remote-tracking branch 'origin/master'
[...]

permanent (kalıcı) dal adı, 7 işaretli değişiklik kümesiyle kaydedildi.

Git açısından bakıldığında, bu dal stillerinden herhangi biriyle çalışmak aynıdır: normalde yaptığınız gibi yalnızca geçiş yapın, kaydedin, getirin, birleştirin, çekin ve itin. Bilmeniz gereken bir şey de Mercurial’ın tarihin yeniden yazılmasını desteklememesidir. Ona yalnızca ekleme yapabilirsiniz. Etkileşimli bir yeniden temelleme (rebase) ve zorla itme (forced push) sonrasında Mercurial repomuz şu şekilde görünür:

$ hg log --style compact -G
o  10[tip]   99611176cbc9   2014-08-14 20:21 -0700   ben
|    A permanent change
|
o  9   f23e12f939c3   2014-08-14 20:01 -0700   ben
|    Add some documentation
|
o  8:1   c16971d33922   2014-08-14 20:00 -0700   ben
|    goodbye
|
| o  7:5   a4529d07aad4   2014-08-14 20:21 -0700   ben
| |    A permanent change
| |
| | @  6   8f65e5e02793   2014-08-14 20:06 -0700   ben
| |/     More documentation
| |
| o    5[featureA]:4,2   bd5ac26f11f9   2014-08-14 20:02 -0700   ben
| |\     Merge remote-tracking branch 'origin/master'
| | |
| | o  4   0434aaa6b91f   2014-08-14 20:01 -0700   ben
| | |    update makefile
| | |
+---o  3:1   318914536c86   2014-08-14 20:00 -0700   ben
| |      goodbye
| |
| o  2   f098c7f45c4f   2014-08-14 20:01 -0700   ben
|/     Add some documentation
|
o  1   82e55d328c8c   2005-08-26 01:21 -0700   mpm
|    Create a makefile
|
o  0   0a04b987be5a   2005-08-26 01:20 -0700   mpm
     Create a standard "hello, world" program

8, 9 ve 10 değişiklik kümeleri oluşturuldu ve permanent dalına aitler, ancak eski değişiklik kümeleri hâlâ duruyor. Bu, Mercurial kullanan takım arkadaşlarınız için çok kafa karıştırıcı olabilir, bu yüzden bundan kaçınmaya çalışın.

Özetle Mercurial

Git ve Mercurial, sınırın ötesinde çalışmanın oldukça sancısız olmasını sağlayacak kadar benzerdir. (Genellikle önerildiği üzere) makinenizden kalan geçmişi değiştirmekten kaçınırsanız, diğer ucun Mercurial olduğunun farkına bile varmazsınız.