tidak dapat mendorong ke cabang setelah rebase

131

Kami menggunakan git dan memiliki cabang master dan cabang pengembang. Saya perlu menambahkan fitur baru dan kemudian rebase komit ke master, lalu dorong master ke server CI.

Masalahnya adalah jika saya mengalami konflik saat rebase saya tidak bisa mendorong ke cabang pengembang jarak jauh saya (di Github) setelah rebase selesai, sampai saya menarik cabang jauh saya. Ini menyebabkan duplikat komit. Ketika tidak ada konflik, bekerja seperti yang diharapkan.

pertanyaan: setelah rebase dan resolusi konflik, bagaimana cara menyinkronkan cabang pengembang lokal dan jarak jauh saya tanpa membuat duplikat komit

Mempersiapkan:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to '[email protected]:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

EDIT

Jadi sepertinya ini akan memecah alur kerja:

developer1 bekerja pada myNewFeature developer2 yang bekerja pada hisNewFeature keduanya menggunakan master sebagai cabang utama

developer2 menggabungkan myNewFeature ke hisNewFeature

developer1 rebases, menyelesaikan konflik, lalu memaksa mendorong ke cabang jauh untuk myNewFeature

beberapa hari kemudian, developer2, menggabungkan myNewFeature ke dalamNewFeature lagi

Apakah ini akan menyebabkan pengembang lain membenci developer1?

Mat
sumber
bukan solusi tetapi hanya sebuah pemikiran. siapa we? Apakah Anda berada dalam tim yang lebih dari sekadar Anda? theykatakan (orang-orang yang tahu lebih banyak dari saya) bahwa jika Anda membagikan kode Anda, jangan menggunakan rebase. Mengapa tidak Anda hanya melakukan git pulldan git merge?
AdamT
maaf, Kami = tim pengembangan
Matt
1
jadi ya, mungkin seharusnya tidak rebasing ketika Anda berbagi kode. yang mungkin membuat Anda harus melakukan hal-hal seperti apa yang tercantum di bawah ini ( forcepush)
AdamT
oh maaf, ketika mereka berkata rewriting history, itu adalahrebase
AdamT
Seperti yang dia katakan itu adalah cabang pengembangan miliknya sendiri sehingga seharusnya tidak menjadi masalah kecuali seseorang diharapkan untuk menggabungkannya.
Learath2

Jawaban:

93

Pertama, Anda dan mereka yang bekerja dengan Anda harus menyetujui apakah topik / cabang pengembangan adalah untuk pengembangan bersama atau hanya untuk Anda sendiri. Pengembang lain tahu untuk tidak bergabung di cabang pengembangan saya karena mereka akan diubah kapan saja. Biasanya alur kerjanya adalah sebagai berikut:

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

Kemudian untuk tetap up-to-date dengan remote saya akan melakukan hal berikut:

 git fetch origin
 git checkout master
 git merge --ff origin/master

Saya melakukan ini karena dua alasan. Pertama karena memungkinkan saya untuk melihat apakah ada perubahan jarak jauh tanpa perlu beralih dari cabang devel saya. Kedua, ini adalah mekanisme keamanan untuk memastikan saya tidak menimpa perubahan yang tidak disimpan / dilakukan. Juga, jika saya tidak dapat maju dengan cepat bergabung ke cabang master yang berarti seseorang telah mengubah master jarak jauh (yang mana mereka perlu dicambuk dengan parah) atau saya secara tidak sengaja berkomitmen untuk menguasai dan perlu membersihkan tujuan saya.

Lalu ketika remote memiliki perubahan dan saya telah diteruskan dengan cepat ke yang terbaru saya akan rebase:

git checkout devel0
git rebase master
git push -f origin devel0

Pengembang lain tahu bahwa mereka harus mengubah rebase cabang devel saya dari yang terbaru:

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

Yang menghasilkan banyak riwayat bersih:

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

Jangan gabungkan komitmen bolak-balik sesuai keinginan Anda. Tidak hanya membuat duplikat komit dan membuat sejarah tidak mungkin untuk diikuti, menemukan regresi dari perubahan tertentu menjadi hampir tidak mungkin (itulah sebabnya Anda menggunakan kontrol versi di tempat pertama, kan?). Masalah yang Anda alami adalah hasil dari melakukan hal ini.

