git push --force-with-leasing vs --force

182

Saya mencoba memahami perbedaan antara keduanya

git push --force

dan

git push --force-with-lease

Dugaan saya adalah bahwa yang terakhir hanya mendorong ke remote jika remote tidak memiliki komitmen yang tidak dimiliki cabang lokal ?

Alexander Mills
sumber
" cabang pelacakan jarak jauh lokal ". Pada dasarnya berarti remote harus terlihat seperti apa yang diharapkan klien Anda. git help pushmemiliki use-case yang menjelaskan tujuannya (pada dasarnya untuk menjaga Anda agar tidak merusak perubahan yang baru saja seseorang dorong). Apa yang sedikit tidak jelas bagi saya adalah cara kerja cabang pelacakan jarak jauh. Tapi mungkin itu perlu terlihat persis seperti apa yang terlihat terakhir kali Anda melakukan fetchatau pulltanpa komitmen baru.
zzxyz
4
@zzxyz: implementasi aktualnya --force-with-leasemirip dengan instruksi compare-and-swap pada CPU modern: orang yang menginginkan swap terjadi memasok nilai yang diharapkan dan nilai baru. Sistem yang melakukan swap membandingkan nilai yang diharapkan dengan nilai aktual saat ini, dan melakukan swap jika dan hanya jika keduanya sama. Dengan git push, nilai yang diharapkan adalah apa pun yang ada dalam nama pelacakan jarak jauh, misalnya, git push --force-with-lease origin Xmengirimkan nilai Anda sendiri origin/Xbersama dengan nilai yang diinginkan baru; originGit memberi tahu Anda apakah itu pertukaran, atau tidak.
torek
1
Jika Git di originmelakukan pertukaran, Anda selesai. Jika tidak, Anda dapat berlari git fetch originuntuk mengambil nilai saat ini yang baru , mengolah kembali perubahan Anda jika perlu, dan menjalankan pembandingan dan pertukaran swap-paksa dengan yang lain untuk mencoba lagi.
torek

Jawaban:

173

force menimpa cabang jauh dengan cabang lokal Anda.

--force-with-leaseadalah pilihan yang lebih aman yang tidak akan menimpa pekerjaan apa pun di cabang jarak jauh jika lebih banyak komitmen ditambahkan ke cabang jarak jauh (oleh anggota tim atau rekan kerja lain atau apa pun yang Anda miliki). Ini memastikan Anda tidak menimpa orang lain bekerja dengan paksa mendorong.

Saya pikir ide umum Anda seputar perintah itu benar. Jika cabang jarak jauh memiliki nilai yang sama dengan cabang jarak jauh pada mesin lokal Anda - Anda akan menimpa jarak jauh. Jika tidak memiliki nilai yang sama - ini menunjukkan perubahan yang dilakukan orang lain ke cabang jarak jauh saat Anda sedang mengerjakan kode Anda dan dengan demikian tidak akan menimpa kode apa pun. Jelas jika ada komit tambahan di jarak jauh maka nilainya tidak akan sama.

Saya hanya menganggap --force-with-leasesebagai opsi untuk digunakan ketika saya ingin memastikan saya tidak menimpa kode rekan tim. Banyak tim di perusahaan saya menggunakan --force-with-leasesebagai opsi default untuk gagal-aman. Ini tidak perlu dalam kebanyakan situasi tetapi akan menyelamatkan Anda dari banyak sakit kepala jika Anda menimpa sesuatu yang orang lain berikan pada remote.

Saya yakin Anda melihat dokumen tetapi mungkin ada beberapa penjelasan bertele-tele yang terkandung di sini:

https://git-scm.com/docs/git-push

chevybow
sumber
38

Mencari gambar jawaban dari sumber terpercaya dan / atau resmi.

"Bandingkan dan tukar" yang disebutkan oleh torek dalam komentar dan jawaban lainnya diilustrasikan lebih lanjut oleh sumber - sumber Git itu sendiri .

yang terakhir hanya mendorong ke remote jika remote tidak memiliki komitmen yang tidak dimiliki cabang lokal?

Fitur itu diperkenalkan di komit ini (Desember 2013, Git v1.8.5-rc0)

