Backup Blog

Selain menggabung sekian blog jadi satu, kemarin saya juga memindahkan tempat si blog berada. Sebelumnya, 3 dari 4 blog yang saya gabung ada di Dreamhost namun blog ini ada di sebuah VPS mungil murah meriah πŸ˜€Β Satu hal yang jujur saja saya khawatirkan adalah masalah realibilitas dari si VPS sehingga kali ini saya memikirkan mengenai backup. Sebelumnya saya cukup percaya sama om Google dan Dreamhost tuk menjaga data saya.

Setelah memikirkan beberapa strategi backup, akhirnya saya memilih tuk membackup data saya ke layanan lain yang mudah2an bisa saya percayai: BitBucket! πŸ˜€

Ada dua hal dari blog ini yang saya rasa perlu saya backup: database yang dipakai dan juga instalasi WordPress (termasuk berkas-berkas yang saya upload via WordPress). Strategi backup saya adalah dengan memasukkan semuanya ke dalam repositori Git dan mengirimnya ke BitBucket. Untung saja BitBucket menyediakan repositori privat yang gratis dan dapat memiliki kapasitas tak terbatas. Klop!

Strategi sudah dipilih, sekarang saatnya membuat langkah konkrit. Untuk database, saya dapat menjalankan mysqldump agar isi database disimpan ke berkas. Saya juga menggunakan opsiΒ --skip-extended-insert agar satu buah record ditulis menjadi satu baris. Andai opsi ini tidak dimasukkan, maka satu baris dalam berkas SQL yang dihasilkan dapat mengandung banyak data sekaligus. Dengan membuat satu entry satu baris, ukuran berkas SQL yang dihasilkan memang bertambah besar namun Git akan dapat melacak perubahan dengan lebih efisien. Untuk berkas instalasi, tidak ada perlakuan khusus agar Git dapat memasukkan semuanya dengan baik.

Setelah coba-coba, inilah kira2 skrip yang saya pakai. Saya jalankan skrip berikut di direktori induk dari direktori instalasi WordPress, secara berkala melalui crontab.

#!/bin/sh

set -x

cd `dirname $0`

mysqldump -h HOST -u USER --password=PASSWORD \
          --skip-extended-insert DATABASE > data.sql

git add data.sql
git commit -m "Database backup"

git add www
git commit -m "WordPress backup"

git push origin master

Tentunya sebelum ini saya sudah persiapkan direktori kerja lokal Git dan juga repositori Git di BitBucket. Kunci SSH tanpa password juga saya gunakan agar operasi push dapat bekerja di belakang layar.

Distributed Version Control System

Wah udah lama saya ngga mengisi blog ini. Saya akan awali lagi mengisi blog ini dengan cerita sedikit mengenai pengalaman saya menggunakan distributed version control system alias DVCS.

Dari sekian DVCS yang ada, saya cuma pernah memakai Bazaar, Git, dan terakhir Mercurial. Saya bisa dibilang sudah meninggalkan Bazaar, yang saya kenal sambil mengembangkan BlankOn, setelah saya mengenal Git. Sejak sekitar dua tahun lalu, saya mencoba menggunakan Mercurial. Sebelum saya menggunakan Bazaar, saya biasanya menggunakan Subversion.

