Git Minimum yang Layak untuk Pengembangan Berbasis Batang
Lebih sedikit lebih baik dalam hal alat yang kuat — dan terlalu rumit — seperti Git
Eli adalah salah satu pendiri dan Co-CEO dari trunk.io . Dia memegang posisi kepemimpinan teknik di Microsoft, Uber, dan Google (yang mengakuisisi startup yang dia dirikan bersama). Fokus utamanya adalah membantu tim membangun perangkat lunak yang lebih baik, lebih cepat.

Berkembang dalam lingkungan kolaboratif adalah operasi rumit yang melibatkan pelacakan dan koordinasi pekerjaan dari banyak pengembang. Banyak dari kita menggunakan Git sebagai kontrol versi untuk menangani semua perubahan ini. Namun dalam kata-kata Linus sendiri , Git adalah “manajer informasi dari neraka”. Ini menawarkan begitu banyak opsi dan status aneh, Anda dapat dengan mudah menemukan diri Anda berada di tempat yang buruk hingga Anda perlu mengkloning ulang dari awal — bahkan jika Anda tidak melakukan kesalahan apa pun.
Banyak dari kita tahu bahwa satu pengembang yang mempelajari referensi Git dan pohon Merkle yang mendasarinya, tetapi menjadi ahli Git mungkin tidak ada dalam deskripsi pekerjaan Anda. Saya dapat mengendarai mobil dengan sangat baik tanpa memahami cara kerja transmisi yang sebenarnya, dan pada akhirnya, Git hanyalah alat untuk mencapai tujuan.
Untuk mendapatkan hasil maksimal dari Git, Anda harus menggunakannya sesedikit mungkin untuk pengembangan berbasis trunk. Batasi perintah yang Anda gunakan, perbarui cabang fitur Anda dengan benar, dan standarkan penggunaan sebagai sebuah tim. Secara individu, Anda dapat menikmati kebebasan untuk melakukan apapun yang Anda inginkan. Tapi sebagai sebuah tim, harga kebebasan dibayar dengan gesekan.
Batasi tindakan Git Anda
Praktik termudah untuk diterapkan untuk efisiensi puncak Git adalah tetap berpegang pada subset perintah. Git dapat melakukan banyak hal, tetapi sebagian besar kekuatannya hanya ada untuk membantu Anda keluar dari situasi yang mengerikan. Jumlah perintah yang diizinkan Git versus jumlah perintah yang harus Anda panggil sangat berbeda.
Saya pernah diminta oleh CTO untuk memberikan kelas git lanjutan kepada tim tekniknya. Tanggapan saya sederhana:
pada saat Anda membutuhkan git tingkat lanjut — roda mobil sudah terlepas. mari kita fokus menggunakan inti git dengan benar.
Berikut adalah 10 perintah git yang saya gunakan untuk menyelesaikan pekerjaan sambil meminimalkan berapa kali saya mendarat di Git hell:
Manajemen Cabang
git checkout -t -b {branch-name}
Buat cabang, atur upstream ke cabang saat ini, dan alihkan ke sana. Anda juga dapat melakukan ini melalui perintah `git branch`, tetapi dibutuhkan banyak perintah. Karena saya selalu ingin beralih ke cabang saat saya membuatnya, perintah ini lebih ringkas. Buat dan checkout cabang dalam satu gerakan. Saya biasanya menamai semua cabang saya eli/{work-being-done}
.
git checkout {branch-name}
Beralih ke cabang.
git branch -vv
Lihat cabang Anda saat ini dan hulunya.
git branch -D {branch-name}
Hapus cabang lokal, biasanya untuk membersihkan cabang basi/digabung menjadi utama.
Mendorong & Menarik
git fetch origin main:main
Tarik remote main
ke lokal Anda main
, bahkan saat Anda tidak sedang berada di main
cabang! Itulah ; sangat berguna saat Anda mencoba menggabungkan yang terbaru main
ke dalam cabang PR.
git push origin
Dorong kode saya ke remote; kemungkinan memutar banyak mesin di CI untuk memeriksa pekerjaan saya.
git pull
Perbarui cabang lokal saya dengan remote dengan nama yang sama.
Berkomitmen
git add -A .
Tambahkan semua yang sedang saya kerjakan (file baru dan yang diedit).
git commit -am "work"
Lihat di sini untuk menyelami pemikiran saya tentang pesan komit lokal
git merge main
Lebih banyak tentang ini di bawah ini. Saya pragmatis dan bukan rebaser dan senang memperkeruh cabang lokal saya dengan kejadian dari main
.
Selalu perbarui cabang fitur Anda dengan benar
Di bagian terakhir saya , saya membahas bagaimana mengelola kode arahan ke main
. Namun seringkali selama pengembangan, dan tentu saja sebelum penggabungan, Anda harus mengetahui perubahan terbaru main
karena:
- Anda memerlukan beberapa fitur yang ada
main
untuk melakukan pekerjaan fitur Anda. - Sesuatu
main
berubah dan jika Anda tidak mengambilnya, Anda akan merusaknya saat Anda mencoba memasukkan kode Anda. - Anda hanya ingin tetap segar karena Anda seorang insinyur dan menyukai hal-hal baru yang berkilau.
Pintu 1: git merge
Ini adalah strategi gabungan saya. Ini sederhana, andal, dan tanpa embel-embel. Dasar git merge
mengambil semua perubahan yang terjadi main
dan menggabungkannya sebagai komit bersama perubahan Anda. Anda dapat membaca iklan yang memuakkan tentang kerugian dari solusi tanpa embel-embel ini, tetapi sejujurnya saya hanya mengangkat bahu dan berkata, "Saya tidak peduli tentang itu." Jika Anda menggabungkan cabang pekerjaan Anda, main
maka semua omong kosong tentang polusi git-log menjadi hanya itu.
Sejujurnya tidak masalah bagaimana/mengapa/apa yang masuk ke cabang pekerjaan saya. Yang penting adalah — apakah ini dibuat, berfungsi, dan apakah kode melakukan apa yang saya inginkan? Selebihnya akademik.
Dalam praktiknya, dan saya seorang insinyur yang sangat praktis, git merge
memungkinkan Anda untuk menangani konflik gabungan dengan bersih dan kembali membangun. Anda menyelesaikan setiap konflik penggabungan satu kali — dan Anda siap melakukannya. Ini adalah opsi terbaik untuk pemula, pengguna tingkat lanjut yang sibuk, dan Anda yang tidak bermimpi menjadi guru Git.
Pintu 2: git rebase
Ini adalah pilihan terburuk sejauh ini. Oke, saya tahu; praktis ada satu generasi yang melihat rebase vs menggabungkan sesuatu seperti tab vs spasi. Tetapi dalam proyek "nyata", di mana satu atau banyak tim bergabung ke repo setiap hari, rebase membutuhkan penyelesaian n konflik gabungan alih-alih satu dengan rebase gabungan atau squash (lebih lanjut di bawah).
Selain itu, setiap rebasing akan menulis ulang riwayat Git, dan itu berarti jika cabang Anda memiliki mitra jarak jauh, Anda perlu git push --force
menginjak-injak riwayatnya dengan riwayat rebase baru cabang Anda. Ini bagus secara teori tetapi berpotensi untuk secara tidak sengaja menghapus pekerjaan Anda sebelumnya dengan cara yang sangat sulit untuk dipulihkan. Ini jauh lebih berbahaya daripada penggabungan dan sejujurnya membuat saya pusing hanya dengan memikirkannya.
Untuk tujuan artikel ini, saya mencoba mengubah basis hanya untuk mengingatkan diri sendiri betapa saya tidak menyukai alur kerja ini. Lihat apa yang dimuntahkan oleh perintah rebase sederhana ke terminal saya:

