git - melewatkan komit tertentu saat penggabungan

200

Saya telah menggunakan Git selama sekitar satu tahun sekarang dan menganggapnya fantastis, tetapi saya baru saja memulai versi kedua dari proyek dan memulai cabang baru untuk itu. Saya berjuang sedikit dengan cara terbaik untuk menangani hal-hal ke depan.

Saya memiliki dua cabang yang disebut katakanlah master10 (untuk v1) dan master20 (untuk v2). Saya telah membuat perbaikan bug di v1 pada master10 cabang, dan mengembangkan hal baru dari master20. Setiap kali saya melakukan perbaikan bug saya menggabungkannya ke v2 dengan memeriksa master20 dan melakukan git merge master10. Sejauh ini baik.

Namun sekarang, saya telah membuat perubahan pada v1 yang tidak saya inginkan di v2, tetapi saya ingin terus menggabungkan perbaikan bug lainnya. Bagaimana cara saya memberi tahu Git untuk melewati commit tertentu (atau serangkaian commit), tetapi ke depan saya masih ingin menggabungkan perbaikan bug lainnya.

Saya pikir git rebasemungkin yang saya butuhkan tetapi membaca dokumen dan kepala saya hampir meledak.

Saya pikir apa yang saya inginkan adalah sesuatu seperti perintah "git sync" yang memberi tahu git bahwa dua cabang sekarang dalam sinkronisasi dan di masa depan hanya menggabungkan komit dari titik sinkronisasi ini aktif.

Setiap bantuan dihargai.

Brad Robinson
sumber

Jawaban:

289

Jika Anda ingin menggabungkan sebagian besar tetapi tidak semua komit di cabang "Maint" ke "Master", misalnya, Anda bisa melakukan ini. Itu memerlukan beberapa pekerjaan ---- seperti yang disebutkan di atas, kasus penggunaan yang biasa adalah untuk menggabungkan semuanya dari cabang --- tapi kadang-kadang terjadi bahwa Anda membuat perubahan ke versi rilis yang tidak boleh diintegrasikan kembali (mungkin kode itu adalah sudah digantikan di master sudah), jadi bagaimana Anda mewakili itu? Ini dia ...

Jadi anggap saja maint memiliki 5 perubahan yang diterapkan, dan salah satu dari itu (maint ~ 3) tidak dapat digabungkan kembali menjadi master, meskipun semua yang lain seharusnya. Anda melakukan ini dalam tiga tahap: sebenarnya menggabungkan semuanya sebelum yang satu itu, beri tahu git untuk menandai maint ~ 3 digabungkan bahkan ketika tidak, dan kemudian gabungkan sisanya. Keajaibannya adalah:

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

Perintah pertama menggabungkan semuanya sebelum pemeliharaan bermasalah Anda menjadi master. Pesan log penggabungan default akan menjelaskan Anda menggabungkan "branch 'Maint (bagian awal)".

Perintah kedua menggabungkan Maintom 3 yang bermasalah, tetapi opsi "-s our" memberitahu git untuk menggunakan "strategi penggabungan" khusus yang, pada kenyataannya, bekerja dengan hanya menjaga pohon yang Anda gabungkan dan mengabaikan komit (s ) Anda menggabungkan sepenuhnya. Tapi itu masih membuat komitmen gabungan baru dengan HEAD dan mempertahankan ~ 3 sebagai orang tua, sehingga grafik revisi sekarang mengatakan bahwa maint ~ 3 digabungkan. Jadi sebenarnya Anda mungkin ingin menggunakan opsi -m untuk 'git merge' juga, untuk menjelaskan bahwa maint ~ 3 commit sebenarnya diabaikan!

Perintah terakhir hanya menggabungkan sisa maint (maint ~ 2..maint) menjadi master sehingga Anda semua disinkronkan lagi.

araqnid
sumber
5
Saya pikir bahwa jika Anda perlu menunda penggabungan komit itu, Anda punya sedikit pilihan selain melewatinya (menggabungkan -s milik kami) dan kemudian menerapkannya menggunakan perintah cherry-pick. Setelah komit dapat dijangkau dari master, komit tidak dapat digabungkan lagi - menghindari menggabungkan perubahan yang sama dua kali adalah salah satu tujuan utama git.
araqnid
3
Mengenai contoh cabang pembantu Anda: Saya menduga bahwa setelah Anda menggabungkan cabang pembantu Anda berada dalam situasi yang persis sama dengan Anda setelah langkah kedua dari posting saya. Membuat cabang tambahan tidak ada bedanya dengan hubungan komit.
araqnid
5
Hanya karena ketertarikan, jika Anda hanya ingin menghilangkan satu perubahan, mengapa Anda tidak hanya melakukan satu penggabungan dan kemudian mengembalikan satu perubahan itu, daripada melakukan tiga penggabungan? Ini akan menghasilkan lebih sedikit perubahan yang dilakukan pada repositori dan riwayat yang lebih eksplisit.
Mark Booth
3
Seringkali lebih mudah untuk secara eksplisit memberi nama komit. Jadi, Anda hanya perlu melihat log git dari cabang yang akan digabungkan dan mencatat hash dari commit yang tidak boleh digabungkan dan yang sebelumnya - daripada menghitung komit ...
zwirbeltier
14
@MarkBooth: Komit yang ingin Anda lewati mungkin berada dalam konflik besar dengan cabang yang ingin Anda gabungkan. Lebih mudah melompatinya daripada memperbaiki konflik lalu mengembalikan perubahan itu dan memperbaiki konflik lagi
SztupY
39

