Apakah menggunakan Git Stash sebagai alur kerja sebagai antipattern?

25

Baru-baru ini saya melihat bagaimana saya dan tim saya menggunakan Git dan bagaimana alur kerja kami bekerja. Kami saat ini menggunakan alur kerja cabang fitur yang tampaknya berfungsi dengan baik.

Saya juga melihat beberapa orang di tim kami menggunakan alur kerja berdasarkan simpanan git . Alur kerjanya berjalan seperti ini:

  • Bekerja di cabang utama (seperti master)
  • Buat komitmen saat Anda pergi
  • Jika Anda perlu mendapatkan perubahan atau beralih cabang, dorong perubahan Anda yang tidak dikomit ke simpanan
  • Setelah pembaruan Anda selesai, buang perubahan dari simpanan.

Saya harus menyebutkan bahwa alur kerja ini digunakan sebagai pengganti alur kerja cabang fitur. Alih-alih mengambil cabang dan mengerjakannya, pengembang di sini hanya pernah bekerja pada satu cabang tunggal dan mendorong / pop dari tumpukan sesuai keinginan mereka.

Saya sebenarnya tidak berpikir ini adalah alur kerja yang hebat, dan percabangan akan lebih tepat daripada menggunakan simpanan git dengan cara ini. Saya dapat melihat nilai git simpanan sebagai operasi darurat, tetapi tidak untuk menggunakannya dalam alur kerja harian yang teratur.

Apakah menggunakan git simpanan secara teratur dianggap sebagai anti-pola? Jika demikian, apa saja masalah khusus yang bisa muncul? Jika tidak, apa manfaatnya?

joshin4colours
sumber
2
Anda dapat mencoba bertanya kepada rekan kerja Anda apakah mereka memiliki masalah dengan alur kerja. Jika belum, saya tidak akan menganggapnya berbahaya.
AlexFoxGill
@AlexG Itu poin yang valid. Saya mengajukan pertanyaan di sini untuk melihat apakah ada "gotcha" yang ditemukan orang.
joshin4colours
3
Jika saya mengerti dengan benar ... If you need to get changes or switch branches, push your uncommitted changes onto the stash- thats persis apa simpanan adalah untuk.
3
@MichaelT Cabang lokal saya memungkinkan semuanya. Tanpa syarat.
maaartinus
2
Pola saya adalah: -> jangan gunakan git simpanan -> gunakan cabang fitur -> simpan work-in-progress dengan pesan komit 'wip'. -> rebase interaktif pada cabang untuk menekan wip menjadi satu komit yang berarti tetapi hanya untuk perubahan lokal Anda yang tidak dihapus . -> push to remote -> bergabung menjadi master (dan push) yang sesuai untuk alur kerja git Anda.
Michael Durrant

Jawaban:

31

Dari Git SCM Book :

Seringkali, ketika Anda sedang mengerjakan bagian dari proyek Anda, banyak hal berada dalam keadaan berantakan dan Anda ingin berganti cabang sedikit untuk mengerjakan sesuatu yang lain. Masalahnya adalah, Anda tidak ingin melakukan komitmen pekerjaan setengah jadi hanya agar Anda bisa kembali ke titik ini nanti. Jawaban untuk masalah ini adalah perintah git stash.

Stashing mengambil kondisi kotor dari direktori kerja Anda - yaitu, file yang Anda lacak yang dimodifikasi dan melakukan perubahan - dan menyimpannya di tumpukan perubahan yang belum selesai yang dapat Anda aplikasikan kembali kapan saja.

Dengan uraian ini, saya akan mengatakan ini adalah Pola Anti. Penjelasan Git Stash yang terlalu disederhanakan adalah bahwa itu adalah "Potong dan Tempel" dari kontrol sumber. Anda mengambil banyak file yang diubah, "menyimpannya" dalam pena di luar alur kerja percabangan normal Git, dan kemudian mengajukan kembali perubahan itu ke cabang lain di kemudian hari.