Ada banyak kesalahan dengan terminal itu. Saya mendapat catatan tentang komit hash - tidak ingin melihatnya. Saya mendapatkan empat baris petunjuk kuning untuk mengingatkan saya bagaimana semua ini bekerja. Dan saya sekarang dalam beberapa alur kerja hanya untuk mendapatkan kode dari main
cabang saya. Pohon keputusan itu sangat rumit; git rebase --skip
- apa itu?! Mengapa boleh melewatkan komit? Kamu tahu apa? Jangan beritahu saya karena saya memiliki pekerjaan yang harus dilakukan.
Pintu 3: git squash rebase
Anda pasti tidak menginginkan apa yang ada di balik pintu #2, tetapi beberapa orang adalah rebaser yang tangguh. Co-founder saya, co-CEO David Apirian, telah menunjukkan kepada saya pintu masuk rahasianya ke belakang panggung untuk rebase dan itu luar biasa. Kami akan menyebutnya squash rebase .
Saya telah menegaskan kembali pentingnya kesederhanaan Git, tetapi dengan pendekatan ini, Anda dapat memiliki rebase dan memakannya juga. Anda mendapatkan lapisan ajaib dari rebase tanpa kegilaan aliran rebase standar. Dengan rebase squash, Anda dapat:
- Lihat perbedaan dari komitmen lokal Anda sebelum mendorong ke GitHub.
- Batalkan komit terakhir Anda dengan mudah.
- Hindari mencemari pandangan GitHub tentang permintaan penarikan Anda dengan banyak komitmen lokal kecil.
Langkah 1 — hancurkan semua komitmen lokal Anda:
git reset --soft $(git merge-base HEAD main) &&
git commit -am "" --allow-empty-message
git rebase main
Anda dapat menyatukan semua ini menjadi satu perintah uber untuk menarik main terbaru, menghancurkan semua komit Anda, dan mengubah basis pada main terbaru:
git reset --soft $(git merge-base HEAD main) &&
git commit -am "" --allow-empty-message &&
git fetch origin main:main &&
git rebase main
[alias]
smartcommit = !git add -A . && git commit -am "" --allow-empty-message
squash = !git reset --soft $(git merge-base HEAD main) && git commit -am "" --allow-empty-message
squashrebase = !git squash && git fetch origin main:main && git rebase main
smart = !git smartcommit && git squashrebase
Salah satu aspek yang lebih keren dari selalu menekan komitmen lokal Anda adalah bahwa di atas Anda git log
adalah semua pekerjaan yang telah Anda lakukan di cabang. Pekerjaan lokal Anda sekarang lebih mirip dengan tampilan PR yang digabungkan dengan squash saat mendarat di main
.
Anda dapat kapan saja melepaskan komit terakhir dari HEAD dengan cabang lokal Anda dan melihat semua pekerjaan yang telah Anda lakukan main
. Ini mirip dengan tampilan mendetail yang diberikan GitHub tentang apa yang berubah, tetapi memungkinkan Anda untuk tetap berada di terminal dan menghindari peralihan yang membingungkan di antara dua UI yang berbeda.
Saya harus mengakui bahwa pertama kali David menunjukkan kepada saya alur kerja ini, saya terkesan. Dia sebagian besar telah membunuh rebase
naga dan kemampuan untuk melihat secara lokal semua file yang telah Anda ubah di cabang Anda sangat keren.
Sementara squash rebasing membantu Anda mempertahankan kondisi aliran yang lebih baik, sebagian besar pengembang lebih baik menggabungkan saja. Menggunakan rebase atau squash rebase secara tidak benar akan mengakibatkan gesekan yang mematikan produktivitas.
Perangkap bantuan cabang GitHub
GitHub menawarkan pengaturan ini ☝️ untuk menyarankan penggabungan main
secara otomatis ke cabang Anda jika kedaluwarsa. Pengaturan ini seringkali kontra-produktif. Saya ingin cabang lokal saya menjadi satu-satunya sumber kebenaran untuk PR saya, dan tidak ada orang lain (termasuk GitHub) yang mendorongnya. Bekerja dengan GitHub di cabang pribadi saya harus menjadi jalan satu arah. Saya membuat kode secara lokal dan mendorong.
Jika Anda mengonfigurasi GitHub untuk mulai mendorong pembaruan ke cabang pekerjaan Anda, Anda meminta lalu lintas untuk mulai menuju ke arah yang salah. Dan itu resep untuk rasa sakit.
Masalah ini muncul juga ketika peninjau kode memberi Anda sedikit saran komit pada permintaan penarikan Anda dan Anda dengan senang hati menerapkannya. Jika Anda kemudian melakukan pekerjaan apa pun di cabang lokal Anda sebelum menarik perubahan itu… Anda telah membuka sedikit masalah.
Saya sering menemukan bahwa saya tidak sengaja melakukan ini pada diri saya sendiri ketika saya mencoba mendorong pembaruan saya kembali ke jarak jauh dan git memberi tahu saya bahwa saya tidak sinkron. Pada saat itu, saya memiliki dua opsi:
git push --force
dan menerbangkan apa pun di remote bukan di cabang lokal Anda. Umumnya segala sesuatu dengan kata kekuatan bersifat merusak dan membuat putus asa.git merge origin/{my-work-branch}
untuk menggabungkan perubahan jarak jauh ke dalam tampilan lokal cabang.
Pengaturan GitHub ini ️☝️ membutuhkan PR untuk diperbarui main
sebelum bergabung ke dalamnya. Ini umumnya “memecahkan” potensi untuk rusak main
; namun, ini hanya berfungsi dengan repo berkecepatan sangat rendah. Begitu segelintir pengembang mencoba menggabungkan beberapa PR per hari, mereka akhirnya berlomba untuk bergabung main
— atau mendapati diri mereka terus-menerus melakukan penggabungan/rebase main
ke cabang mereka untuk menjadi "terbaru" lagi, dan pada dasarnya berlomba dengan rekan kerja mereka menjadi yang pertama bergabung. Menyakitkan. Biasanya jika Anda menginginkan fitur ini tetapi Anda bukan pengembang tunggal, Anda mungkin menginginkan antrean gabungan — yang merupakan cara yang dapat diskalakan untuk mencapai induk tanpa kerusakan. Ini adalah sesuatu yang kami rasa cukup penting untuk diproduksi dengan Trunk Merge .
Minimalkan Git untuk nilai maksimum
Dengan menjaga penggunaan Git Anda sesederhana mungkin, Anda memberi pengembang lebih sedikit tali untuk menggantung diri dan lebih banyak waktu untuk melakukan pekerjaan pengembangan yang benar-benar penting. Jadikan Git sebagai peran pendukung, dan bukan menjadi protagonis. Untuk mempertahankan lingkungan pengembangan yang waras dan kolaboratif, ingatlah untuk:
- Pilih area permukaan Git terkecil untuk digunakan dan pertahankan.
- Selalu kelola perubahan upstream Anda dengan cara yang sama.
- Standarisasikan praktik di seluruh tim Anda sehingga rekan-rekan Anda juga tidak keluar jalur.