Bagaimana saya bisa menggunakan git rebase tanpa memerlukan dorongan paksa?

94

Dalam upaya mencapai git nirwana, saya menghabiskan hari mempelajari cara memanfaatkan rebase untuk situasi di mana saya saat ini bergabung.

Saat menjalankan apa yang saya anggap sebagai aliran git 101 (yang saya jelaskan di bawah), saya harus melakukannya push --forcesaat mendorong perubahan saya kembali ke asalnya.

Saya bukan satu-satunya - Saya tahu bahwa ini adalah tanah tertutup (lihat 1 , 2 , 3 , 4 , 5 ), dan saya memahami alasan teknis mengapa gaya diperlukan. Masalah saya adalah ini --- ada banyak (banyak) entri blog yang memuji rebase dan bagaimana hal itu mengubah hidup mereka (lihat 1 , 2 , 3 , 4 untuk beberapa daftar), tetapi tidak satupun dari mereka menyebutkan bahwa itu push --forceadalah bagian dari aliran mereka. Namun, hampir setiap jawaban untuk pertanyaan stackoverflow yang ada mengatakan hal-hal seperti "ya, jika Anda akan mengubah basis, ya harus menggunakan push --force".

Mengingat jumlah dan religiusitas pendukung rebase, saya harus percaya bahwa menggunakan 'push --force' bukanlah bagian inheren dari aliran rebase, dan jika seseorang sering harus memaksakan dorongan mereka, mereka melakukan sesuatu yang salah .

push --forceadalah hal yang buruk .

Jadi inilah aliran saya. Dengan cara apa saya bisa mencapai hasil yang sama tanpa kekuatan?

Contoh Sederhana

Dua cabang:

  • v1.0 - cabang rilis, hanya berisi patch
  • master - semuanya untuk rilis mayor berikutnya.

Saya punya beberapa patch komit dan beberapa komit untuk rilis berikutnya.

premerge

Saya ingin memasukkan tambalan ke master saya sehingga tidak hilang untuk rilis berikutnya. Pra-pencerahan, saya cukup:

git checkout master
git merge v1.0

Tapi sekarang saya sedang mencoba

git checkout master
git rebase v1.0

Jadi sekarang saya di sini:

masukkan deskripsi gambar di sini

Waktu untuk:

git push

Tidak ada dadu.

Roy Truelove
sumber

Jawaban:

43

Rebasing adalah alat yang hebat, tetapi akan bekerja paling baik saat Anda menggunakannya untuk membuat penggabungan maju cepat untuk cabang topik ke master. Misalnya, Anda mungkin mendasarkan kembali cabang add-new-widget Anda terhadap master:

git checkout add-new-widget
git rebase -i master

sebelum melakukan penggabungan percepatan cabang menjadi master. Sebagai contoh:

git checkout master
git merge --ff-only add-new-widget

Manfaatnya adalah bahwa riwayat Anda tidak akan memiliki banyak komit penggabungan yang rumit atau konflik penggabungan, karena semua perubahan Anda akan didasarkan pada ujung master sebelum penggabungan. Manfaat sekunder adalah Anda telah melakukan rebased, tetapi Anda tidak harus menggunakan git push --forcekarena Anda tidak melakukan clobbering history pada cabang master.

Itu tentu saja bukan satu-satunya kasus penggunaan untuk rebase, atau satu-satunya alur kerja, tetapi itu salah satu penggunaan yang lebih masuk akal untuk itu yang pernah saya lihat. YMMV.

Todd A. Jacobs
sumber
4
Terima kasih CG, saya pikir "menggunakannya untuk membuat penggabungan maju cepat" adalah kuncinya. Ini tidak berlaku untuk kasus saya di atas di mana saya memiliki dua cabang langsung - cabang pengembangan dan cabang rilis, tetapi tampaknya berlaku sangat baik untuk cabang topik sementara yang hanya diperlukan untuk waktu yang terbatas, dan kemudian bisa dihapus setelah digabungkan. Terima kasih lagi.
Roy Truelove
1
Saya mengerti ini, tetapi pertanyaan aslinya tetap ada. Saya pikir jawaban sebenarnya adalah yang diberikan oleh @Fabien Quatravaux
IsmailS
5
Nah, Anda masih harus memaksakan cabang 1.0, bukan? Setidaknya, begitulah kecenderungan saya sepanjang waktu. Metode Fabiens akan mencegah hal itu terjadi.
joerx
23