Yang sekarang bisa saya simpulkan mengenai pengalaman saya menggunakan ketiga DVCS ini adalah seperti berikut.

  • Perpindahan dari Subversion ke Bazaar tidak terlalu sulit bagi saya. Saat itu saya hanya perlu tahu konsep repositori lokal, yang secara praktis berarti harus memahami bahwa commit itu hanya akan menyimpan perubahan ke repositori lokal dan push itu dibutuhkan agar perubahan dikirim ke repositori bersama.
  • Saya juga belajar bahwa repositori lokal ini dapat disalin ke direktori lain dan secara otomatis kita akan memiliki sebuah cabang repositori baru.
  • Saat mencoba2 Git, saya menemukan sebuah konsep baru yaitu staging area. Operasi commit pada Git itu hanya akan menyimpan perubahan yang sudah dimasukkan ke dalam staging area. Karena saya masih baru menggunakan Git, perintah git commit -a, yang berarti add dan commit sekaligus, adalah perintah yang saya pakai untuk melakukan commit.
  • Setelah beberapa waktu, saya menemukan operasi commit secara interaktif dengan git commit -i. Saya bisa memilih dulu berkas mana yg ingin saya commit dan mana yg tidak.
  • Selain commit secara interaktif, Git juga memiliki operasi untuk memasukkan berkas ke staging area secara parsial, yang artinya juga kita bisa melakukan commit secara parsial, dengan perintah git add -p. Kita akan dihadapkan dengan pertanyaan bertubi-tubi mengenai setiap perubahan yang kita buat: ingin dimasukkan ke staging area atau tidak.
  • Semakin sering saya menggunakan git add -p semakin paham pula saya apa kegunaan dari staging area dan mengapa ini adalah fitur Git yang sangat powerful yang membedakan Git dengan yang lain
  • Selain ini, saya juga tau bahwa cabang di Git dapat berada di dalam satu buah repositori lokal (alias direktori) yang sama.
  • Setelah saya terbiasa dengan commit parsial, saya mencoba menggunakan Mercurial. Operasi pertama yang saya cari: commit parsial dan pembuatan cabang.
  • Mercurial tidak memiliki staging area sehingga operasi commit akan menyimpan semua perubahan yang dibuat. Sama dengan operasi commit di Bazaar dan bahkan Subversion.
  • Ada pengaya (extension) Mercurial yang dapat membuat kita melakukan commit secara selektif, yaitu Record Extension. Namun walau begitu, ini masih kalah canggih dibanding punyanya Git dalam urusan memilah-milah perubahan.
  • Mercurial memiliki tiga jenis percabangan: cabang dengan nama alias named branch, cabang tanpa nama alias anonymous/unnamed branch, dan bookmark.
  • Cabang dengan nama di Mercurial bersifat permanen: nama cabang akan selalu dibawa ke mana-mana termasuk saat perubahan dikirim ke repositori lain (push).
  • Bookmark adalah jenis cabang di Mercurial yang mirip dengan percabangan di Git.

Kesimpulan lain: Git dapat itu mengubah pikiran dan cara pandang Anda mengenai bagaimana cara menggunakan version control system. Setelah Anda paham mengenai penggunaan Git, maka menggunakan (D)VCS lain itu bisa bikin stres πŸ˜› *kisah nyata*

Git commit message from a text file

Once I need to do many commits and in each commit I have prepared the commit message. It’s very sensible to do this automatically since everything is already set. But wait, does Git provide a way to make it read a commit message from a text file?

After reading the manual page, yes `git help commit`, I could not find any clue on how to do this. Git provides `-m` option to enter the message inline, but I found this to be very limited since I have a paragraph long message. Git also provides `-t` to specify a template file. This is very close to what I need, however I still need to save and close the text editor which still pops up. Nah, I could not automate with this.

Then I realized that I can trick Git by changing the text editor it uses when asking user for the message. We can change the editor by setting the `EDITOR` environment variable. Git will call whatever specified there and give another parameter: the file Git will read for commit message. By default it will be set to `.git/COMMIT_EDITMSG`

So, for example, if I enter `/usr/bin/gedit` to `EDITOR`, Git will execute the following

/usr/bin/gedit .git/COMMIT_EDITMSG

Gedit application will run and Git wait until it closes. Then used whatever written in `.git/COMMIT_EDITMSG` as the commit message. We can also give parameter to Gedit, like adding `–new-window`, that will tell Gedit to open a new window instead of just using what is already opened.

$ EDITOR=”/usr/bin/gedit –new-window” git commit

That said, to make Git read a text file and use it as commit message, we can do a magic by using `cp`! Yes, the one that can create a copy! Let me show you how..

What will Git do if we set the `EDITOR` variable like the following?

$ EDITOR=”cp a-text-file.txt” git commit

Yes, Git will execute `cp a-text-file.txt .git/COMMIT_EDITMSG`, then wait until the execution finishes, and finally use the content of `.git/COMMIT_EDITMSG` as the commit message. In other words, we use what is written in `a-text-file.txt` as the commit message without touching any text editor! Perfect!

