Belajar Menggunakan Branching Di Git


Ada kalanya pengembangan perangkat lunak tidak selalu berlangsung linear.   Pada kondisi tertentu, pengembangan bisa menjadi bercabang (disebut juga branching).   Sebagai contoh, anggap saja saya mengembangkan sebuah framework internal untuk keperluan pribadi.   Framework versi 1 (V1) sudah dipakai pada beberapa proyek saya. Lalu, mengambil pelajaran dari pengalaman, saya berniat melakukan perubahan drastis pada framework internal tersebut menjadi versi 2 (V2) yang TIDAK compatible dengan V1.  Proyek yang memakai framework V1 tidak bisa begitu saja men-upgrade ke framework V2.   Pengembangan framework versi 1 menjadi versi 2 bukankah terlihat sangat ‘lurus’ linear?  Bukankah begitu?

Proyek lama masih tetap memakai framework versi 1.   Saya tidak ingin menanggung resiko upgrade ke framework versi 2 karena proyek lama sudah dipakai.   Tapi permasalahannya:  saya tetap harus men-support proyek lama.   Bila ada keluhan yang berkaitan dengan bug di framework versi 1,  saya harus memperbaikinya dan merilis versi 1.1 dan seterusnya untuk dipakai oleh proyek lama.   Sementara itu, saya juga tetap harus mengembangkan develop dan memperbaiki framework versi 2 menjadi versi 2.1 dan seterusnya.   Beberapa perubahan yang saya lakukan pada versi 1 harus diterapkan pada versi 2 karena pada dasarnya kode program untuk versi 2 dilahirkan dari kode program versi 1.  Sekarang kondisinya tidak lagi linear, bukan?

Kasus di atas adalah salah satu alasan untuk melakukan percabangan (branching).   Beruntungnya, saya tidak perlu terlalu khawatir karena Git dapat menangani skenario di atas dengan baik.   Pada Git, sebuah branch adalah kumpulan hasil commit yang diberi pengenal tertentu (lebih tepatnya branch adalah referensi ke sebuah commit terakhir).   Setiap kali berpindah branch, maka struktur direktori dan isi file di working directory akan disesuaikan dengan kondisi untuk keadaan branch tersebut.   Git menyimpan struktur direktori dalam bentuk tree dan isi file dalam bentuk blob di dalamn folder bernama .git.   Berdasarkan informasi ini, Git dapat mengubah-ubah (atau memproduksi ulang) struktur direktori dan isi file secara mudah.  Ini merupakan salah satu fitur andalan Git yang membuatnya populer.

Sebagai contoh, saya akan membuat sebuah repository baru seperti berikut ini:

$ git init framework
Initialized empty Git repository in c:/Users/Snake/Desktop/framework/.git/

$ cd framework

$ git config 'user.name' 'Snake'

$ git config 'user.email' 'snake@dev.com'

Git secara default akan membuat sebuah branch dengan nama master.   Dengan demikian, saat ini repository saya sedang berada di branch master.  Saya dapat memulai branch V1 dengan memberikan perintah:

$ git checkout -b V1
Switched to a new branch 'V1'

Lalu saya mensimulasikan beberapa perubahan yang saya lakukan pada framework versi 1 seperti berikut ini:

$ mkdir core

$ echo 'Ini source core' >> core/core.txt

$ git add .
warning: LF will be replaced by CRLF in core/core.txt.
The file will have its original line endings in your working directory.

$ git commit -m 'Development untuk core'
[V1 (root-commit) ce68760] Development untuk core
warning: LF will be replaced by CRLF in core/core.txt.
The file will have its original line endings in your working directory.
 1 file changed, 1 insertion(+)
 create mode 100644 core/core.txt

$ mkdir shared

$ echo 'Ini shared code' >> shared/shared.txt

$ git add .
warning: LF will be replaced by CRLF in shared/shared.txt.
The file will have its original line endings in your working directory.

