Git non-fast-forward ditolak

88

Saya merasa pertanyaan ini telah ditanyakan berkali-kali, tetapi solusinya biasanya "Saya menghapus direktori dan melakukan kembali pekerjaan saya dengan checkout baru". Saya melakukan komit dan mendorong tetapi menyadari bahwa saya merujuk ke nomor tiket yang salah dalam pesan komit. Jadi saya melihat SO sebentar solusi dan akhirnya mengetik yang berikut ke terminal:

$ git reset --soft HEAD^
$ git commit -m "... correct message ..."

Satu-satunya masalah adalah saya mendapatkan pesan kesalahan berikut:

To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

Saya menggunakan model git-flow dan sedang mengerjakan pengembangan cabang. Bagaimana cara menggabungkan kembali hal-hal untuk membuat git bahagia lagi?

rynmrtn
sumber

Jawaban:

52

Paksa git push:

git push origin +develop
Alan Haggai Alavi
sumber
24
Itu solusinya, tapi baca komentar Brian Campbell sehingga Anda memahami apa yang Anda lakukan sebelum menggunakannya.
thelem
5
git push origin + master
Aniket Thakur
Lihat juga catatan tentang receive.denyNonFastForwardsdalam jawaban Brian Campbell : +atau --forcemungkin tidak cukup kuat, bergantung pada bagaimana mereka — siapa pun mereka — telah mengonfigurasi repositori Git mereka .
torek
174

Jika Anda mendorong komit ke server, dan kemudian menulis ulang yang melakukan secara lokal (dengan git reset, git rebase,git filter-branch , atau manipulasi sejarah lainnya), dan kemudian mendorong yang ditulis ulang berkomitmen kembali ke server, Anda akan mengacaukan orang lain yang telah ditarik. Berikut contohnya; katakanlah Anda telah melakukan A, dan mendorongnya ke server.

- * - * - A <- master

- * - * - A <- origin / master

Sekarang Anda memutuskan untuk menulis ulang A, dengan cara yang Anda sebutkan, menyetel ulang dan melakukan ulang. Perhatikan bahwa ini meninggalkan komit yang menggantung, A, yang pada akhirnya akan menjadi sampah yang dikumpulkan karena tidak dapat dijangkau.

-*-*-SEBUAH
    \
     A '<- master

- * - * - A <- origin / master

Jika orang lain, katakanlah Fred, menarik ke bawah masterdari server saat Anda melakukan ini, mereka akan memiliki referensi ke A, yang mungkin mereka mulai bekerja dari:

- * - * - A '<- master

- * - * - A <- origin / master

- * - * - AB <- fred / master

Sekarang jika Anda dapat mendorong A 'ke origin / master, yang akan membuat non-fast-forward, ia tidak akan memiliki A dalam sejarahnya. Jadi jika Fred mencoba menarik lagi, dia tiba-tiba harus bergabung, dan akan memperkenalkan kembali A commit:

- * - * - A '<- master

- * - * - A <- origin / master

- * - * - AB- \ 
    \ * <- fred / master
     SEBUAH'--/

Jika Fred kebetulan melihat ini, maka dia bisa melakukan rebase, yang akan mencegah komit A muncul kembali. Tetapi dia harus memperhatikan ini, dan ingat untuk melakukan ini; dan jika Anda memiliki lebih dari satu orang yang menjatuhkan A, mereka semua harus melakukan rebase untuk menghindari mendapatkan tambahan A commit di pohon.

Jadi, biasanya bukan ide yang baik untuk mengubah sejarah pada repo yang diambil orang lain. Namun, jika Anda mengetahui bahwa tidak ada orang lain yang menarik dari repo itu (misalnya, itu adalah repo pribadi Anda sendiri, atau Anda hanya memiliki satu pengembang lain yang mengerjakan proyek yang dapat Anda koordinasikan dengan mudah), maka Anda dapat secara paksa perbarui dengan menjalankan:

git push -f

atau

git push origin +master

Keduanya akan mengabaikan pemeriksaan push non-fast-forward, dan memperbarui apa yang ada di server ke revisi A 'Anda yang baru, mengabaikan revisi A sehingga pada akhirnya akan dikumpulkan sampahnya.

Ada kemungkinan bahwa dorongan paksa sepenuhnya dinonaktifkan dengan receive.denyNonFastForwardsopsi konfigurasi. Opsi ini diaktifkan secara default di repositori bersama. Dalam hal ini, jika Anda benar-benar ingin memaksakan dorongan, opsi terbaik adalah menghapus cabang dan membuatnya kembali, dengan git push origin :master; git push origin master:master. Namun, denyNonFastForwardsopsi tersebut diaktifkan karena suatu alasan, yang dijelaskan di atas; pada repositori bersama, itu berarti bahwa sekarang setiap orang yang menggunakannya perlu memastikan bahwa mereka kembali ke riwayat baru.