Kembali sedikit lebih jauh, berkomitmen untuk menguasai adalah pola anti di sini. Gunakan cabang. Untuk itulah mereka dirancang.

Ini benar-benar bermuara pada ini:

Anda dapat memalu sekrup ke dinding dan itu akan menahan gambar, tetapi menggunakan obeng adalah apa yang harus Anda lakukan. Jangan gunakan palu saat obeng duduk tepat di samping Anda.

Tentang Komit "Rusak" Kode

Sementara berikut ini adalah opini, saya sampai pada pendapat ini dari pengalaman.

Berkomitmen awal, dan komit sering. Komit sebanyak mungkin kode yang Anda inginkan. Lihat riwayat komit lokal Anda sebagai "save points" saat Anda meretas sesuatu. Setelah Anda melakukan pekerjaan logis, buatlah sebuah komit. Tentu itu bisa menghancurkan segalanya, tapi itu tidak masalah selama Anda tidak mendorong komitmen itu. Sebelum mendorong, rebase dan remas komit Anda.

  1. Buat cabang baru
  2. Hack hack hack
  3. Komit kode yang rusak
  4. Memoles kode dan membuatnya berfungsi
  5. Komit kode kerja
  6. Rebase dan Squash
  7. Uji
  8. Dorong ketika tes lulus

Untuk OP, utas pesan kernal Linux ini mungkin menarik, karena kedengarannya seperti beberapa anggota tim OP menggunakan Git dengan cara yang sama.

@RibaldEddie mengatakan dalam komentar di bawah ini:

Pertama-tama, simpanan bukan di luar "alur kerja percabangan" karena di bawah kap simpanan hanyalah cabang lain.

(dengan risiko menimbulkan kemarahan banyak orang)

Linus berkata:

Dengan "git simpanan", Anda dapat memiliki beberapa hal simpanan yang berbeda juga, tetapi mereka tidak saling mengantri - mereka hanya tambalan independen acak yang Anda simpan karena mereka tidak nyaman di beberapa titik.

Apa yang saya pikirkan @RibaldEddie coba katakan adalah bahwa Anda dapat menggunakan git stashalur kerja cabang fitur - dan ini benar. Bukan penggunaan git stashitu masalahnya. Ini adalah kombinasi dari komitmen untuk menguasai dan menggunakan git stash. Ini adalah pola anti.

Mengklarifikasi git rebase

Dari komentar @ RibaldEddie:

Rebasing jauh lebih mirip copy paste dan bahkan lebih buruk memodifikasi riwayat yang dilakukan.

(Penekanan milikku)

Memodifikasi riwayat komit bukanlah hal yang buruk, asalkan itu adalah sejarah komit lokal . Jika Anda rebase melakukan yang sudah Anda dorong, Anda pada dasarnya akan yatim piatu dengan orang lain menggunakan cabang Anda. Ini buruk.

Sekarang, katakan Anda telah membuat beberapa komitmen selama sehari. Beberapa komitmen bagus. Beberapa ... tidak begitu baik. The git rebaseperintah dalam hubungannya dengan meremas komit Anda adalah cara yang baik untuk membersihkan sejarah komit lokal Anda. Sangat menyenangkan untuk menggabungkan satu komit ke cabang publik karena menjaga komit sejarah cabang bersama tim Anda bersih. Setelah rebasing, Anda akan ingin menguji lagi, tetapi jika tes lulus maka Anda dapat mendorong satu komit bersih daripada beberapa yang kotor.

Ada thread Linux Kernel lain yang menarik tentang clean commit history .

Lagi, dari Linus:

Saya ingin membersihkan sejarah, tetapi itu benar-benar berarti (a) bersih dan (b) sejarah.

Orang dapat (dan mungkin harus) menumbuhkan pohon pribadi mereka (pekerjaan mereka sendiri). Itu pembersihan . Tapi tidak pernah kode orang lain. Itu adalah "menghancurkan sejarah"

