Rebasing dan apa yang dimaksud dengan rebasing komitmen yang didorong

109

Sering dikatakan bahwa, Anda tidak boleh melakukan rebase terhadap komitmen yang telah Anda dorong. Apa artinya itu?

Hemant Kumar
sumber

Jawaban:

80

The book ProGit memiliki penjelasan yang baik .

Jawaban spesifik untuk pertanyaan Anda dapat ditemukan di bagian berjudul " The Perils of Rebasing ". Kutipan dari bagian itu:

Saat Anda melakukan rebase, Anda meninggalkan komitmen yang ada dan membuat yang baru yang serupa tetapi berbeda. Jika Anda mendorong komitmen di suatu tempat dan orang lain menariknya ke bawah dan mendasarkannya pada mereka, lalu Anda menulis ulang komitmen tersebut dengan git rebase dan mendorongnya lagi, kolaborator Anda harus menggabungkan kembali pekerjaan mereka dan hal-hal akan menjadi berantakan saat Anda mencoba melakukannya. menarik pekerjaan mereka kembali ke pekerjaan Anda.

Pembaruan:
Berdasarkan komentar Anda di bawah ini, sepertinya Anda mengalami kesulitan dengan alur kerja Git Anda. Berikut beberapa referensi yang mungkin bisa membantu:

Tim Henigan
sumber
Terima kasih untuk penjelasannya. Jadi, hanya untuk memperjelas pemahaman saya, setelah saya mendorong perubahan tertentu, saya tidak boleh menggunakan git rebase(--interactive?) Untuk menulis ulang histori itu, ini pasti resep gagal. Di sisi lain, jika saya telah mengubah dasar perubahan tertentu pada topik cabang (dari cabang X) dan mendorongnya, itu normal untuk rebase lagi setelah pengembang lain mengubah cabang topik. Pada dasarnya, saya telah menggunakan mergecukup lama, tetapi kami berada dalam perahu yang sama dengan, darwinweb.net/articles/86 dan riwayatnya hampir tidak dapat digunakan.
Hemant Kumar
@Hemant: Rebasing komit setelah mendorong ke repo publik umumnya adalah ide yang buruk. Meskipun demikian, saran dari artikel darwinweb yang Anda kutip terdengar masuk akal jika alur kerja Anda mirip dengan mereka. Lihat tanggapan saya yang diperbarui untuk daftar referensi lain yang mungkin membantu.
Tim Henigan
Harap perbarui tautan ke halaman "ProGit" tentang "Tim yang Dikelola Swasta" ke git-scm.com/book/en/…
Eimantas
Jadi secara teknis, git komit tetap sama tetapi "mengabaikan komit yang ada dan membuat yang baru yang serupa tetapi berbeda" adalah hanya komit yang sama dengan id sha1 berbeda? nah itu akan menjadi satu-satunya cara yang jelas bagi saya untuk memikirkan mengapa kolaborator harus menggabungkan kembali pekerjaan mereka sendiri!
Ciasto piekarz
@Ciastopiekarz, ini karena Anda sedang menulis ulang sejarah di repo upstream, dan repo lokal pengembang lain mungkin memiliki petunjuk untuk itu. Sekarang petunjuk mereka sudah usang: klien git tidak memiliki alternatif selain menggunakan petunjuk yang lebih lama dan bergantung pada manusia untuk menyelesaikan sisanya. Ini adalah penggabungan ulang, dan bisa SANGAT berantakan dengan banyak perubahan membingungkan yang harus diselesaikan secara manual! Oleh karena itu, rekomendasinya untuk tidak pernah mendasarkan kembali apa pun yang sudah didorong ke repo hulu. Ini adalah nasihat yang bagus dan tidak boleh diabaikan kecuali Anda seorang ahli dengan pengetahuan yang mendalam.
Forbin
240

Untuk memahami ini, kita perlu memahami sedikit tentang cara kerja git. Repositori git adalah struktur pohon, di mana simpul dari pohon tersebut terikat. Berikut adalah contoh repositori yang sangat sederhana: Saat Anda bercabang

itu memiliki empat komit pada cabang master, dan setiap komit memiliki ID (dalam hal ini, a, b, c, dan d). Anda akan melihat bahwa d saat ini adalah komit (atau HEAD) terbaru dari cabang master. masukkan deskripsi gambar di sini

Di sini, kami memiliki dua cabang: master dan my-branch. Anda dapat melihat bahwa master dan my-branch keduanya berisi komit a dan b, tetapi kemudian mereka mulai menyimpang: master berisi c dan d, sedangkan my-branch berisi e dan f. b dikatakan sebagai "basis gabungan" dari my-branch dibandingkan dengan master - atau lebih umum, hanya "basis". Masuk akal: Anda dapat melihat bahwa my-branch didasarkan pada versi master sebelumnya.

