Mengapa saya menggabungkan "cabang pelacakan jarak jauh 'asal / pengembangan' menjadi pengembangan"?

125

Saya satu-satunya di organisasi saya yang membuat komitmen dengan pesan berikut:

Gabungkan cabang pelacakan jarak jauh 'origin / develop' menjadi develop

Tidak yakin apa yang saya lakukan yang menyebabkan mereka, tetapi saya ingin berhenti.

Perintah apa yang saya keluarkan untuk membuat komit ini, dan perintah apa yang tepat yang harus saya gunakan untuk tidak memproduksinya?

Jordan Feldstein
sumber
1
Jawaban yang dibuat oleh Richard Hansen baik-baik saja. Tapi menurut saya ini bisa membingungkan bagi pemula. Solusi saya adalah tetap melakukan pull --rebase tetapi untuk menghindari bahaya, saya menyimpan perubahan saya sebelum menarik. Kemudian, setelah menarik, saya menerapkannya. Saya menyelesaikan konflik. Akhirnya saya bisa berkomitmen & mendorong.
Johnjohn
Apakah git pull --autostash --rebasebekerja untuk Anda @Johnjohn?
sourcecedelica

Jawaban:

206

git pullmungkin membuat komit. Jika Anda membuat komit lokal dan kemudian menjalankan git pullsetelah orang lain mendorong komit ke repositori, Git mengunduh komit pengembang lain dan kemudian menggabungkannya ke cabang lokal Anda.

Bagaimana cara menghindari komitmen gabungan ini di masa mendatang

Anda dapat menggunakan git pull --rebaseuntuk mencegah hal ini terjadi di masa mendatang, tetapi rebasing memiliki risiko sendiri, dan saya sarankan untuk menghindarinya pullsama sekali .

Sebagai gantinya, saya mendorong Anda untuk mengikuti pola penggunaan ini:

# download the latest commits
git remote update -p

# update the local branch
git merge --ff-only @{u}

# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}

Penjelasan

  • git remote update -pmengunduh semua komit di repositori jarak jauh dan memperbarui cabang pelacakan jarak jauh (misalnya, origin/master). Ini TIDAK menyentuh direktori kerja, indeks, atau cabang lokal Anda.

    The -pplum Argumen dihapus cabang hulu. Dengan demikian, jika foocabang tersebut terhapus di originrepositori, git remote update -potomatis origin/fooref Anda akan terhapus .

  • git merge --ff-only @{u}memberi tahu Git untuk menggabungkan cabang upstream ( @{u}argumen) ke dalam cabang lokal Anda tetapi hanya jika cabang lokal Anda dapat "diteruskan dengan cepat" ke cabang upstream (dengan kata lain, jika cabang tersebut belum menyimpang).

  • git rebase -p @{u}secara efektif memindahkan komit yang telah Anda buat tetapi belum mendorong ke atas cabang hulu, yang menghilangkan kebutuhan untuk membuat komit gabungan konyol yang Anda coba hindari. Ini meningkatkan linearitas riwayat pengembangan, membuatnya lebih mudah untuk ditinjau.

    The -ppilihan memberitahu Git untuk melestarikan gabungan. Hal ini mencegah Git melinierisasi komitmen yang dibuat ulang. Ini penting jika, misalnya, Anda menggabungkan cabang fitur menjadi master. Tanpa -p, setiap komit pada cabang fitur akan diduplikasi mastersebagai bagian dari linierisasi yang dilakukan oleh git rebase. Ini akan membuat riwayat perkembangan lebih sulit untuk ditinjau, bukan lebih mudah.

    Waspadalah : git rebasemungkin tidak melakukan apa yang Anda harapkan, jadi tinjau hasilnya sebelum mendorong. Sebagai contoh:

    git log --graph --oneline --decorate --date-order --color --boundary @{u}..
    

Saya lebih suka pendekatan ini git pull --rebasekarena alasan berikut:

  • Ini memungkinkan Anda untuk melihat komit upstream yang masuk sebelum Anda mengubah riwayat Anda untuk memasukkannya.
  • Ini memungkinkan Anda untuk meneruskan opsi -p( --preserve-merges) git rebasejika Anda perlu melakukan rebase pada penggabungan yang disengaja (misalnya, menggabungkan cabang fitur yang sudah didorong ke master).

Singkatan: git upbukangit pull

Untuk mempermudah melakukan hal di atas, saya sarankan membuat alias bernama up:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

Sekarang yang perlu Anda lakukan untuk memperbarui cabang Anda adalah menjalankan:

git up

bukannya git pull. Jika Anda mendapatkan kesalahan karena cabang lokal Anda menyimpang dari cabang hulu, itu isyarat Anda untuk melakukan rebase.