Jadi bagian sejarahnya cukup mudah. Hanya ada satu aturan utama, dan satu klarifikasi kecil:

  • Anda tidak boleh pernah menghancurkan sejarah orang lain. Anda tidak boleh mengulangi komitmen yang dilakukan orang lain. Pada dasarnya, jika Anda tidak memiliki sign-off di atasnya, itu terlarang: Anda tidak dapat rebase, karena itu bukan milik Anda.

    Perhatikan bahwa ini benar-benar tentang sejarah orang lain , bukan tentang kode orang lain . Jika mereka mengirim barang kepada Anda sebagai tambalan yang diemailkan, dan Anda menerapkannya dengan "git am -s", maka itu adalah kode mereka, tetapi ini adalah riwayat Anda .

    Jadi Anda bisa menjadi liar pada hal "git rebase" di atasnya, meskipun Anda tidak menulis kode, selama komit itu sendiri adalah milik pribadi Anda.

  • Klarifikasi kecil terhadap aturan: setelah Anda menerbitkan riwayat Anda di beberapa situs publik, orang lain mungkin menggunakannya, dan sekarang jelas bukan riwayat pribadi Anda lagi.

    Jadi klarifikasi kecil sebenarnya adalah bahwa ini bukan hanya tentang "komit Anda", tetapi juga tentang kerahasiaan pada pohon Anda, dan Anda belum mendorongnya dan mengumumkannya.

...

Sekarang bagian "bersih" sedikit lebih halus, meskipun aturan pertama cukup jelas dan mudah:

  • Biarkan riwayat Anda sendiri dapat dibaca

    Beberapa orang melakukan ini hanya dengan menyelesaikan masalah di kepala mereka terlebih dahulu, dan tidak membuat kesalahan. tapi itu sangat jarang, dan bagi kita semua, kita menggunakan "git rebase" dll ketika kita mengerjakan masalah kita.

    Jadi "git rebase" tidak salah. Tapi itu benar hanya jika itu pohon git ANDA SANGAT SENDIRI.

  • Jangan biarkan omong kosong Anda.

    Ini berarti: jika Anda masih dalam fase "git rebase", Anda tidak mendorongnya. Jika belum siap, Anda mengirim tambalan, atau menggunakan pohon git pribadi (seperti "pengganti rangkaian tambalan") yang tidak Anda beri tahu masyarakat luas.

(penekanan milikku)

Kesimpulan

Pada akhirnya, OP memiliki beberapa pengembang melakukan ini:

git checkout master
(edit files)
git commit -am "..."
(edit files)
git stash
git pull
git stash (pop|apply)

Ada dua masalah disini:

  1. Pengembang berkomitmen untuk menguasainya. Kunci ini segera. Sungguh, ini adalah masalah terbesar .
  2. Pengembang terus menggunakan git stashdan git pullmenguasai saat mereka harus menggunakan cabang fitur.

Tidak ada yang salah dengan menggunakan git stash- terutama sebelum tarikan - tetapi menggunakan git stashdengan cara ini adalah pola anti ketika ada alur kerja yang lebih baik di Git.

Mereka menggunakan git stashherring merah. Bukan itu masalahnya. Berkomitmen untuk menguasai adalah masalahnya.

Greg Burghardt
sumber
4
Wow, ini tidak benar. Pertama-tama, simpanan bukan di luar "alur kerja percabangan" karena di bawah kap simpanan hanyalah cabang lain. Gagasan bahwa itu adalah alur kerja salin-tempel tidak masuk akal. Rebasing jauh lebih mirip copy paste dan bahkan lebih buruk memodifikasi riwayat yang dilakukan. Akhirnya, alur kerja Anda sama sekali tidak berguna segera setelah Anda perlu berbagi pekerjaan yang sedang berlangsung dengan kolega karena itu berantakan begitu Anda mendorong perubahan. Bagaimana ini memiliki enam suara adalah membingungkan.
RibaldEddie
8
@RibaldEddie: Tidak ada yang salah dengan rebasing dan penulisan ulang riwayat commit selama itu adalah sejarah commit lokal. Setelah Anda mendorong komitmen tersebut, komentar Anda akan benar, tetapi baca kembali jawaban saya. Dikatakan: "Sebelum mendorong, rebase dan hancurkan komitmen Anda." Itu adalah sejarah commit lokal , yang sepenuhnya di bawah kendali Anda.
Greg Burghardt
1
@RibaldEddie: Saya sudah mengklarifikasi jawaban saya. Itu memang perlu dibersihkan.
Greg Burghardt
Saya akan memberikan lebih banyak konteks dalam jawaban saya sendiri.
RibaldEddie
Lihat jawaban saya di bawah ini - sementara berkomitmen untuk menguasai adalah anti-pola, itu bukan masalah sebenarnya.
RibaldEddie
7