--force-with-lease akan melindungi semua referensi jarak jauh yang akan diperbarui dengan mengharuskan nilainya saat ini sama dengan beberapa standar wajar, kecuali ditentukan lain;

Untuk saat ini, "beberapa default yang masuk akal" secara tentatif didefinisikan sebagai " nilai cabang pelacakan jarak jauh yang kami miliki untuk referensi jarak jauh yang diperbarui ", dan ini merupakan kesalahan jika kami tidak memiliki cabang pelacakan jarak jauh seperti itu.

Jadi "sewa" berarti:

" force-with-lease": Anda menganggap Anda mengambil sewa pada wasit ketika Anda mengambil untuk memutuskan apa yang seharusnya menjadi sejarah rebased, dan Anda dapat mendorong kembali hanya jika sewa belum rusak.

Sumber masih menyebutkan "cas":

  • Opsi ini pada awalnya disebut " cas" (untuk "bandingkan dan tukar"), nama yang tidak disukai siapa pun karena terlalu teknis.
  • Upaya kedua menyebutnya "lockref" (karena secara konseptual seperti mendorong setelah mengambil kunci) tetapi kata "kunci" dibenci karena menyiratkan bahwa ia dapat menolak dorongan oleh orang lain, yang bukan cara opsi ini bekerja.
  • Putaran ini menyebutnya "paksa-dengan-sewa".
    Anda menganggap Anda mengambil sewa pada referensi ketika Anda mengambil untuk memutuskan apa yang seharusnya menjadi sejarah rebased, dan Anda dapat mendorong kembali hanya jika sewa belum rusak.

Jadi: " git push --force-with-leasevs. --force"

Seperti yang saya sebutkan di " push --force-with-leasesecara default ", seperti Git 2.13 (Q2 2017) menyebutkan, bahwa opsi --force-with-leasedapat diabaikan jika proses latar belakang (seperti yang Anda temukan dalam IDE dengan plugin Git) berjalan git fetch origin.
Dalam hal itu, --forcemenang.

VONC
sumber
29

git push --force merusak karena tanpa syarat menimpa repositori jarak jauh dengan apa pun yang dimiliki secara lokal. push git --force sangat tidak dianjurkan karena dapat menghancurkan commit lain yang sudah didorong ke repositori bersama. Salah satu penyebab kekuatan yang paling umum adalah ketika kita dipaksa untuk rebase cabang.

Sebagai contoh. Kami memiliki proyek dengan cabang fitur yang akan dikerjakan oleh Alice dan Bob. Mereka berdua mengkloning repositori ini dan mulai bekerja. Alice awalnya menyelesaikan bagiannya dari fitur, dan mendorongnya ke repositori utama. Ini semua baik dan bagus. Bob juga menyelesaikan pekerjaannya, tetapi sebelum mendorongnya ia memperhatikan beberapa perubahan telah digabung menjadi master. Ingin menjaga pohon yang bersih, ia melakukan rebase terhadap cabang utama. Tentu saja, ketika dia pergi untuk mendorong cabang rebased ini akan ditolak. Namun tidak menyadari bahwa Alice telah mendorong pekerjaannya, dia melakukan push - force. Sayangnya, ini akan menghapus semua catatan perubahan Alice di repositori pusat.

Apa - Force-with-lease tidak menolak untuk memperbarui cabang kecuali itu adalah keadaan yang kita harapkan; yaitu tidak ada yang memperbarui cabang hulu. Dalam praktiknya ini bekerja dengan memeriksa bahwa ref hulu adalah apa yang kita harapkan, karena ref adalah hash, dan secara implisit menyandikan rantai orang tua ke dalam nilainya.

Berikut ini adalah pos yang bagus mengenai git push --force dan git push --force-with-leasing.