Mengapa tidak git pull --rebase?

Berlari git pull --rebasesetara dengan berlari git fetchdiikuti dengan git rebase. Ini mencoba untuk mempercepat ke komit upstream baru, tetapi jika itu tidak memungkinkan maka itu akan me-rebase komit lokal Anda ke komit upstream baru. Ini biasanya OK, tapi hati-hati:

  • Rebase adalah topik lanjutan, dan Anda harus memahami implikasinya sebelum melakukan rebasing.
  • git pull --rebasetidak memberi Anda kesempatan untuk memeriksa komit sebelum memasukkannya. Tergantung pada apa yang berubah hulu, itu sangat mungkin bahwa rebase adalah salah operasi-a rebase --onto, merge, reset, atau push -fmungkin lebih tepat daripada polos rebase.
  • Saat ini tidak mungkin untuk meneruskan --preserve-mergeske operasi rebase, jadi setiap penggabungan yang disengaja dari cabang fitur akan dilinearisasi, mengulang (dan dengan demikian menggandakan) semua cabang fitur yang berkomitmen.

"Memperbaiki" komit penggabungan yang ada yang dibuat oleh git pull

Jika Anda belum mendorong komit penggabungan yang dibuat oleh git pull, Anda dapat menghapus kembali komit penggabungan. Dengan asumsi Anda belum membuat penggabungan yang disengaja (misalnya, menggabungkan cabang fitur yang sudah didorong ke cabang Anda saat ini), berikut ini yang harus dilakukan:

git rebase @{u}

Perintah di atas memberitahu Git untuk memilih semua komit non-gabungan yang dapat dijangkau dari HEAD(komit saat ini), dikurangi semua komitmen yang dapat dijangkau dari @{u}(yang merupakan singkatan dari "cabang upstream", yaitu, origin/masterjika HEADada master), putar ulang (cherry-pick ) di atas cabang upstream, lalu pindahkan referensi cabang saat ini untuk menunjukkan hasil dari pemutaran ulang komit. Ini secara efektif memindahkan komitmen non-penggabungan ke komit upstream terbaru, yang menghilangkan penggabungan yang dibuat oleh git pull.

Jika Anda memiliki komit penggabungan yang disengaja, Anda tidak ingin menjalankannya git rebase @{u}karena itu akan memutar ulang semuanya dari cabang lain. Menangani kasus ini jauh lebih rumit, oleh karena itu sebaiknya digunakan git updan dihindari git pullsama sekali. Anda mungkin harus menggunakan resetuntuk membatalkan penggabungan yang dibuat oleh pulldan kemudian melakukannya git rebase -p @{u}. The -pargumen untuk git rebasetidak bekerja andal untuk saya, sehingga Anda mungkin akhirnya harus menggunakan resetuntuk membatalkan penggabungan disengaja, memperbarui cabang lokal Anda untuk @{u}, dan kemudian mengulang gabungan disengaja (yang sakit jika ada banyak merge berbulu konflik).

Richard Hansen
sumber
1 untuk mendiskusikan --preserve-merges, kecuali Anda tidak benar-benar mendokumentasikannya dalam perintah yang Anda perintahkan untuk dijalankan, jadi -1 untuk itu.
Seth Robertson
@ Set: Terima kasih atas komentarnya; Saya memperbarui jawaban untuk merekomendasikan -p. Saya menghindari merekomendasikannya sebelumnya karena tidak terlalu sering diperlukan dan perilakunya tidak terdokumentasi dengan baik.
Richard Hansen
3
Apa perbedaan antara git remote update -pdan git fetch?
eckes
3
@eckes: git remote update -psama dengangit fetch --all -p . Saya terbiasa menggunakan git remote update -ppunggung ketika fetchtidak punya -ppilihan.
Richard Hansen
1
@ user1914692: Setelah penggabungan selesai, Git akan memperbarui cabang lokal untuk menunjuk ke komit penggabungan yang baru dibuat, bukan ke komit yang sama seperti cabang jarak jauh. Komitmen gabungan baru ini adalah masalahnya, terutama saat didorong.
Richard Hansen
18
git fetch
git rebase origin/master

Itu harus dilakukan. Atau jika ingin terus menggunakan tarik

git pull --rebase

Anda juga dapat mengatur cabang itu dalam konfigurasi Anda untuk melakukan rebase secara otomatis, atau diatur seperti itu secara otomatis untuk cabang pelacakan lain yang Anda buat di masa mendatang. Kemudian Anda dapat kembali menggunakan

git pull

Lebih lanjut tentang ini di bagian "tarik dengan rebase daripada menggabungkan" halaman ini:

http://mislav.uniqpath.com/2010/07/git-tips/

Adam Dymitruk
sumber