IMHO, hal yang paling logis untuk dilakukan, adalah menggabungkan semuanya, dan kemudian menggunakan git revert (commit_you_dont_want) untuk menghapusnya .

Contoh:

git merge master
git revert 12345678

Jika Anda memiliki beberapa komitmen "untuk-abaikan", atau ingin mengedit pesan kembalikan:

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

Maka riwayat Anda mungkin terlihat seperti:

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

Jika Anda memiliki konflik yang melibatkan HANYA untuk "mengabaikan" ini, Anda dapat menggunakan:

git merge master -X ours

Jadi versi Anda akan bertahan dibandingkan yang lain. Bahkan tanpa pesan kesalahan, Anda mungkin masih "mengembalikan" komitmen yang tidak diinginkan itu, karena mereka mungkin memiliki perubahan lain yang tidak bertentangan, dan Anda masih tidak menginginkannya.

Jika Anda memiliki konflik yang melibatkan TIDAK HANYA komitmen "untuk-abaikan", Anda harus menyelesaikannya secara manual, dan Anda mungkin harus menyelesaikannya lagi selama kembali.

Alexandre T.
sumber
2
Jika kemudian Anda ingin menggabungkan komitmen yang dikembalikan tersebut ke cabang menjadi pertanyaan, apakah Git masih mengabaikannya?
Anriëtte Myburgh
@ AnriëtteMyburgh Anda dapat mengembalikan komitmen pengembalian untuk kemudian menggabungkannya menjadi sesuatu yang sebenarnya tidak dapat Anda lakukan dengan mudah dengan strategi "menggabungkan-milik kita".
Lily Chung
Terima kasih, ini adalah persis apa yang saya butuhkan memiliki beberapa komitmen yang lebih tua di cabang fitur yang saya tidak inginkan dalam master dan banyak yang saya inginkan dalam master. Bagus dan bersih.
Vale Trujillo
17

Komit termasuk keturunan. Anda tidak dapat menggabungkan komit tanpa menggabungkan komit sebelumnya.

Anda bisa memilihnya, tentu saja. Itu aliran yang baik ketika Anda memiliki cabang yang dalam mode pemeliharaan.

Dustin
sumber
1
Terima kasih, cherry pick akan melakukan pekerjaannya. Tidak sebagus yang saya harapkan tetapi itu akan berhasil.
Brad Robinson
3

Semacam iklan untuk proyek saya yang pada dasarnya membungkus proses yang dijelaskan oleh @araqnid.

Ini semacam pembantu yang memperkenalkan alur GIT berikut:

  • ada pemberitahuan harian / mingguan tentang gabungan yang tertunda dari cabang pemeliharaan ke cabang dev / master
  • pengelola cabang memeriksa status dan memutuskan sendiri apakah semua komitmen diperlukan dan memblokir mereka atau meminta pengembang untuk memblokir diri mereka sendiri. Pada akhirnya cabang pemeliharaan digabung ke dalam upsteam.

Kutipan dari halaman proyek:

Bergantung pada alur kerja, dimungkinkan untuk memiliki cabang khusus untuk pemeliharaan atau pelanggan bersama dengan cabang utama. Cabang-cabang ini juga disebut cabang LTS.

Seringkali hot fix masuk ke cabang tempat bug dilaporkan dan kemudian komit digabung kembali ke cabang master.

Praktik umum adalah memiliki semua cabang disinkronkan dengan sempurna dengan master, yaitu Anda ingin melihat delta yang jelas antara cabang tertentu dan master untuk memahami apakah master berisi semua fitur dan perbaikan bug.

Namun terkadang Anda tidak ingin melakukan komitmen tertentu karena mereka khusus untuk pelanggan dan tidak akan terlihat oleh pengguna lain. Atau cabang master Anda menyimpang jauh sehingga membutuhkan pendekatan yang sama sekali berbeda untuk memperbaiki masalah, atau bahkan lebih baik, masalahnya tidak lagi ada di sana.

Juga dalam hal sakura memilih dari master ke cabang pemeliharaan komit yang dihasilkan harus diblokir di master.

Dmytro
sumber
0

Buat cabang ketiga untuk perubahan yang Anda inginkan di master10 tetapi tidak di master20. Selalu anggap master10 sebagai "tuan" Anda, cabang paling stabil dari semuanya. Cabang yang ingin disinkronkan semua cabang lainnya setiap saat.

wilhelmtell
sumber
Saya kira itu bisa berhasil, tetapi saya sudah masuk ke keadaan ini, dan cabang ketiga mungkin akan membingungkan saya lebih banyak lagi. :)
Brad Robinson
0

Daripada revertatau cherry-pickuntuk kasus ini, Anda perlu meminta git untuk mempertimbangkan perubahan yang Anda lewati menjadi lebih tua dari yang Anda buat.

Begitu:

  1. gabungkan komit terakhir sebelum komit yang ingin Anda lewati. Ini tentu saja akan menggabungkan semua komitmen sebelumnya. git merge ccc
  2. gabungkan komit yang ingin Anda lewati. git merge fff --no-commit
  3. tahap penggabungan, hapus tahapan semua perubahan, batalkan semua perubahan. (Mungkin ada perintah bodoh untuk ini, tapi saya hanya akan melakukan bagian ini di UI - namun Anda tahu caranya)
  4. selesaikan penggabungan yang kosong git merge --continue
  5. gabungkan komit SETELAH yang ingin Anda lewati. git merge source-branch-head

Setelah Langkah 4, git akan menganggap cabang Anda lebih baru dari komit itu, karena Anda sudah menanganinya (dengan memilih untuk menyimpan versi-versi ANDA).

Jason Kleban
sumber