Juga kedengarannya seperti pengembang lain mungkin membuat komitmen ke cabang devel Anda. Bisakah Anda mengkonfirmasi ini?

Satu-satunya waktu untuk bergabung adalah ketika cabang topik Anda siap untuk diterima master.

Di samping catatan. Jika beberapa pengembang melakukan ke repositori yang sama, Anda semua harus mempertimbangkan memiliki cabang bernama untuk membedakan antara pengembang mengembangkan cabang. Sebagai contoh:

git branch 'my-name/devel-branch'

Jadi semua cabang topik pengembang berada dalam set bersarang mereka sendiri.

Trevor Norris
sumber
1
"Juga kedengarannya seperti pengembang lain mungkin membuat komitmen ke cabang devel kamu. Bisakah kamu mengkonfirmasi ini?" YA mereka ...
Matt
Anda juga membawa saya ke masalah lain. Bekerja antara kantor dan rumah. Saya membuat gabungan di kedua tempat dan pada akhir hari saya mendorong sehingga saya bisa mengambil dari tempat saya tinggalkan. Lalu ketika saatnya untuk rebase, semua komitmen itu menciptakan kebingungan. Saya perlu memperlakukan cabang saya sebagai satu cabang dan rebase
Matt
@ Matt Ya, kedua masalah itu benar-benar akan mengacaukan alur kerja Anda. Untuk yang pertama, saya akan berkomunikasi dengan pengembang lain yang hanya dapat dikomitmenkan oleh pemilik ke cabang yang bernama (mis. 'Matt / devel'). IMHO, tidak ada dua pengembang yang harus berkomitmen ke cabang yang sama. Hanya menciptakan kebingungan. Untuk nanti, rebasing dan memaksa mendorong harus menjaga kedua lokasi tetap terbaru.
Trevor Norris
Jawaban yang bagus Saya punya pertanyaan sampingan, mengapa Anda menggunakan --forcebendera saat melakukannya git push -f origin devel0?
Nobita
2
@Nobita Ketika a git pushtidak bisa maju-cepat (yaitu riwayat sha tidak cocok), Anda harus mendorong untuk menimpa riwayat sebelumnya dengan riwayat baru yang dihasilkan dari git rebase.
Trevor Norris
50

Anda perlu memaksakan dorongan saat Anda telah memindahkan komit lebih jauh ke bawah, git mengharapkan Anda menambahkan komit ke ujung cabang. git push -f origin myNewFeatureakan memperbaiki masalah Anda.

Tip: Di atas adalah penggunaan kekuatan mendorong secara sah. Jangan pernah menulis ulang sejarah di repositori yang dapat diakses publik atau banyak orang akan membencimu.

Learath2
sumber
1
Saya menemukan ini cara paling optimal untuk mempertahankan alur kerja.
Syed Priom
1
Terima kasih sobat. Saya menggunakan perintah ini untuk memaksa cabang lokal saya yang telah diubah ke cabang terpencil yang sama.
wei
11
menggunakan git push --force-with-leasejauh lebih aman daripada menggunakangit push --force
git push --force-with-lease origin HEAD- dengan asumsi cabang target Anda sudah checkout
Lucaci Sergiu
31

Hal utama yang perlu diingat di sini adalah apa yang dilakukan tarik dan rebase di belakang layar.

Tarikan pada dasarnya akan melakukan dua hal: ambil dan gabungkan. Saat Anda memasukkan --rebase, ia akan melakukan rebase alih-alih penggabungan.

Rebase hampir seperti menyimpan semua perubahan lokal Anda sejak Anda bercabang, meneruskan cabang Anda dengan cepat ke komit terbaru pada target, dan membatalkan perubahan Anda secara berurutan.

(Ini menjelaskan mengapa Anda mungkin mendapatkan beberapa resolusi konflik yang diminta saat melakukan rebase vs satu resolusi konflik yang Anda dapatkan dengan penggabungan. Anda memiliki kesempatan untuk menyelesaikan konflik pada SETIAP komitmen yang sedang direstrukturisasi untuk mempertahankan komitmen Anda. )