Pada repositori bersama, secara umum lebih baik untuk hanya mendorong komit baru di atas yang memperbaiki masalah apa pun yang Anda miliki; Anda dapat menggunakan git revertuntuk menghasilkan komit yang akan membatalkan perubahan komit sebelumnya.

Brian Campbell
sumber
pendidikan yang bagus, dan Anda mendapatkan perintah yang tepat pada akhirnya, tetapi cabang saya disebut develop (berdasarkan git-flow), dan orang lain memasukkan +developperintahnya - jadi cek diberikan kepadanya.
Bagaimanapun,
8
Atau gunakan yang kurang samargit push --force
Bennett McElwee
3
@Panique Anda mencoba mengizinkan beberapa orang untuk mengerjakan basis kode yang besar dan kompleks pada saat yang sama, tanpa memblokir satu sama lain (hanya mengizinkan satu orang untuk mengerjakannya pada satu waktu), dan tanpa perubahan yang menimpa satu sama lain. Anda membutuhkan setiap orang untuk dapat membuat perubahan secara mandiri, dan menggabungkan perubahan tersebut. Penggabungan (baik manual atau otomatis) dapat menimbulkan masalah yang tidak terduga; jadi Anda ingin menyimpan informasi sebanyak mungkin untuk mengetahui apa yang terjadi jika terjadi kesalahan. Ini secara intrinsik kompleks; itu tidak kotor, hanya masalah yang sulit.
Brian Campbell
Saya mencoba opsi -f dan + untuk menulis ulang riwayat repo jarak jauh. Di kedua opsi, saya mengalami masalah non-fast-forward. [17.05] $ git push -f origin local_A: remote_A Menghitung objek: 35, selesai. Kompresi delta menggunakan hingga 2 utas. Mengompresi objek: 100% (18/18), selesai. Menulis objek: 100% (21/21), 7,41 KiB, selesai. Total 21 (delta 9), digunakan kembali 0 (delta 0) jarak jauh: Untuk mencegah Anda kehilangan riwayat, pembaruan non-percepat-maju ditolak. Gabungkan perubahan jarak jauh (mis. 'Git pull') sebelum mendorong lagi. Lihat bagian 'Catatan tentang maju cepat' pada 'git push --help' untuk detailnya.
Srikanth
4
@Srikanth Anda dapat sepenuhnya menonaktifkan dorongan paksa dengan receive.denyNonFastForwardsopsi konfigurasi. Opsi ini diaktifkan secara default di repositori bersama. Dalam hal ini, jika Anda benar-benar ingin memaksakan dorongan, opsi terbaik adalah menghapus cabang dan membuatnya kembali, dengan git push origin :remote_A; git push origin local_A:remote_A. Tapi baca apa yang saya tulis di atas tentang mengapa itu ide yang buruk untuk melakukan alur kerja semacam ini pada repositori bersama. Anda harus mencoba melakukan ini hanya jika Anda memiliki sesuatu yang menyebabkan masalah serius dalam commit yang Anda coba singkirkan atau tulis ulang.
Brian Campbell
14

Anda mungkin harus melakukan git pull, yang DAPAT menggabungkan barang secara otomatis untuk Anda. Kemudian Anda dapat berkomitmen lagi. Jika Anda mengalami konflik, itu akan meminta Anda untuk menyelesaikannya.

Perlu diingat, Anda harus menentukan cabang mana yang akan ditarik jika Anda belum memperbarui gitconfig untuk menentukan ...

Sebagai contoh:

git pull origin develop:develop
Tony
sumber
Masih tergila-gila dengan non-fast-forward. Ada pemikiran tentang bagaimana memaksanya untuk bergabung? ! [rejected] develop -> develop (non-fast-forward)
rynmrtn
Saya pikir tombolnya adalah -f tetapi saya bisa saja salah. kernel.org/pub/software/scm/git/docs/git-pull.html
Tony
Ini berfungsi sebagian. Saya tidak melihat pembaruan di github, meskipun (ini menunjukkan komit sebelumnya sebagai yang terbaru bahkan dengan a git push origin develop)
rynmrtn
7

Saya menggunakan EGit dan saya menghadapi masalah ini juga. Baru saja mencoba ke rebasecabang saat ini dan Berhasil.

Nguyen Minh Binh
sumber