Shakil
sumber
2
apa yang saya tidak mengerti - jika Anda rebase dengan tuan, maka Anda harus bisa mendorong tanpa --force-with-lease ? Mengapa --force-with-leaseperlu setelah rebasing dengan master?
Alexander Mills
3
@AlexanderMills mungkin ada beberapa kemungkinan yang menyebabkan masalah. Jika Anda adalah orang terakhir yang mendorong ini untuk dikuasai maka tidak ada masalah tetapi ada orang lain yang bekerja dengan tugas lain maka itu dapat menyebabkan masalah serius. Katakan pada awalnya A - B - C adalah master, Pada awalnya Alice membuatnya A - B - C - D - E dan saat yang sama Bob membuatnya A - B - C - F - G. Jika Alice adalah orang terakhir yang mendorong master setelah rebasing A - B - C - D - E - F - G tidak akan menyebabkan masalah tetapi orang lain Tom mencoba untuk mendorong A - B - C - D - E - R pada saat yang sama dalam master bencana akan terjadi !! !
Shakil
3
--forcetidak kehilangan komitmen, itu hanya melepaskan mereka. Mereka dapat dibangkitkan dengan hash mereka, seperti dalam git checkout <SHA>atau git reset --hard <SHA>, dengan asumsi pemilik repo jarak jauh tidak melakukan GC atau operasi pemangkasan.
Keith Russell
1
"Dorongan push --force sangat tidak dianjurkan karena dapat menghancurkan commit lain yang sudah didorong ke repositori bersama" pernyataan ini sangat berdasarkan opini. Melakukan push paksa adalah bagian dari alur kerja tinjauan kode git rebase yang normal. Juga seperti disebutkan sudah Anda dapat mengambil komit bahkan setelah melakukan ini.
Étienne
9

Dengan asumsi kait pra-terima di server menerima dorongan, ini akan selalu berhasil:

git push --force

Sedangkan ini menjalankan pemeriksaan sisi klien tertentu sebelum melanjutkan:

git push --force-with-lease

Anda dapat menjalankan pemeriksaan spesifik sendiri secara manual. Inilah algoritma "pemeriksaan-sewa":

  1. Cari tahu cabang Anda saat ini.

  2. Lari git for-each-ref refs/remotes. Perhatikan komit-id yang menurut git Anda sesuai dengan kondisi hulu dari cabang Anda saat ini.

Misalnya, jika Anda menggunakan "foo" cabang, catat kom-id yang terkait dengan "ref / remote / origin / foo".

  1. Tentukan komit aktual dari cabang jarak jauh pada server upstream git sekarang.

  2. Biarkan "git push" berjalan jika komit yang Anda ekstrak dari langkah 2 dan langkah 3 setuju. Dengan kata lain, hanya lanjutkan jika gagasan kloning git lokal Anda tentang hulu setuju dengan hulu yang sebenarnya.

Ada implikasi yang menyedihkan di sini: karena git fetchmemperbarui semua referensi di bawah "ref / remote / origin / *" ke versi terbaru mereka, kombinasi perintah ini pada dasarnya identik dengan git push --force:

git fetch

# The command below behaves identically to "git push --force"
# if a "git fetch" just happened!

git push --force-with-lease

Untuk mengatasi kelemahan bawaan ini, git push --force-with-leasesaya mencoba untuk tidak pernah berlari git fetch. Alih-alih, saya selalu menjalankan git pull --rebasesetiap kali saya perlu menyinkronkan dengan hulu, karena git pullhanya memperbarui satu ref di bawah ref / remote, menjaga "sewa" --force-with-leaseberguna.

G. Sylvie Davies
sumber
1
jika ceknya adalah sisi klien, apakah ada potensi untuk kondisi balapan? yaitu orang lain mendorong perubahan setelah cek tetapi sebelum dorongan paksa?
craq
2

Paksaan-dengan-sewa belum tentu aman. Ini hanya berfungsi seperti yang dikatakan Sylvie. Satu catatan: Dalam git, sebuah cabang hanyalah sebuah pointer pada sebuah commit. Dan komit menunjuk ke nol atau lebih komit induk. Bahkan jika Anda mengubah cabang sepenuhnya dengan reset git keras dan dorongan paksa atau dorongan dengan - - paksa-dengan-sewa tanpa menginginkannya, itu belum tentu masalah besar. Anda dapat menggunakan reflog git lokal Anda untuk melihat bagaimana tip lokal Anda pada cabang (Di mana KEPALA saat itu?) Telah berubah dan mengatur ulang dan mendorong cabang lagi. Maka Anda hanya kehilangan komit baru di cabang terpencil, tetapi bahkan itu dapat dipulihkan oleh anggota tim.

Ikan
sumber