Tidak terlalu terkait dengan jawaban ini, tetapi saya akan membuang git pull, yang hanya git fetchdiikuti oleh git merge. Anda melakukan tiga penggabungan, yang akan membuat Git Anda menjalankan tiga operasi pengambilan, dan Anda hanya memerlukan satu pengambilan. Karenanya:
git fetch origin # update all our origin/* remote-tracking branches
git checkout demo # if needed -- your example assumes you're on it
git merge origin/demo # if needed -- see below
git checkout master
git merge origin/master
git merge -X theirs demo # but see below
git push origin master # again, see below
Mengontrol penggabungan tersulit
Bagian yang paling menarik di sini adalah git merge -X theirs. Seperti yang dicatat root545 , -Xopsi diteruskan ke strategi penggabungan, dan baik recursivestrategi default maupun resolvestrategi alternatif mengambil -X oursatau -X theirs(satu atau yang lain, tetapi tidak keduanya). Namun, untuk memahami apa yang mereka lakukan, Anda perlu tahu bagaimana Git menemukan, dan memperlakukan, menggabungkan konflik .
Konflik penggabungan dapat terjadi dalam beberapa file 1 ketika versi dasar berbeda dari versi saat ini (juga disebut lokal, HEAD, atau --ours) dan versi lain (juga disebut jarak jauh atau --theirs) dari file yang sama. Artinya, penggabungan telah mengidentifikasi tiga revisi (tiga komit): basis, milik kita, dan milik mereka. Versi "base" adalah dari gabungan dasar antara komit kita dan komit mereka, seperti yang ditemukan di grafik komit (untuk lebih banyak lagi tentang ini, lihat posting StackOverflow lainnya). Git kemudian menemukan dua rangkaian perubahan: "apa yang kami lakukan" dan "apa yang mereka lakukan". Perubahan ini (secara umum) ditemukan baris demi baris, murni tekstualdasar. Git tidak benar-benar memahami isi file; itu hanya membandingkan setiap baris teks.
Perubahan ini adalah apa yang Anda lihat dalam git diffkeluaran, dan seperti biasa, mereka juga memiliki konteks . Mungkin saja hal-hal yang kita ubah berada pada baris yang berbeda dari hal-hal yang diubah, sehingga perubahan tersebut tampak seperti tidak akan bertabrakan, tetapi konteksnya juga telah berubah (misalnya, karena perubahan kita dekat dengan bagian atas atau bawah file, sehingga file tersebut habis dalam versi kami, tetapi dalam versi mereka, mereka juga menambahkan lebih banyak teks di bagian atas atau bawah).
Jika perubahan terjadi di baris yang berbeda — misalnya, kami mengubah colorke colourbaris 17 dan berubah fredke barneybaris 71 - maka tidak ada konflik: Git hanya mengambil kedua perubahan tersebut. Jika perubahan terjadi pada baris yang sama, tetapi merupakan perubahan yang identik , Git akan mengambil satu salinan dari perubahan tersebut. Hanya jika perubahan berada pada baris yang sama, tetapi merupakan perubahan yang berbeda, atau kasus khusus dari konteks yang mengganggu, Anda mendapatkan konflik modifikasi / modifikasi.
The -X oursdan -X theirspilihan memberitahu Git bagaimana menyelesaikan konflik ini, dengan memilih hanya salah satu dari dua perubahan: kita, atau mereka. Karena Anda mengatakan Anda menggabungkan demo(milik mereka) ke master(milik kami) dan menginginkan perubahan dari demo, Anda pasti menginginkannya -X theirs.
-XNamun, penerapan secara membabi buta berbahaya. Hanya karena perubahan kami tidak bertentangan baris demi baris tidak berarti perubahan kami tidak benar-benar bertentangan! Satu contoh klasik terjadi dalam bahasa dengan deklarasi variabel. Versi dasar mungkin mendeklarasikan variabel yang tidak digunakan:
int i;
Dalam versi kami, kami menghapus variabel yang tidak terpakai untuk membuat peringatan compiler pergi-dan mereka versi, mereka menambahkan satu lingkaran beberapa baris kemudian, menggunakan isebagai loop counter. Jika kita menggabungkan dua perubahan tersebut, kode yang dihasilkan tidak lagi dapat dikompilasi. The -Xpilihan adalah tidak membantu di sini karena perubahan berada pada baris yang berbeda .
Jika Anda memiliki rangkaian pengujian otomatis, hal terpenting yang harus dilakukan adalah menjalankan pengujian setelah penggabungan. Anda dapat melakukan ini setelah melakukan, dan memperbaikinya nanti jika diperlukan; atau Anda dapat melakukannya sebelum melakukan, dengan menambahkan --no-commitke git mergeperintah. Kami akan menyerahkan detail untuk semua ini ke postingan lainnya.
1 Anda juga bisa mendapatkan konflik sehubungan dengan operasi "file-wide", misalnya, mungkin kita memperbaiki ejaan kata dalam sebuah file (sehingga kita memiliki perubahan), dan mereka menghapus seluruh file (sehingga mereka memiliki menghapus). Git tidak akan menyelesaikan konflik ini dengan sendirinya, apa pun -Xargumennya.
Melakukan lebih sedikit penggabungan dan / atau penggabungan yang lebih cerdas dan / atau menggunakan rebase
Ada tiga penggabungan di kedua urutan perintah kami. Yang pertama adalah membawa origin/demoke lokal demo(penggunaan Anda git pullyang, jika Git Anda sangat tua, akan gagal diperbarui origin/demotetapi akan menghasilkan hasil akhir yang sama). Yang kedua adalah origin/mastermemasukkan master.
Tidak jelas bagi saya siapa yang memperbarui demodan / atau master. Jika Anda menulis kode Anda sendiri di democabang Anda sendiri , dan orang lain menulis kode dan mendorongnya ke democabang origin, maka penggabungan langkah pertama ini dapat menimbulkan konflik, atau menghasilkan penggabungan yang nyata. Lebih sering daripada tidak, lebih baik menggunakan rebase, daripada menggabungkan, untuk menggabungkan pekerjaan (memang, ini masalah selera dan pendapat). Jika demikian, Anda mungkin ingin menggunakannya git rebase. Di sisi lain, jika Anda tidak pernah melakukan komit Anda sendiri pada demo, Anda bahkan tidak perlu sebuah democabang. Atau, jika Anda ingin mengotomatiskan banyak hal ini, tetapi dapat memeriksa dengan cermat ketika ada commit yang dibuat oleh Anda dan orang lain, Anda mungkin ingin menggunakannya.git merge --ff-only origin/demo: ini akan mempercepat Anda demountuk mencocokkan yang diperbarui origin/demojika memungkinkan, dan langsung gagal jika tidak (pada titik mana Anda dapat memeriksa dua set perubahan, dan memilih penggabungan nyata atau rebase yang sesuai).
Logika yang sama berlaku untuk master, meskipun Anda melakukan merge pada master , sehingga Anda pasti membutuhkan master. Namun, lebih mungkin Anda ingin penggabungan gagal jika tidak dapat dilakukan sebagai fast-forward non-merge, jadi ini mungkin juga harus dilakukan git merge --ff-only origin/master.
Katakanlah Anda tidak pernah melakukan komitmen Anda sendiri demo. Dalam hal ini kita dapat membuang nama demoseluruhnya:
git fetch origin # update origin/*
git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"
git merge -X theirs origin/demo || die "complex merge conflict"
git push origin master
Jika Anda sedang melakukan sendiri demokomit cabang, ini tidak membantu; Anda mungkin juga mempertahankan penggabungan yang ada (tetapi mungkin menambahkan --ff-onlytergantung pada perilaku apa yang Anda inginkan), atau beralih ke melakukan rebase. Perhatikan bahwa ketiga metode mungkin gagal: penggabungan mungkin gagal dengan konflik, penggabungan dengan --ff-onlymungkin tidak dapat maju cepat, dan rebase mungkin gagal dengan konflik (rebase bekerja dengan, pada dasarnya, melakukan pengambilan ceri , yang menggunakan penggabungan mesin dan karenanya bisa mendapatkan konflik gabungan).
git push -f origin master