Jadi katakanlah my-branch telah basi, dan Anda ingin memperbaruinya dengan versi master terbaru. Dengan kata lain, my-branch perlu berisi c dan d. Anda bisa melakukan penggabungan, tetapi itu menyebabkan cabang berisi komit penggabungan aneh yang membuat peninjauan permintaan penarikan jauh lebih sulit. Sebagai gantinya, Anda bisa melakukan rebase.

masukkan deskripsi gambar di sini

Saat Anda melakukan rebase, git menemukan basis dari cabang Anda (dalam hal ini, b), menemukan semua komit antara basis tersebut dan HEAD (dalam hal ini, e dan f), dan memainkan ulang komit tersebut di HEAD cabang Anda rebasing ke (dalam hal ini, master). Git sebenarnya membuat komit baru yang merepresentasikan seperti apa perubahan Anda di atas master: dalam diagram, komit ini disebut e ′ dan f ′. Git tidak menghapus komit Anda sebelumnya: e dan f tidak tersentuh, dan jika ada yang salah dengan rebase, Anda dapat langsung kembali ke kondisi semula.

Saat banyak orang berbeda mengerjakan sebuah proyek secara simultan, permintaan tarik bisa menjadi basi dengan cepat. Permintaan tarik "lama" adalah permintaan yang tidak lagi diperbarui dengan jalur utama pengembangan, dan perlu diperbarui sebelum dapat digabungkan ke dalam proyek. Alasan paling umum mengapa permintaan tarik menjadi basi adalah karena konflik: jika dua permintaan tarik mengubah baris serupa dalam file yang sama, dan satu permintaan tarik digabung, permintaan tarik yang tidak digabungkan sekarang akan memiliki konflik. Terkadang, permintaan tarik bisa menjadi basi tanpa konflik: mungkin perubahan dalam file yang berbeda dalam basis kode memerlukan perubahan yang sesuai dalam permintaan penarikan Anda untuk menyesuaikan dengan arsitektur baru, atau mungkin cabang dibuat ketika seseorang secara tidak sengaja menggabungkan pengujian unit yang gagal ke cabang master. Terlepas dari alasannya,

pseudoCoder
sumber
68

Rebasing menulis ulang sejarah. Jika tidak ada yang tahu tentang sejarah itu, maka itu tidak masalah. Namun, jika sejarah itu diketahui publik, maka penulisan ulang sejarah di Git berfungsi seperti di dunia nyata: Anda memerlukan konspirasi.

Konspirasi sangat sulit untuk disatukan, jadi sebaiknya Anda menghindari rebasing cabang publik sejak awal.

Perhatikan bahwa ada yang contoh konspirasi berhasil: pucabang repositori git Junio C. Hamano ini (repositori resmi dari Git SCM) adalah rebased sering. Cara kerjanya adalah hampir semua orang yang menggunakan pujuga berlangganan milis pengembang Git, dan fakta bahwa pucabang tersebut di-rebased dipublikasikan secara luas di milis dan situs web Git.

Jörg W Mittag
sumber
4
+1. Menurut saya pucabang git.git adalah contoh yang sangat berguna tentang bagaimana menggunakan rebase dalam alur kerja (publik). Bagi mereka yang tidak terbiasa dengannya, ide umumnya adalah untuk me-rebase cabang topik yang tidak memiliki komit di next(cabang yang tidak stabil sebelum menggabungkan ke master), kemudian membangun kembali pucabang dengan mengatur ulang ke next, dan menggabungkan semua cabang topik. (Sumber: Dokumentasi / howto / maintain-git.txt git.kernel.org/?p=git/git.git;a=blob;f=Documentation/howto/… )
Cascabel
25
+1 untuk "menulis ulang sejarah di Git bekerja seperti di dunia nyata: Anda membutuhkan konspirasi"
Sleeper Smith
"Pengumuman publik tidak diperlukan karena pu adalah cabang yang dapat dibuang, seperti dijelaskan di atas." git-scm.com/docs/gitworkflows Kami melakukan sesuatu yang serupa di tempat kerja, "TEMP-sesuatu-terbaru" adalah cabang sekali yang merupakan kombinasi dari perubahan terbaru, bisa jadi merupakan gabungan dari beberapa cabang fitur, dapat dihapus dan diciptakan kembali kapan saja dan tidak boleh dikembangkan.
pilkch
6

Sebuah rebase mengubah sejarah repositori Anda. Jika Anda mendorong komitmen ke dunia, yaitu membuatnya tersedia untuk orang lain, dan kemudian Anda mengubah pandangan Anda tentang riwayat komitmen, akan sulit untuk bekerja dengan siapa pun yang memiliki riwayat lama Anda.

Rebase yang dianggap berbahaya adalah gambaran yang bagus, menurut saya.

dsolimano.dll
sumber