$ git commit -m 'Development untuk shared'
[V1 0e34b49] Development untuk shared
warning: LF will be replaced by CRLF in shared/shared.txt.
The file will have its original line endings in your working directory.
 1 file changed, 1 insertion(+)
 create mode 100644 shared/shared.txt

Sampai disini, struktur direktori saya adalah seperti berikut ini:

$ ls -R
.:
core  shared

./core:
core.txt

./shared:
shared.txt

Anggap saja struktur direktori ini mewakili framework versi 1 yang telah dirilis dan dipakai oleh proyek-proyek sebelummnya.

Lalu, dari sini saya berencana melakukan perubahan besar, yaitu dengan menghapus folder core dan membuat folder baru bernama core_baru.  Ini akan menjadi framework versi 2.   Saya akan mulai dengan membuat branch baru dengan perintah berikut ini:

$ git checkout -b V2
Switched to a new branch 'V2'

Saya mensimulasikan beberapa perubahan pada versi 2, yaitu:

$ rm -Rf core

$ mkdir core_baru

$ echo 'Ini adalah core baru' >> core_baru/core.txt

$ git add --all
warning: LF will be replaced by CRLF in core_baru/core.txt.
The file will have its original line endings in your working directory.

$ git commit -m 'Development untuk core baru'
[V2 warning: LF will be replaced by CRLF in core_baru/core.txt.
The file will have its original line endings in your working directory.
e6e7d19] Development untuk core baru
warning: LF will be replaced by CRLF in core_baru/core.txt.
The file will have its original line endings in your working directory.
 2 files changed, 1 insertion(+), 1 deletion(-)
 delete mode 100644 core/core.txt
 create mode 100644 core_baru/core.txt

Sampai disini, bila saya melihat informasi branch untuk repository, saya akan menemukan hasil seperti berikut ini:

$ git branch -a
  V1
* V2

$ ls -R
.:
core_baru  shared

./core_baru:
core.txt

./shared:
shared.txt

Framework versi 2 sekarang sudah selesai dibuat.

Suatu hari, saya mendapatkan laporan dari developer yang menemukan adanya bug kritis di shared.txt.   Bug ini harus segera diperbaiki dan seluruh proyek lama harus segera di-update agar memakai framework yang telah diperbaiki.   Karena proyek lama terikat pada framework versi 1, maka saya melakukan perubahan pada branch V1.   Untuk itu, saya segera beralih ke branch V1 dengan perintah berikut ini:

$ git checkout V1
Switched to branch 'V1'

$ ls -R
.:
core  shared

./core:
core.txt

./shared:
shared.txt

Saat saya beralih ke branch V1, struktur pada working directory kembali ke kondisi lama dimana terdapat folder core.   Sementara itu, folder core_baru yang ada di V2 tidak terlihat disini.   Saya segera melakukan perbaikan bug yang disimulasikan dengan:

$ echo 'Ada perbaikan bug penting!' >> shared/shared.txt

$ cat shared/shared.txt
Ini shared code
Ada perbaikan bug penting!

$ git commit -a -m 'Perbaikan bug penting!'
warning: LF will be replaced by CRLF in shared/shared.txt.
The file will have its original line endings in your working directory.
[V1 warning: LF will be replaced by CRLF in shared/shared.txt.
The file will have its original line endings in your working directory.
213674f] Perbaikan bug penting!
warning: LF will be replaced by CRLF in shared/shared.txt.
The file will have its original line endings in your working directory.
 1 file changed, 1 insertion(+)

Anggap saja bug terdapat pada file shared.txt.  Saya telah men-commit perubahan file shared.txt yang telah diperbaiki.

Sebagai bonus, saya juga melakukan penambahan fitur.  Perubahan ini khusus untuk framework versi 1 saja dan tidak berlaku untuk versi 2.  Sebagai simulasi, saya memberikan perintah:

$ echo 'Ini fitur baru untuk versi lama' >> core/fitur.txt

$ git add core/fitur.txt
warning: LF will be replaced by CRLF in core/fitur.txt.
The file will have its original line endings in your working directory.

