Saya memiliki seorang kolega yang mengklaim itu git pull
berbahaya, dan menjadi marah setiap kali seseorang menggunakannya.
The git pull
perintah tampaknya menjadi cara kanonik untuk memperbarui repositori lokal Anda. Apakah menggunakan git pull
masalah menciptakan? Masalah apa yang diciptakannya? Apakah ada cara yang lebih baik untuk memperbarui repositori git?
git pull --rebase
mengatur strategi ini sebagai default untuk cabang barugit config branch.autosetuprebase
--rebase
tanda untukgit pull
menyinkronkan lokal dengan remote kemudian memutar ulang perubahan lokal Anda di atas lokal yang diperbarui. Kemudian ketika Anda mendorong semua yang Anda lakukan adalah menambahkan komit baru Anda ke ujung remote. Cukup mudah.Jawaban:
Ringkasan
Secara default,
git pull
membuat komit gabungan yang menambahkan kebisingan dan kompleksitas ke riwayat kode. Selain itu,pull
membuatnya mudah untuk tidak memikirkan bagaimana perubahan Anda mungkin dipengaruhi oleh perubahan yang masuk.The
git pull
perintah aman asalkan hanya melakukan penggabungan cepat-maju. Jikagit pull
dikonfigurasi untuk hanya melakukan penggabungan maju-cepat dan ketika penggabungan maju-cepat tidak memungkinkan, maka Git akan keluar dengan kesalahan. Ini akan memberi Anda kesempatan untuk mempelajari komit yang masuk, berpikir tentang bagaimana mereka dapat mempengaruhi komit lokal Anda, dan memutuskan tindakan terbaik (gabung, rebase, atur ulang, dll.).Dengan Git 2.0 dan yang lebih baru, Anda dapat menjalankan:
untuk mengubah perilaku default menjadi hanya maju cepat. Dengan versi Git antara 1.6.6 dan 1.9.x Anda harus terbiasa mengetik:
Namun, dengan semua versi Git, saya sarankan mengonfigurasi
git up
alias seperti ini:dan menggunakan
git up
bukangit pull
. Saya lebih suka alias ini daripadagit pull --ff-only
karena:origin/*
cabang - cabang lama yang tidak lagi ada di hulu.Masalah dengan
git pull
git pull
tidak buruk jika digunakan dengan benar. Beberapa perubahan terbaru pada Git telah membuatnya lebih mudah untuk digunakangit pull
dengan benar, tetapi sayangnya perilaku default dari suatu datarangit pull
memiliki beberapa masalah:git pull
Masalah-masalah ini dijelaskan secara lebih rinci di bawah ini.
Sejarah Nonlinier
Secara default,
git pull
perintah ini setara dengan menjalankangit fetch
diikuti olehgit merge @{u}
. Jika ada komit yang tidak di-cush dalam repositori lokal, bagian gabungan darigit pull
membuat komit gabungan.Tidak ada yang secara inheren buruk tentang gabungan yang dilakukan, tetapi mereka bisa berbahaya dan harus diperlakukan dengan hormat:
Tentu saja ada waktu dan tempat untuk penggabungan, tetapi memahami kapan penggabungan harus dan tidak boleh digunakan dapat meningkatkan kegunaan repositori Anda.
Perhatikan bahwa tujuan Git adalah membuatnya mudah untuk berbagi dan mengonsumsi evolusi basis kode, bukan untuk mencatat sejarah dengan tepat seperti saat dibuka. (Jika Anda tidak setuju, pertimbangkan
rebase
perintah dan mengapa itu dibuat.) Penggabungan yang dilakukan olehgit pull
tidak menyampaikan semantik yang bermanfaat kepada orang lain — mereka hanya mengatakan bahwa ada orang lain yang mendorong ke repositori sebelum Anda selesai dengan perubahan Anda. Mengapa penggabungan tersebut dilakukan jika tidak berarti bagi orang lain dan bisa berbahaya?Dimungkinkan untuk mengonfigurasi
git pull
rebase alih-alih bergabung, tetapi ini juga memiliki masalah (dibahas nanti). Sebagai gantinya,git pull
harus dikonfigurasi untuk hanya melakukan penggabungan maju-cepat.Reintroduksi Komitmen Rebased-out
Misalkan seseorang me-rebet cabang dan memaksa mendorongnya. Ini umumnya tidak boleh terjadi, tetapi kadang-kadang diperlukan (misalnya, untuk menghapus file log 50GiB yang sengaja dikomit dan didorong). Penggabungan yang dilakukan oleh
git pull
akan menggabungkan versi baru dari cabang hulu ke versi lama yang masih ada di repositori lokal Anda. Jika Anda mendorong hasilnya, garpu dan garpu nada akan mulai menghampiri Anda.Beberapa mungkin berpendapat bahwa masalah sebenarnya adalah pembaruan paksa. Ya, pada umumnya disarankan untuk menghindari dorongan kekuatan kapan pun memungkinkan, tetapi kadang-kadang tidak dapat dihindari. Pengembang harus siap menghadapi pembaruan kekuatan, karena hal itu kadang-kadang terjadi. Ini berarti tidak secara membuta menggabungkan komitmen lama dengan yang biasa
git pull
.Modifikasi Direktori Kerja Kejutan
Tidak ada cara untuk memprediksi seperti apa direktori atau indeks kerja sampai
git pull
selesai. Mungkin ada gabungan konflik yang harus Anda selesaikan sebelum Anda bisa melakukan hal lain, itu mungkin memperkenalkan file log 50GiB di direktori kerja Anda karena seseorang secara tidak sengaja mendorongnya, itu mungkin mengubah nama direktori yang sedang Anda kerjakan, dll.git remote update -p
(ataugit fetch --all -p
) memungkinkan Anda untuk melihat komitmen orang lain sebelum Anda memutuskan untuk bergabung atau rebase, memungkinkan Anda untuk membuat rencana sebelum mengambil tindakan.Kesulitan Meninjau Komitmen Orang Lain
Misalkan Anda berada di tengah-tengah membuat beberapa perubahan dan orang lain ingin Anda meninjau beberapa komitmen yang baru saja mereka dorong.
git pull
Operasi gabungan (atau rebase) memodifikasi direktori dan indeks kerja, yang berarti direktori dan indeks kerja Anda harus bersih.Anda bisa menggunakan
git stash
dan kemudiangit pull
, tetapi apa yang Anda lakukan ketika Anda selesai meninjau? Untuk kembali ke tempat Anda sebelumnya, Anda harus membatalkan gabungan yang dibuat olehgit pull
dan menerapkan simpanan.git remote update -p
(ataugit fetch --all -p
) tidak mengubah direktori atau indeks kerja, jadi aman untuk dijalankan kapan saja — bahkan jika Anda telah melakukan dan / atau mengubah unstaged. Anda dapat menjeda apa yang Anda lakukan dan meninjau komit orang lain tanpa khawatir tentang menyembunyikan atau menyelesaikan komit yang sedang Anda kerjakan.git pull
tidak memberi Anda fleksibilitas itu.Rebasing ke Cabang Remote
Pola penggunaan Git yang umum adalah melakukan
git pull
untuk membawa perubahan terbaru diikuti olehgit rebase @{u}
untuk menghilangkan komit gabungan yanggit pull
diperkenalkan. Ini cukup umum bahwa Git memiliki beberapa pilihan konfigurasi untuk mengurangi kedua langkah ini untuk satu langkah dengan mengatakangit pull
untuk melakukan rebase bukannya gabungan (lihatbranch.<branch>.rebase
,branch.autosetuprebase
danpull.rebase
pilihan).Sayangnya, jika Anda memiliki komit gabungan yang tidak dicuri yang ingin Anda pertahankan (mis., Komit yang menggabungkan cabang fitur yang didorong ke dalamnya
master
), baik tarikan rebase (git pull
denganbranch.<branch>.rebase
set ketrue
) maupun tarikan gabungan (git pull
perilaku default ) diikuti oleh rebase akan bekerja. Ini karenagit rebase
menghilangkan gabungan (itu linierkan DAG) tanpa--preserve-merges
opsi. Operasi rebase-pull tidak dapat dikonfigurasikan untuk mempertahankan penggabungan, dan tarikan gabungan diikuti olehgit rebase -p @{u}
tidak akan menghilangkan gabungan yang disebabkan oleh tarikan gabungan. Pembaruan: Git v1.8.5 ditambahkangit pull --rebase=preserve
dangit config pull.rebase preserve
. Penyebab inigit pull
harus dilakukangit rebase --preserve-merges
setelah mengambil komitmen hulu. (Terima kasih kepada funkaster untuk informasi terkini!)Membersihkan Cabang yang Dihapus
git pull
tidak memangkas cabang pelacakan jarak jauh yang terkait dengan cabang yang dihapus dari repositori jarak jauh. Misalnya, jika seseorang menghapus cabangfoo
dari repo jarak jauh, Anda masih akan melihatorigin/foo
.Hal ini menyebabkan pengguna secara tidak sengaja menghidupkan kembali cabang yang mati karena mereka pikir mereka masih aktif.
Alternatif yang Lebih Baik: Gunakan
git up
sebagai gantigit pull
Alih-alih
git pull
, saya sarankan membuat dan menggunakangit up
alias berikut :Alias ini mengunduh semua komit terbaru dari semua cabang hulu (memangkas cabang yang mati) dan mencoba memajukan cepat cabang lokal ke komit terbaru di cabang hulu. Jika berhasil, maka tidak ada komitmen lokal, sehingga tidak ada risiko menggabungkan konflik. Percepat-maju akan gagal jika ada komitmen lokal (tidak dicuci), memberi Anda kesempatan untuk meninjau komitmen hulu sebelum mengambil tindakan.
Ini masih memodifikasi direktori kerja Anda dengan cara yang tidak dapat diprediksi, tetapi hanya jika Anda tidak memiliki perubahan lokal. Tidak seperti itu
git pull
,git up
tidak akan pernah menjatuhkan Anda ke prompt yang mengharapkan Anda untuk memperbaiki konflik gabungan.Pilihan lain:
git pull --ff-only --all -p
Berikut ini adalah alternatif dari
git up
alias di atas :Versi ini
git up
memiliki perilaku yang sama dengangit up
alias sebelumnya , kecuali:-p
argumen, yang diteruskan kefetch
) yang dapat berubah di versi Git yang akan datangJika Anda menjalankan Git 2.0 atau lebih baru
Dengan Git 2.0 dan yang lebih baru, Anda dapat mengonfigurasi
git pull
untuk hanya melakukan penggabungan maju-cepat secara default:Ini menyebabkan
git pull
untuk bertindak sepertigit pull --ff-only
, tetapi masih tidak mengambil semua komitmen upstream atau membersihkanorigin/*
cabang lama jadi saya masih lebih sukagit up
.sumber
git remote update -p
setara dengangit fetch --all -p
. Saya terbiasa mengetikgit remote update -p
karena sekali waktufetch
tidak memiliki-p
opsi. Mengenai pimpinan!
, lihat deskripsialias.*
digit help config
. Dikatakan, "Jika ekspansi alias diawali dengan tanda seru, itu akan diperlakukan sebagai perintah shell."pull.ff
konfigurasi yang tampaknya mencapai hal yang sama, tanpa alias.git up
terdengar seperti alternatif yang menarik.git pull
.Jawaban saya, ditarik dari diskusi yang muncul di HackerNews:
Saya merasa tergoda untuk hanya menjawab pertanyaan dengan menggunakan Hukum Headline Betteridge: Mengapa
git pull
dianggap berbahaya? Bukan itu.sumber
git pull
. Namun, itu mungkin bertentangan dengan beberapa praktik berbahaya, seperti ingin menulis ulang sejarah lebih dari yang diperlukan. Tetapi git fleksibel, jadi jika Anda ingin menggunakannya dengan cara yang berbeda, tentu saja lakukanlah. Tapi itu karena kamu (well, @Richard Hansen) ingin melakukan sesuatu yang tidak biasa di git, dan bukan karenagit pull
berbahaya.git rebase
dan mempertimbangkangit pull
berbahaya? Betulkah?git pull
tanpa--rebase
opsi adalah arah penggabungan yang dibuatnya. Saat Anda melihat perbedaan, semua perubahan dalam penggabungan sekarang menjadi milik orang yang menarik, bukan orang yang membuat perubahan. Saya suka alur kerja di mana penggabungan dicadangkan untuk dua cabang terpisah (A -> B) sehingga komit gabungan jelas apa yang diperkenalkan, dan rebasing disediakan untuk mendapatkan pembaruan di cabang yang sama (jarak jauh A -> lokal A )Tidak dianggap berbahaya jika Anda menggunakan Git dengan benar. Saya melihat bagaimana ini memengaruhi Anda secara negatif karena use case Anda, tetapi Anda dapat menghindari masalah hanya dengan tidak mengubah riwayat bersama.
sumber
git pull
bukan masalah apa pun. Bercabang di git murah.Klaim jawaban yang diterima
tetapi pada Git 1.8.5 , yang setelah tanggal jawaban itu, Anda bisa melakukannya
atau
atau
The docs mengatakan
Diskusi sebelumnya ini memiliki informasi dan diagram yang lebih terperinci: git pull --rebase --preserve-merge . Ini juga menjelaskan mengapa
git pull --rebase=preserve
tidak sama dengangit pull --rebase --preserve-merges
, yang tidak melakukan hal yang benar.Diskusi sebelumnya lainnya ini menjelaskan apa yang sebenarnya dilakukan oleh varian rebate-merge dari rebase, dan bagaimana itu jauh lebih kompleks daripada rebase biasa: Apa sebenarnya yang dilakukan "rebase --preserve-merge" git (dan mengapa?)
sumber
Jika Anda pergi ke git repositori tua git up alias mereka menyarankan berbeda. https://github.com/aanand/git-up
git config --global alias.up 'pull --rebase --autostash'
Ini berfungsi sempurna untuk saya.
sumber