@CodeGome benar. Anda sebaiknya tidak me-rebase master pada cabang v1.0 tetapi cabang v1.0 pada master, itu akan membuat semua perbedaan.

git checkout -b integrate_patches v1.0
git rebase master
git checkout master
git merge integrate_patches

Buat cabang baru yang menunjuk ke v1.0, pindahkan cabang baru itu di atas master dan kemudian integrasikan versi baru dari patch V1.0 ke cabang master. Anda akan mendapatkan sesuatu seperti:

o [master] [integrate_patches] Another patch on v1.0
o A patch on v1.0
o Another change for the next major release
o Working on the next major release
|  o [v1.0] Another path on v1.0
|  o A patch on v1.0
| /
o Time for the release

Cara menggunakan rebase ini direkomendasikan oleh dokumentasi resmi git .

Saya pikir Anda benar tentang git push --force: Anda hanya boleh menggunakannya jika Anda membuat kesalahan dan mendorong sesuatu yang tidak Anda inginkan.

Fabien Quatravaux
sumber
Saya rasa ini adalah jawaban terbaik untuk masalah spesifik di OP. Anda membuat cabang penggabungan sementara dan melakukan rebase pada itu, lalu menggabungkan ke master dan mendorong ke asal. Cabang sementara tidak harus didorong ke asal. Satu-satunya saran tambahan yang akan saya berikan adalah memiliki cabang develop atau qa di mana kode gabungan / rebased dapat memenuhi syarat. Setelah kualifikasi, kode ini hanya akan digabungkan dengan ff menjadi master. Ini memungkinkan hotfix yang mudah jika proses kualifikasi Anda memakan waktu terlalu lama. Ini pada dasarnya adalah proses "aliran git".
Javid Jamae
Terima kasih Fabien, jawaban yang bagus. Bagi kita yang hanya ingin mengintegrasikan perubahan ke dalam masterdan tidak keberatan menggabungkan cabang fitur itu sendiri, ini dapat dilakukan dengan:git checkout my-branch; git rebase master; git checkout master; git merge my-branch
Siavas
17

Anda harus memaksa push jika Anda melakukan rebase, dan Anda telah mempublikasikan perubahan Anda, bukan?

Saya menggunakan rebase secara keseluruhan, tetapi saya menerbitkan ke sesuatu yang privat di mana dorongan paksa tidak masalah (misalnya: klon saya sendiri di GitHub, sebagai bagian dari permintaan tarik), atau saya melakukan rebase sebelum saya mendorong untuk pertama kalinya.

Ini adalah inti dari alur kerja di mana Anda menggunakan rebase, tetapi jangan memaksa terlalu banyak: jangan mempublikasikan sesuatu sampai mereka siap, jangan rebase setelah Anda melakukan push.

Daniel Pittman
sumber
Terima kasih Dan. Bisakah Anda memberi tahu saya bagaimana hal di atas harus dicapai? Apakah ini bukan skenario di mana rebase berlaku?
Roy Truelove
2
Jika Anda mengisolasi semua pekerjaan Anda ke cabang topik, maka itu menyiapkan skenario yang baik untuk rebasing. Anda rebasebaru menarik perubahan ke cabang topik Anda, tetapi ketika Anda telah menyelesaikan perubahan cabang itu, Anda mergecabang tersebut kembali ke cabang pengembangan utama.
redhotvengeance
1
Masalahnya adalah Anda telah menerbitkan cabang - jadi Anda perlu memaksa push ke repositori. Anda harus melepaskan salah satu dari keduanya: menerbitkan dengan cara yang Anda lakukan, atau rebasing. Maaf.
Daniel Pittman
Sepertinya rebasing tidak berfungsi untuk skenario ini. v1.0 bukanlah cabang topik, ini adalah cabang rilis, jadi tidak akan pernah mati dan harus dipublikasikan.
Roy Truelove
5