$ git commit -a -m 'Penambahan fitur baru'
[V1 62c536a] Penambahan fitur baru
warning: LF will be replaced by CRLF in core/fitur.txt.
The file will have its original line endings in your working directory.
 1 file changed, 1 insertion(+)
 create mode 100644 core/fitur.txt

Tugas saya telah selesai.   Proyek yang memakai versi 1 dapat segera di-update untuk memakai perubahan terbaru tersebut.

Tapi ada satu masalah baru yang muncul:  saat saya kembali ke branch V2, perubahan di shared.txt tidak akan diikutsertakan.   Hal ini karena perubahan sebelumnya saya lakukan di branch V1.  Tapi bila perubahan tidak diterapkan di V2, maka bug yang diperbaiki di V1 akan muncul kembali di V2.   Untuk memeriksanya, saya menggunakan perintah berikut ini:

$ git checkout V2
Switched to branch 'V2'

$ ls -R
.:
core_baru  shared

./core_baru:
core.txt

./shared:
shared.txt

$ cat shared/shared.txt
Ini shared code

Bila branch V2 masih belum di-push ke upstream (belum di-‘lihat‘ orang lain), maka saya dapat melakukan rebase, seperti yang ditunjukkan pada perintah berikut ini:

$ git rebase V1~
First, rewinding head to replay your work on top of it...
Applying: Development untuk core baru

$ ls -R
.:
core_baru  shared

./core_baru:
core.txt

./shared:
shared.txt

$ cat shared/shared.txt
Ini shared code
Ada perbaikan bug penting!

Saya memakai V1~ untuk merujuk pada commit sebelum commit terakhir di branch V1.   Hal ini karena commit terakhir: ‘Penambahan fitur baru‘, tidak perlu disertakan pada branch V2.   Nilai V1~ sama seperti merujuk pada commit dengan keterangan ‘Perbaikan bug penting!‘.   Selain memakai notasi relatif tersebut, saya dapat langsung merujuk ke id commit secara langsung, dengan perintah seperti:

$ git rebase 213674f4a0528e16d26d32476fff303008be3ede
First, rewinding head to replay your work on top of it...
Applying: Development untuk core baru

Salah satu alasan untuk tidak menggunakan rebase adalah proses ini menyebabkan seluruh commit yang ada di branch V2 berubah.   Rebase menghasilkan commit baru dengan id yang baru.   Hal ini tidak masalah bila hanya saya satu-satunya yang melihat seluruh commit yang ada di branch V2.   Akan tetapi lain ceritanya bila terdapat developer lain yang pernah men-fetch (atau men-pull) branch V2 sebelumnya.   Seluruh commit yang mereka lihat di repository lokal mereka kini tidak lagi valid.   Hal ini bisa jadi membingungkan ketika mereka akan men-push ke upstream!

Solusi lainnya adalah dengan menggunakan merge.   Sebagai contoh, saya dapat mengganti perintah rebase di atas dengan perintah berikut ini:

$ git merge V1~
Merge made by the 'recursive' strategy.
 shared/shared.txt | 1 +
 1 file changed, 1 insertion(+)

$ ls -R
.:
core_baru  shared

./core_baru:
core.txt

./shared:
shared.txt

$ cat shared/shared.txt
Ini shared code
Ada perbaikan bug penting!

Perintah merge tidak akan mengubah commit yang sudah ada, tetapi akan menghasilkan sebuah merge commit.  Dengan memberikan perintah gitk, saya dapat melihat visualisasi hubungan setiap commit untuk branch V2, seperti yang terlihat pada gambar berikut ini:

Visualisasi isi branch dengan gitk

Visualisasi isi branch dengan gitk

Perihal Solid Snake
I'm nothing...

2 Responses to Belajar Menggunakan Branching Di Git

  1. boleh di coba tuh sobh

    kunjungin balik ya

  2. phpgeek programmer mengatakan:

    Wah mantaps bray, penjelasannya sangat mudah untuk difahami. thanks alot.

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: