# Feature Keren Git bernama Worktree

Satu fitur Git yang jarang di-*notice* programmer padahal fitur ini sangat-sangat berguna untuk management source code ketika workspace tidak memungkinkan untuk diganggu seperti misal checkout branch, switch branch, rebase atau bahkan merge code. Namanya Git Worktree. Maksudnya bagaimana?

Bayangkan seperti ini, programmer sedang dalam pengerjaan sebuah fitur yang cukup kompleks. Lalu tiba-tiba ada request untuk fixing bug yang cukup critical yang harus di-fix saat itu juga, padahal pada saat yang sama, bisa jadi banyak config yang harus dirubah untuk keperluan testing. Pastinya file config seperti .env tidak diperbolehkan di-*snapshot* oleh git. Sangat merepotkan kalau harus ubah-ubah config hanya untuk fixing sesaat.

Pada situasi seperti itu, programmer yg baru menggunakan Git mungkin akan meng-*copy* semua isi directory *project*\-nya ke directory lain dengan nama yang berbeda.

Asumsinya directory project seperti ini

```plaintext
projects/
│
└── main/
    └── .git/
```

Lalu programmer melakukan cloning projects seperti ini

```plaintext
$ rsync -arlv ./projects/main/ ./projects/hotfix
```

Maka tiap directory project akan memliki `.git` folder masing-masing yang "tidak saling" berkaitan,

```plaintext
projects/
│
├── main-app/
│   └── .git/        // directory history .git
└── hotfix/
    └── .git/        // directory history .git
```

Ketika fixing selesai, programer melakukan testing dan commit pada workspace yang baru tersebut. Tapi yang terjadi adalah historynya berbeda dengan directory utama. Mungkin masalah tersebut bisa diselesaikan dengan cara membuat bridging shared local repository dari dua workspace yang berbeda tersebut. Push dari directory baru ke local shared repository, lalu pull dari directory project utama. Akan sangat merepotkan. selain itu dengan meng-copy semua isi snapshot di folder .git, akan memakan storage yang besar juga. Disitulah *worktree* akan berguna.

*Worktree* memiliki konsep yang serupa seperti flow di atas. Tapi tanpa duplikasi directory .git dan ketika melakukan commit di-*workspace* baru akan masuk juga ke history di *workspace* utama.

### Bagaimana membuat worktree ?

Pertama yang perlu dilakukan sebelum membuat worktree adalah buat branch yang akan digunakan oleh worktree nantinya.

```plaintext
$ cd main
$ git branch hotfix/feature
```

Worktree tidak boleh memiliki branch yang sama yang sedang aktif. oleh karena itu harus dibuat branch sendiri untuk tiap-tiap *worktree* (branching dengan directory sendiri).

Selanjutnya membuat worktree dari branch yang baru dibuat

```plaintext
$ git worktree ../hotfix hotfix/feature
```

struktur directory projects akan menjadi seperti ini

```plaintext
projects/
│
├── main/
│   └── .git/        // directory
└── hotfix/
    └── .git         // file
```

Pada directory *worktree* yang baru dibuat tidak akan memiliki folder .git melainkan sebuah file .git berisi informasi `gitdir` dimana lokasi original dari folder .git. Contoh isi .git file seperti ini

```plaintext
gitdir: /tmp/projects/main/.git/worktress/hotfix
```

Dengan menggunakan *worktree*, maka programmer bisa memiliki banyak *workspace* dengan konfigurasi yang berbeda-beda.

Jika sudah selesai dengan worktree, directory dan meta worktree pada gitu, bisa di-*remove* dengan cara seperti ini

```plaintext
$ git worktree remove ../hotfix
```

Dengan command tersebut, directory *worktree* akan terhapus (tanpa menghapus branch). Tapi jika ternyata tidak sengaja menghapus directory *worktree* secara manual, maka bisa menggunakan command berikut untuk membersihkan meta dari worktree yang berkaitan

```plaintext
$ git worktree prune
```

Untuk listing worktree apa saja yang terbuat, bisa menggunakan command

```plaintext
$ git worktree list
```

Maka akan tertampil list dari worktree yang sudah dibuat.

### Lalu bagaimana saya memanfaatkan worktree?

Saya menggunakan worktree untuk keperluan automatic test, development dan testing building package. kurang lebih struktur seperti ini

```plaintext
projects/
│
├── main-app/
│   └── .git/
├── staging/
│   └── .git
├── testing/
│   └── .git
└── build-test/
    └── .git
```

Masing-masing worktree menggunakan ke konfigurasi database yang bereda. Misal untuk development menggunakan database yang diperbolehkan nutuk diubah-ubah, lalu staging menggunakan database mirip production misal untuk testing migration, sedangkan worktree testing saya gunakan untuk integration test yang mana ada kalanya database khusus testing harus dikosongkan ketika melakukan testing. sedangkan untuk build, ini dipakai untuk uji coba building secara fresh, untuk memastikan tidak ada masalah ketika building package. Worktree build ini akan diremove ketika testing build tidak ada masalah.

Reference:  
https://git-scm.com/docs/git-worktree