Saya pribadi hanya menggunakan stashuntuk gangguan pendek dan tak terduga, seperti seseorang yang mengajukan pertanyaan yang memerlukan perubahan ke cabang yang berbeda. Saya melakukan ini karena saya sudah lupa tentang simpanan sebelumnya, maka mereka tidak akan berlaku bersih. Komit reguler pada cabang fitur jauh lebih sulit untuk dilupakan, dan lebih mudah untuk digabung, jadi sekarang saya cenderung membuat komit yang rusak, lalu melakukan a git reset HEAD~1atau rebase jika saya tidak ingin menyimpannya nanti.

Namun, hal hebat tentang kontrol versi terdistribusi adalah orang-orang dapat menggunakan alur kerja pilihan mereka dalam repositori mereka sendiri, selama repositori bersama memenuhi standar. Saya akan memastikan orang tidak hanya menggunakan stashalur kerja karena mereka tidak memiliki cukup pelatihan atau kesadaran akan alternatif, tetapi jika mereka masih memilih alur kerja yang Anda temukan kurang optimal, saya akan membiarkannya.

Karl Bielefeldt
sumber
1

Saya pikir bagian dari pertanyaan Anda yang merupakan anti-pola adalah penggunaan satu cabang master bersama . Namun, jika Anda menyertakan cabang pengembangan di samping cabang master dan kemudian menggunakan simpanan untuk menangani sakelar konteks Anda sendiri di cabang pengembangan, itu tidak akan menjadi anti-pola, dan itu sangat erat mencerminkan beberapa alur kerja dijelaskan oleh organisasi seperti Etsy dan Facebook.

Yang telah dikatakan, jawaban @Greg Burghardt di atas agak terlalu menguntungkan untuk apa yang disebut aliran kerja git-flow atau fitur-cabang. Saya dulu menganjurkan untuk strategi yang sama tetapi setelah menyadari bahwa itu menambah kompleksitas yang tidak perlu dan menciptakan rasa aman yang salah, saya tidak lagi melakukannya. Ini juga peninggalan dari hari-hari sistem kontrol versi non-desentralisasi seperti subversi.

Pertama karena Git adalah sistem kontrol versi terdesentralisasi tidak seperti subversi, repositori lokal pengembang pada dasarnya adalah cabang raksasa dari kode itu sendiri. Apa yang dikembangkan individu tidak secara lokal dan tidak seharusnya berdampak pada anggota tim lainnya kecuali kode yang rusak atau bermasalah didorong ke cabang yang dibagikan di repositori bersama.

Perintah rebase, bagaimanapun, dapat merusak sejarah cabang ketika ada konflik gabungan di salah satu komit yang diputar ulang. Dari http://ryantablada.com/post/the-dangers-of-rebasing-a-branch

Sisa dari rebase berjalan dengan lancar, semua ujian tampaknya berlalu. Sebuah PR dibuat.

Dan kemudian beberapa kode lagi ditulis yang bergantung pada properti commentsForAllPosts dan semuanya rusak. Tapi siapa yang kita pergi dan meminta bantuan? git menyalahkan menunjukkan bahwa baris kode hanya ditulis oleh insinyur sisi server dan dia mengangkat tangannya.

Sekarang insinyur front-end Anda sedang berlibur, cuti sakit, atau siapa tahu. Tidak ada yang bisa mengetahui seperti apa kode itu!