PS: This should be also applicable for other applications that use similar method of asking an input.

Pesan commit dari berkas

Saya sedang perlu melakukan banyak commit (seperti biasa, dengan git) berbeda dimana saya ingin memasukkan pesan commit dari sebuah berkas. Kalau saya baca manual dari git-commit, sayangnya Git tidak memiliki fasilitas ini. Git hanya mendukung pemasukkan pesan melalui parameter -m yang saya rasa sangat terbatas atau dengan membuat berkas yg dapat dijadikan sebagai template dari pesan commit. Pembuatan berkas template mungkin mendekati apa yg saya inginkan namun tetap saja saya harus berhadapan dengan teks editor lalu harus menyimpan dan menutupnya sebelum Git dapat melakukan commit. Saya menginginkan semuanya dapat berjalan secara otomatis.

Lalu saya ingat kalau pada dasarnya saya bisa mengganti editor yang akan digunakan oleh Git untuk meminta pengguna memasukkan pesan commit. Pada saat melakukan commit, Git akan memanggil sebuah teks editor dan menunggu sampai teks editor itu ditutup. Berkas yang tadi dibuka oleh teks editor akan dibaca oleh Git lalu isinya dijadikan sebagai pesan commit. Mengatahui alur kerja ini, saya jadi berpikir mengapa tidak membuat teks editor “palsu” saja πŸ˜€

Teks editor yang digunakan oleh Git dapat diatur, antara lain, dengan mengatur nilai environment variabel EDITOR. Sebagai contoh, jika ingin menggunakan Gedit untuk menulis pesan commit, kita bisa melakukan hal berikut.

$ EDITOR=gedit git commit

Sebuah berkas bernama .git/COMMIT_EDITMSG akan dijadikan parameter saat teks editor tadi dipanggil sehingga berkas tersebut akan secara otomatis dibuka. Setelah teks editor ditutup, isi dari berkas tadi akan dibaca oleh Git dan dijadikan sebagai pesan commit. Kalau saya ingin membuat teks editor palsu, berarti yang saya harus lakukan adalah menulisi berkas yg diberikan oleh Git dengan pesan commit yang saya inginkan.

Sekitar 6 baris kemudian, akhirnya jadi juga sebuah skrip sederhana yang akan menjadi teks editor palsu. Berikut ini kodenya. Wait.. tunggu.. setelah dipikir2 lagi.. aplikasi sejenis itu sudah ada! aplikasi tersebut adalah.. jreng jreng jreng.. cp alias copy! hah?

Begini ceritanya.. saat git commit dipanggil, maka Git akan menjalankan hal berikut.

$EDITOR .git/COMMIT_EDITMSG

Jika nilai EDITOR adalah gedit, maka yang akan dijalankan oleh Git adalah gedit .git/COMMIT_EDITMSG yang akan meminta Gedit untuk membuka berkas .git/COMMIT_EDITMSG. Setelah aplikasi yg disebut di EDITOR dideteksi sudah ditutup, maka Git akan membaca berkas .git/COMMIT_EDITMSG dan menggunakannya (saya udah nulis yg seperti ini berapa kali ya?).

Kalau diteliti lebih lanjut, nilai EDITOR itu juga bisa mengandung parameter lain. Sebagai contoh, Gedit memiliki opsi --new-window yang kalau dipakai, maka berkas yang disebutkan akan dibuka di jendela Gedit baru, bukan sekedar di tab baru dari window yg sudah ada (asumsinya sudah ada window Gedit yg terbuka). Jika Gedit ingin dijalankan dengan opsi ini pada saat melakukan commit, maka yang berikut ini bisa dilakukan.

$ EDITOR="gedit --new-window" git commit

Apakah hal tersebut berlaku untuk opsi (yg dimulai dengan - atau --) apakah bisa parameter lain termasuk nama berkas? Ternyata bisa! Coba saja yg berikut ini.

$ EDITOR="gedit a b c" git commit

Maka selain .git/COMMIT_EDITMSG, berkas a, b, dan c juga akan dibuka oleh Gedit.