Anda tidak pernah ingin mendorong perubahan yang dirubah ke cabang jarak jauh karena ini adalah penulisan ulang riwayat. Ofcoarse, tidak pernah sedikit kuat karena hampir selalu ada pengecualian. Contohnya, Anda perlu mempertahankan versi jauh repositori lokal Anda untuk bekerja pada lingkungan tertentu misalnya.

Ini akan mengharuskan Anda untuk mendorong perubahan yang diubah pada waktu baik menggunakan kekuatan:

git push -f origin newfeature

Atau dalam beberapa kasus, administrator Anda mungkin telah menghapus kemampuan untuk memaksa sehingga Anda harus menghapus dan membuat ulang:

git push origin :newfeature
git push origin newfeature

Dalam kedua kasus Anda harus benar-benar yakin Anda tahu apa yang Anda lakukan jika orang lain berkolaborasi dengan Anda di cabang jarak jauh Anda. Ini mungkin berarti bahwa Anda bekerja bersama pada awalnya dengan penggabungan dan rebase mereka ke dalam format komit yang lebih mudah dikelola sebelum pergi untuk menguasai dan menghapus cabang kerja Anda.

Ingat Anda hampir selalu dapat mundur pada git's GC dengan mengambil keuntungan dari:

git reflog

Ini adalah penyelamat hidup BESAR karena Anda dapat mengatur ulang kembali ke keadaan yang lebih stabil jika Anda tersesat dalam semua manajemen rebase / konflik Anda.

Matthew Sanders
sumber
Opsi hapus & buat kembali di atas berfungsi dengan baik untuk saya. Tidak ada pemaksaan yang diizinkan pada repo saya!
Simon Holmes
2

Anda perlu melakukan dorongan paksa, yaitu git push -f origin myNewFeature

Oh, dan Anda lebih baik memastikan bahwa orang-orang tidak mendasarkan apa pun pada cabang dev Anda - biasanya Anda tidak seharusnya menerbitkan cabang tempat Anda menulis ulang sejarah sama sekali (atau lebih tepatnya tidak menulis ulang sejarah setelah diterbitkan). Salah satu cara akan menggunakan nama cabang seperti wip/myNewFeaturedan kemudian menyebutkan bahwa wipcabang akan diubah lagi menjadi master dari waktu ke waktu.

Pencuri
sumber
menggunakan git push --force-with-leasejauh lebih aman daripada menggunakangit push --force
@MrCholo Orang tidak akan mulai menggunakan ini sampai git menambahkan opsi pendek untuk itu seperti -funtuk dorongan paksa yang normal :)
ThiefMaster
ha ya, saya menggunakannya dalam skrip otomatis tho
2

Jawaban umum yang telah diberikan - untuk digunakan git push -f origin myNewFeatureketika mendorong perubahan yang diubah - adalah tempat awal yang baik. Saya menulis jawaban ini untuk mengatasi hasil edit tentang apakah itu akan merusak alur kerja Anda.

Jika kita berasumsi bahwa Anda akan menggunakan git pull --rebase ...(atau beberapa variasi itu) diikuti oleh kekuatan-push to cabang terpencil, maka hal yang istirahat alur kerja dalam contoh Anda developer2 adalah penggabungan myNewFeatureke dalam hisNewFeature. Masuk akal untuk dapat rebase cabang fitur Anda sendiri selama tidak ada orang lain yang bekerja di cabang itu, jadi Anda perlu aturan untuk membatasi wilayah cabang.

Anda dapat menyiasatinya dengan a) menetapkan aturan yang hanya akan Anda gabungkan master, atau b) membuat developcabang kolektif , di mana Anda mendasarkan myNewFeaturecabang Anda sendiri , dan menetapkan aturan yang hanya akan Anda gabungkan develop. masterakan dicadangkan hanya untuk tonggak atau rilis (atau yang lainnya yang Anda ingin atur), dan developakan menjadi tempat Anda mendorong setiap fitur saat siap untuk diintegrasikan ke dalam cabang fitur lainnya.

Saya percaya ini bisa dianggap sebagai versi sederhana dari alur kerja Gitflow.

cosmicFluke
sumber
1

Saya setuju dengan MrCholo , dan mungkin Trevor Norris dapat mempertimbangkan untuk memperbarui jawaban yang baik untuk diganti

git push -f origin devel0

dengan

git push --force-with-lease origin devel0
Sylvain Lesage
sumber