Saya pikir ada kasus penggunaan yang baik untuk pola rebase-kemudian-force-push ini yang bukan hasil dari dorongan yang salah: mengerjakan cabang fitur sendiri dari beberapa lokasi (komputer). Saya sering melakukan ini, karena saya terkadang bekerja di kantor di desktop saya, dan terkadang dari rumah / situs pelanggan di laptop saya. Saya perlu melakukan rebase sesekali untuk mengimbangi cabang utama dan / atau untuk membuat penggabungan lebih bersih, tetapi saya juga perlu mendorong paksa ketika saya meninggalkan satu mesin untuk mengerjakan yang lain (di mana saya hanya menarik). Bekerja seperti pesona, selama saya satu-satunya yang bekerja di cabang.

8forty
sumber
2
Saya memiliki alur kerja yang sama (bekerja dari banyak komputer / lokasi). Jadi, anggap saja Anda sedang mengerjakan cabang topik yang disebut 'mytopic'. Selama Anda selalu me-rebase cabang sekali pakai lokal (yang hanya merupakan cabang dari mytopic) menjadi "master" dan kemudian menggabungkannya kembali ke mytopic, maka Anda tidak perlu memaksakan push. OP memiliki skenario yang sedikit berbeda, jadi dalam kasus seperti itu mungkin diperlukan dorongan paksa. Namun, saya pikir OP melakukan rebasing dengan cara yang salah - jika dia melakukannya seperti yang saya jelaskan maka tidak diperlukan dorongan paksa.
bwv549
3

Inilah yang saya gunakan (dengan asumsi nama cabang Anda adalah foobar ):

git checkout master              # switch to master
git rebase   foobar              # rebase with branch
git merge -s ours origin/master  # do a basic merge -- but this should be empty
git push origin master           # aaand this should work
harum
sumber
2
Rebasing master terlihat aneh.
Emil Vikström
2
gitbukan tanpa kepribadian
harum
1
git merge -s ours origin/<branch>adalah yang memperbaikinya bagi kami
Maks.
0

tl; dr bergabung dengan cabang bersama, rebase dengan cabang individu. --force-with-leaseadalah alternatif yang lebih aman untuk kekuatan dan akan membantu Anda mencapai git nirwana tersebut tanpa sifat kekuatan yang merusak.

Aturan umum yang saya lihat berhasil untuk berbagai alur kerja tim adalah untuk digunakan mergeuntuk cabang bersama (Ie, master atau kembangkan) dan digunakan rebasesaat mengerjakan cabang fitur Anda sendiri. Berikut ini siklus hidup khas dari cabang fitur

git checkout master
git checkout -b new-feature
git commit -am "commit new work"
git push -u origin new-feature
# have code reviewed, run CI, etc.,
# meanwhile master has new commits
git checkout master
git pull
git rebase -i master # -i for interactive rebase allows you to squash intermediate commits
git push --force-with-lease
git merge master

Versi bahasa Inggris sederhana dari apa yang telah kami lakukan di sini:

  1. Membuat cabang baru dari master
  2. Selesai bekerja di cabang dan didorong ke jarak jauh
  3. rebased off master
  4. Dorong pekerjaan ke jarak jauh dengan force-with-lease
  5. bergabung menjadi master dengan log git yang sangat bersih, mengurangi kekacauan dari beberapa penggabungan dari cabang bersama kami untuk membuat cabang kami "menyusul" dengan master terbaru (cabang bersama)

Langkah ke-4 SANGAT penting dan salah satu alasan utama saya mulai menganjurkan penggunaan rebase. force-with-leaseperiksa remote untuk melihat apakah ada komit baru yang telah ditambahkan. Jika Anda git pushterbukti merusak, itu tidak akan mendorong!

Saya harap ini membuat seseorang lebih percaya diri untuk menggunakan rebase.

lucasnad27
sumber