Nah, kembali ke cp, bagaimana kita bisa memanfaatkan cp untuk melakukan commit dengan pesan yg dibaca dari sebuah berkas? Jawabannya adalah dengan menjadikan cp sebagai EDITOR dan berkas tadi sebagai parameter pertamanya. Saat commit dipanggil, Git akan memasukkan parameter kedua dan mengeksekusinya. Alhasil, perintah yang dipanggil adalah salin berkas yg disebut ke .git/COMMIT_EDITMSG πŸ˜€

$ EDITOR="cp /tmp/berkas-berisi-pesan-commit.txt" git commit

Voila! git commit akan keluar seketika namun commit tetap sudah terjadi. Jika melihat log, isi berkas yg disebut akan menjadi pesan commit.

Lho? kok bisa? bisa karena teks editor akan dibuka oleh Git dengan melakukan perintah berikut.

cp /tmp/berkas-berisi-pesan-commit.txt .git/COMMIT_EDITMSG

Perintah tadi akan jalan sekejap dan Git akan otomatis mendeteksi kalau perintah cp sudah selesai dieksekusi. Isi .git/COMMIT_EDITMSG akan diasumsikan sudah berisi pesan commit sehingga bisa digunakan oleh Git πŸ˜€

Slide tutorial Git

Bulan Desember kemarin saya sempat membuat dua buah slide mengenai Git. Slide ini sempat dipakai tuk tutorial di kanal IRC #debian-l10n-indonesian di irc.debian.org. Sebenernya masih ada (minimal) 1 slide lagi yg pengen saya buat, yaitu mengenai percabangan di Git.. namun.. belom sempet lagi xD Ya sudah lah nikmati saja apa yg ada dulu. Semoga bermanfaat πŸ™‚

Pengenalan Git

Berkolaborasi dengan Git

Backup data dg DVCS

Sejak bbrp hari yang lalu saya nyari2 cara tuk membackup data (er.. foto sih tepatnya =D) dg mudah di harddisk eksternal. Berhubung saya jg pengen ada fasilitas versioning, cara backup dg rsync tidak bisa diambil mentah2.

Aplikasi selanjutnya yg terpikir adalah Time Machine yg ada di Mac OS X. Namun setelah baca2, Time Machine tidak bisa melakukan backup secara selektif dalam artian hanya direktori yg dipilih saya yang dibackup, akhirnya Time Machine juga tidak jadi dipilih. Time Machine hanya bisa diatur untuk mengecualikan direktori yg dipilih dan bukan sebaliknya. Kalau begini kondisinya, sudah tentu harddisk eksternal saya akan cepat penuh berhubung Time Machine akan melakukan backup sistem secara keseluruhan.

Sempat mikir juga tuk menggunakan DVCS seperti Git. Namun sejak ingat Git dan DVCS lain akan menduplikasi data yg ada di harddisk internal ke dalam repositori lokalnya juga, pemborosan harddisk akan tetap terjadi. Walau Git melakukan kompresi data, tapi untuk data binari seperti foto rasanya tidak akan begitu berpengaruh. Jadi kalau kita punya foto sebanyak 10GB, maka Git akan menyalinnya ke repositori lokal sehingga total data yg kita simpan bisa mencapai 20GB. Saya jadi ragu tuk menggunakan DVCS tuk membackup data foto.

Loh kok jadi kontradiksi dengan judul?

Tidak, karena tulisan ini belum selesai =P Kekhawatiran tadi akhirnya bisa diakalin sehingga tidak akan terjadi duplikasi data pada harddisk yg sama. Harddisk internet dan eksternal masing-masing akan menyimpan 1 salinan data saja, jadi sangat efisien. Bagaimana caranya?

Caranya adalah dengan meletakkan repositori lokal yang seharusnya ada pada harddisk internal ke harddisk eksternal!

Agar repositori lokal tersebut tetap bisa diakses dari harddisk internal, sebuah symlink digunakan untuk menunjuk direktori repositori lokal yg ada di harddisk eksternal tersebut. Teknik menggunakan symlink ini belum tentu bisa digunakan di seluruh DVCS. Saya sudah mencoba dengan Git dan Bzr dan ternyata keduanya bisa melakukan seluruh skenario yg saya inginkan butuhkan, yang akan saya tunjukkan berikut ini.