Rebase telah membunuh kemampuan tim untuk melihat sejarah untuk menemukan apa yang salah karena konflik gabungan pada cabang anak terbunuh dan kode asli hilang selamanya.

Jika konflik gabungan yang sama ini muncul dan menggabungkan digunakan, kesalahan akan menunjukkan bahwa baris kode telah disentuh dalam proses penggabungan, komit di cabang induk, dan komit di cabang anak. Beberapa bermain-main dengan tiga permutasi dan Anda bisa mendapatkan maksud asli kembali ke basis kode dan bekerja tanpa satu ton kepala menggaruk jari menunjuk. Dan yang Anda miliki hanyalah komitmen lain

Lebih jauh lagi, beberapa model percabangan mengandaikan bahwa tidak ada dua cabang yang bisa mengandung perubahan kode yang saling tergantung. Ketika hal itu benar-benar terjadi, pengembang sekarang harus menyulap lebih banyak cabang agar bekerja secara efisien.

Anti-pola dasar yang saya lihat tidak terkait dengan cabang vs simpanan, tetapi lebih tentang jenis masalah yang telah dibicarakan oleh beberapa orang yang sangat cerdas untuk sementara waktu sekarang: apakah Anda memiliki keyakinan pada kode Anda melalui penggunaan unit test dan arsitektur yang bagus? Apakah Anda dapat membuat perubahan tambahan pada kode Anda sedemikian rupa sehingga pengembang Anda dapat beralasan tentang perubahan dengan mudah dan memahami apa yang akan dilakukan perubahan? Apakah pengembang Anda bahkan menjalankan kode baru sekali untuk melihat apakah itu benar-benar berfungsi? (Ya saya pernah melihat ini sebelumnya).

Jika jawaban untuk pertanyaan-pertanyaan itu adalah tidak, maka tidak masalah berapa banyak cabang yang Anda miliki - pengembang akan mengatakan bahwa kode siap, berfungsi, dan cocok untuk produksi ketika sebenarnya tidak, dan tidak ada jumlah cabang yang akan membantu Anda ketika kode itu tetap berproduksi.

RibaldEddie
sumber
2
Komentar Anda tentang rebasing memiliki masalah dengan resolusi gabungan tidak benar. Rebase adalah jenis gabungan yang sama dengan gabungan sebenarnya. Git hanya menggabungkan komit di bawah tenda. Memulihkan dan menyelesaikan konflik gabungan tidak merusak riwayat komit. Memulihkan kembali dan menyelesaikan konflik gabungan secara tidak benar merusak berbagai hal, yang kemungkinan besar sama dengan gabungan normal. Saya harus setuju bahwa cabang fitur menambah kompleksitas, tetapi ini bisa menjadi kompleksitas yang diperlukan jika pengembang harus menyulap beberapa perubahan yang tidak terkait.
Greg Burghardt
Jadi maksudmu gabungan bisa menghancurkan sejarah ?! Kedengarannya seperti itu lebih banyak pembenaran untuk menghindari memiliki terlalu banyak cabang!
RibaldEddie
1
Penggabungan tidak dapat menghancurkan sejarah. Saya pikir Anda mungkin salah paham bagaimana rebasing dan penggabungan bekerja. Ketika konflik gabungan dipicu, terserah manusia untuk menyelesaikannya. Jika manusia menyelesaikannya dengan salah, Anda tidak dapat menyalahkan Git (atau SVN, atau CVS, atau {masukkan kontrol sumber di sini}).
Greg Burghardt
Sekarang apa yang Anda katakan agak bertentangan dengan apa yang Anda katakan sebelumnya. Apakah Anda membaca artikel yang saya kutip dari? Apakah Anda memahami konteks di mana rebase akan kehilangan sejarah?
RibaldEddie
1
Saya membaca artikel itu. "Di Keen, kami mencoba untuk mendorong kode kami setelah hampir setiap komit." Kedengarannya gila bagi saya. Entah mereka membuat komitmen yang terlalu besar, atau mereka mengeluarkan kode yang belum siap. Jika Anda segera mengumumkan semua komitmen Anda, maka ya, memundurkan akan menyebabkan masalah. Ini prinsip "Dokter, dokter, sakit ketika aku melakukan ini".
Kyralessa
1

git stashadalah alat. Itu sendiri bukanlah suatu pola, juga bukan anti-pola. Ini adalah alat, seperti palu adalah alat. Menggunakan palu untuk menggerakkan paku adalah sebuah pola dan menggunakan palu untuk menggerakkan sekrup adalah pola anti. Demikian juga, ada alur kerja dan lingkungan di mana git stashalat yang tepat untuk digunakan, dan alur kerja dan lingkungan di mana itu salah.

Alur kerja 'semua orang berkomitmen dan mendorong ke arus utama' adalah yang bekerja cukup masuk akal di mana tidak ada perubahan risiko tinggi. Ini sering terlihat digunakan dalam lingkungan svn di mana ada satu server pusat otoritatif yang memiliki kode.

Git, bagaimanapun, ada hubungannya dengan server pusat. Setelah semua pengembang melakukan commit, pull(atau rebasejika Anda suka itu), pushsepanjang waktu dapat membuat kekacauan besar.

Masalah terbesar muncul ketika Anda memiliki sesuatu yang sedang berjalan yang rusak dan Anda perlu mengerjakan bug prioritas. Ini berarti Anda perlu sedikit mengesampingkan pekerjaan itu, mengambil yang terbaru, mengerjakannya tanpa memiliki pekerjaan sebelumnya yang sedang berjalan menyebabkan masalah dengan bangunan yang Anda coba lakukan.

Untuk ini, git stashakan menjadi alat yang tepat untuk digunakan.

Namun, ada masalah yang lebih besar yang mengintai di jantung alur kerja ini. Apakah adalah bahwa semua peran cabang kontrol versi berada di cabang tunggal. Arus utama, pengembangan, pemeliharaan, akumulasi, dan pengemasan semuanya ada di Master. Ini masalah. (Lihat Strategi Cabang SCM Lanjutan untuk lebih lanjut tentang pendekatan ini ke cabang)

Dan ya, Anda memang memanggilnya bahwa itu bukan alur kerja yang hebat dan bahwa ada masalah dengannya. Namun, masalahnya bukan pada alat git stash. Masalahnya adalah kurangnya percabangan yang berbeda untuk peran atau untuk kebijakan yang tidak kompatibel .

git stashNamun, adalah sesuatu yang saya gunakan ketika saya memiliki situasi di mana saya telah membangun sedikit, dalam keadaan lengket yang saya tidak yakin apakah itu yang benar ... jadi saya menyembunyikan perubahan saya dan kemudian mengeksplorasi pendekatan lain untuk memecahkan masalah tersebut. Jika itu berhasil - hebat, buang barang-barang di simpanan dan lanjutkan. Jika eksplorasi lain menjadi lebih lengket kemudian reset kembali ke perubahan sebelumnya dan mengajukan kembali simpanan untuk mengerjakannya. Alternatifnya adalah dengan melakukan, checkout, cabang dan kemudian melanjutkan pada cabang baru ini atau kembali dan mengatur ulang. Pertanyaannya adalah apakah itu benar-benar layak dimasukkan ke dalam sejarah ketika itu hanya sesuatu yang ingin saya jelajahi sebentar?

git stashbukan pola anti. Menggunakan git stashsebagai alternatif untuk bercabang sementara semua orang berkomitmen untuk Master adalah anti pola - tetapi bukan karena git stash.

Jika Anda belum menekannya, tunggulah sampai Anda memiliki masalah dengan build , ketika seseorang perlu membuat perubahan arsitektur yang signifikan pada banyak file (dan konflik gabungan) atau beberapa pekerjaan yang belum teruji dalam kode progres yang bocor ke produksi untuk ini anti-pola untuk mengejar ketinggalan dengan Anda.

Komunitas
sumber