Katakanlah direktori yg ingin dibackup adalah ~/Foto/ dan harddisk eksternal ada di /eksternal/

  1. Menginisialisasi repositori

    $ cd Foto
    $ git init
    $ mv .git /eksternal/Foto.git
    $ ln -s /eksternal/Foto.git .git
    
  2. Backup data yang ada

    $ git add .
    $ git commit -a -m "backup"
    

    Proses ini bisa saja dilakukan secara terjadwal. Jangan lupa mengecek dulu apakah harddisk external tsb sedang dipasang atau tidak.

  3. Mengembalikan data dari direktori backup.

     $ mkdir FotoBaru
     $ cd FotoBaru
     $ ln -s /eksternal/Foto.git .git
     $ git checkout HEAD -- .
    

    Selain pake cara di atas, bisa jg lgs git clone direktori /eksternal/Foto.git namun direktori baru yg terbentuk akan membengkak 2x lipat karena berisi repositori lokal dan juga salinan lokal.

    Jika menggunakan Bzr, perintah terakhir diganti menjadi bzr revert

  4. Mengembalikan file tertentu dari sebuah revisi tertentu.

     $ git checkout [revisi] -- [nama/file]
    

    jika menggunakan Bzr, maka perintah di atas menjadi seperti berikut.

     $ bzr revert -r[revisi] [nama/file]
    

Kira-kira seperti itu saja =D ada yang mau mencoba dg DVCS lainnya?

Oh ya.. direktori backup yang ada di harddisk eksternal tidak bisa dibuka begitu saja dengan untuk melihat data-data didalamnya karena data tersimpan dalam format repositori DVCS yang digunakan. Untuk melihatnya tentu saja harus dikembalikan dulu ke salinan lokal dg aplikasi DVCS yang digunakan. Cara ini memang sepertinya hanya ditujukan bagi yang ingin menjadikan harddisk eksternal tsb hanya sebagai tempat backup, bukan tempat berbagi data jg dg orang lain. Asumsinya kalau untuk berbagi data, maka isi harddisk dapat dilihat scr langsung tanpa bantuan aplikasi backup yg dipakai.

Git Philosophy

Dari Advanced Git Tutorial by Sarah Sharp.

Git Philosophy

  • Commit early, commit often.

  • One commit represents one idea or one change.

    • Makes it easy to read patches
    • Easy to revert unwanted changes later
  • Your working directory, index, and local repo are your scratch pads.

Saya sangat setuju dengan seluruh hal di atas =D Sesuatu yang tidak bisa susah dilakukan andai menggunakan centralized vcs.

Yang asik dari …

Beberapa hal dari VCS alias Version Control System yang saya rasa lebih asik daripada VCS yang lain (tentu saja yg pernah saya pakai). Hal-hal menarik yg saya tuliskan di sini adalah hal-hal yang sudah saya pakai. Tentu saja masih banyak hal menarik yg belum saya temukan/rasakan. Silakan ditambahkan kalau mau..

Git

  1. Github
  2. Bikin cabang di tempat yang sama! Jadi ngga perlu ganti2 direktori kalau mau bikin/gabung cabang (ref: git branch).
  3. Tidak perlu pusing mikirin perubahan nama berkas. Perubahan nama berkas secara otomatis tercatat.
  4. Bisa nyomot perubahan dalam sebuah commit pada sebuah cabang untuk diterapkan pada cabang yang lain (ref: git cherry-pick).

Daftar akan terus bertambah xD

Bazaar

  1. Launchpad

Duh.. gak kok gak bisa nemuin yang lain =))

Yang pasti, pada dasarnya Distributed VCS >> Centralized VCS.

Subversion

  1. Google Code Hosting
  2. Repositori “parsial”. Direktori apa saja bisa jadi root directory dari sebuah repositori Subversion.

Itu aja kayanya. Saya bukan penggemar VCS yang terpusat lagi =D