Menyelesaikan konflik Git yang mendukung perubahan mereka selama penarikan

1227

Bagaimana cara menyelesaikan konflik git gabung yang mendukung perubahan yang ditarik?

Pada dasarnya saya perlu menghapus semua perubahan yang bertentangan dari pohon yang berfungsi tanpa harus melalui semua konflik dengan git mergetoolsementara menjaga semua perubahan bebas konflik. Lebih disukai melakukan ini sambil menarik, bukan sesudahnya.

sanmai
sumber
2
Gandakan tarikan git dari jarak jauh .. bisakah saya memaksanya untuk menimpa daripada melaporkan konflik? Anda dapat melihat solusi yang sama di sana.
Dan Dascalescu
3
@DanDascalescu Jawaban yang diterima di sana tidak menjawab pertanyaan ini, jadi jelas itu bukan duplikat. Plus, pertanyaan lain itu cukup ambigu: sangat sulit untuk mengatakan apa yang ditanyakan. Secara keseluruhan saya tidak setuju dengan Anda. Apa maksud Anda dalam hal ini?
sanmai
2
@sanmai Anda punya dua jawaban - dan Anda menerima salah satunya. Bisakah Anda lebih menjelaskan apa yang Anda harapkan dalam jawaban dan berapa banyak lagi detail yang Anda inginkan di sini?
Edward Thomson
2
@EdwardThomson yah, sebenarnya saya berpikir untuk memberikan reputasi ini untuk jawaban pertama, tetapi jika Anda bertanya, saya mungkin menunggu dan melihat apakah jawaban yang lebih baik muncul
sanmai

Jawaban:

1220
git pull -s recursive -X theirs <remoterepo or other repo>

Atau, cukup, untuk repositori default:

git pull -X theirs

Jika Anda sudah dalam keadaan konflik ...

git checkout --theirs path/to/file
Tarif Pascal
sumber
40
Perhatikan bahwa di -s recursivesini berlebihan, karena itulah strategi penggabungan default. Jadi Anda bisa menyederhanakannya git pull -X theirs, yang pada dasarnya setara dengan git pull --strategy-option theirs.
5
Jika saya melakukan ini, saya akan kembali ke MERGINGnegara bagian. Saya bisa lalu git merge --abortmencoba lagi, tetapi setiap kali saya berakhir dengan penggabungan. ... Saya tahu bahwa rebase didorong ke hulu saya, jadi mungkin itu yang menyebabkan ini?
Benjohn
22
Hati-hati dengan git checkout --theirs path/to/file. Digunakan saat rebase dan mendapat hasil yang tidak terduga. Ditemukan penjelasan dalam dokumen: Perhatikan bahwa selama git rebase dan git pull --rebase, kita dan mereka mungkin tampak bertukar; --our memberikan versi dari cabang perubahan yang dirubah kembali, sementara --theirs memberikan versi dari cabang yang menahan pekerjaan Anda yang sedang direstrukturisasi.
Vuk Djapic
10
Perhatikan bahwa git checkout --theirs/--ours pathhalaman manual menyatakan bahwa itu berfungsi untuk jalur yang tidak di-emergasi . Jadi jika tidak ada konflik di jalan, sudah digabungkan perintah ini tidak akan melakukan apa-apa. Ini dapat menyebabkan masalah ketika Anda ingin misalnya versi 'mereka' dari seluruh sub-folder. Jadi dalam kasus seperti itu akan lebih aman untuk melakukan git checkout MERGE_HEAD pathatau menggunakan hash komit.
fsw
4
git pull -X theirsmembuat komit gabungan jika ada konflik (mis. jika committer lain lari git push -fke remote). Jika Anda tidak ingin menggabungkan komit, jalankan saja git fetch && git reset --hard origin/master.
Dan Dascalescu
985

Anda dapat menggunakan opsi strategi "mereka" rekursif :

git merge --strategy-option theirs

Dari pria itu :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

Catatan: seperti yang dikatakan halaman manual, "kita" bergabung opsi strategi sangat berbeda dari strategi gabungan "milik kami" .

Ikke
sumber
Berikut adalah penjelasan yang lebih terperinci: lostechies.com/joshuaflanagan/2010/01/29/…
mPrinC
227
Juga git checkout --theirsuntuk beroperasi pada satu file yang saling bertentangan
dvd
48
Ini tidak berfungsi jika Anda sudah dalam kondisi resolusi konflik. Dalam hal ini saya percaya cara terbaik untuk menyelesaikannya adalah dengan git checkout <ref to theirs> -- the/conflicted.file; dan kemudian git addperubahan mereka.
ThorSummoner
54
@ Tumormoner Dalam hal ini, ada checkout git --theirs path / of / file. Dengan begitu, Anda tidak perlu mencari hash yang benar secara manual.
Ikke
8
@ Ike Itu pada dasarnya harus menjadi jawabannya sendiri (dan jawaban yang diterima pada saat itu) jika Anda bertanya kepada saya.
ThorSummoner
473

Jika Anda sudah dalam keadaan konflik, dan Anda ingin menerima saja :

git checkout --theirs .
git add .

Jika Anda ingin melakukan yang sebaliknya:

git checkout --ours .
git add .

Ini sangat drastis, jadi pastikan Anda benar-benar ingin menghapus semuanya seperti ini sebelum melakukannya.

banyak-untuk-belajar
sumber
47
atau, jangan gunakan .dan tentukan file sebagai pengganti titik yang ingin Anda checkout. kurang "drastis" & persis apa yang ingin Anda lakukan, mungkin.
manroe
10
ini tidak berfungsi jika file telah dihapus dari cabang lain: '<file>' tidak memiliki versi mereka
Japster24
3
Akan lebih tinggi jika saya bisa, terus kembali ke jawaban ini setiap sekarang dan kemudian.
tarikki
6
Gunakan git add -usebaliknya untuk melewati file yang tidak di bawah kontrol versi.
Sudipta Basak
3
Kasus hipotetis, tiga perubahan dalam file, satu konflik, dua tanpa konflik, akankah solusi ini menerapkan perubahan yang tidak bertentangan dan menyelesaikan perubahan yang bertentangan dengan kita? Atau akankah hanya versi kami yang mengabaikan perubahan yang tidak bertentangan dari versi mereka?
pedromarce
222

OK jadi, bayangkan skenario saya tadi:

Anda mencoba merge, atau mungkin cherry-pick, dan Anda dihentikan

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

Sekarang, Anda melihat file yang konflik dan Anda benar-benar tidak ingin menyimpan perubahan Anda. Dalam kasus saya di atas, file tersebut bentrok hanya pada baris baru IDE saya telah ditambahkan secara otomatis. Untuk membatalkan perubahan Anda dan menerimanya, cara termudah adalah:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Kebalikan dari ini (untuk menimpa versi yang masuk dengan versi Anda) adalah

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Anehnya, saya tidak dapat menemukan jawaban ini dengan mudah di Internet.

Theodore R. Smith
sumber
15
Perhatikan bahwa, jika seseorang melakukan git statusantara checkoutdan add, file masih ditampilkan sebagai "keduanya dimodifikasi".
Uskup
Apakah Anda tahu jika ada cara untuk melakukan ini untuk semua file yang dalam keadaan konflik? Jika demikian, itu akan menjadi ekstensi yang bagus untuk jawaban Anda.
Drew Noakes
2
Saya melakukan ini: git reset --hard dan kemudian git pull [remote server name] [branch name] -Xtheirs(membatalkan penggabungan kemudian menarik barang baru di atas barang saya) - tidak yakin apakah ini yang Anda inginkan.
ssaltman
38

The git pull -X theirsjawaban dapat membuat merge jelek komit, atau menerbitkan

kesalahan: Perubahan lokal Anda ke file berikut akan ditimpa oleh gabungan:

Jika Anda ingin mengabaikan modifikasi lokal untuk file dari repo, misalnya pada klien yang harus selalu menjadi cermin asal, jalankan ini (ganti masterdengan cabang yang Anda inginkan):

git fetch && git reset --hard origin/master

Bagaimana cara kerjanya? git fetchtidak git pulltetapi tanpa penggabungan . Kemudian git reset --hardbuat pohon kerja Anda cocok dengan komit terakhir. Semua perubahan lokal Anda ke file dalam repo akan dibuang , tetapi file lokal baru akan dibiarkan sendiri.

Dan Dascalescu
sumber
1
+1 - git fetch && git reset --hard {remote}/{branch}adalah yang memecahkan masalah saya. Saya harus benar-benar membuang perubahan saya sendiri demi status "mereka" cabang, tetapi git pull -X theirstersedak pada beberapa file yang dipindahkan / diganti nama. Terima kasih!
Ivaylo Slavov
23

Setelah git bergabung, jika Anda mendapatkan konflik dan Anda ingin Anda atau mereka

git checkout --theirs .
git checkout --ours .
Mohit Kanojia
sumber
Bagaimana saya melakukan ini berdasarkan basis potongan yang saling bertentangan? Di atas berfungsi pada tingkat file, membuang potongan yang tidak bertentangan yang mungkin dimiliki file yang bertentangan.
Jani
21

Untuk menyelesaikan semua konflik dengan versi di cabang tertentu:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

Jadi, jika Anda sudah dalam status penggabungan, dan Anda ingin menyimpan versi master dari file yang bertentangan:

git diff --name-only --diff-filter=U | xargs git checkout master
Ariel Alvarez
sumber
Dan untuk orang-orang di windows tanpa akses ke pipa xargs, bagaimana ini menerjemahkan?
tsemer
Bukankah itu akan melewatkan perubahan Anda sepenuhnya? Bahkan mereka yang tidak dalam keadaan konflik?
Valentin Heinitz
Inilah yang akhirnya saya lakukan. Sayangnya itu kemudian memerlukan salah satu git cherry-pick --continue atau satu git commit --allow-emptyperintah untuk melakukan perubahan ini, dan tampaknya tidak ada sistem di belakang yang diperlukan perintah, yang membuat mengotomatisasi ini menyusahkan. Saat ini saya sedang memecahkan ini dengan menguji keberadaan .git/COMMIT_EDITMSGfile tetapi itu tampak rapuh dan rapuh, dan saya belum yakin bahwa itu selalu berhasil.
Konrad Rudolph
Ini bagus, artinya jika Anda secara manual menyelesaikan beberapa (dan melakukan git add) maka Anda dapat menyelesaikan sisanya melalui ini. git checkout --oursSaya git checkout --theirsjuga berguna.
rcoup
18

Harap jangan bahwa kadang-kadang ini tidak akan berhasil :

git checkout - jalur kami / ke / file

atau

git checkout - jalur mereka / ke / file

Saya melakukan ini sebagai gantinya, dengan asumsi HEAD adalah milik kita dan MERGE_HEAD adalah milik mereka

git checkout HEAD -- path/to/file

atau:

git checkout MERGE_HEAD -- path/to/file

Setelah kami melakukan ini dan kami baik-baik saja:

git add .

Jika Anda ingin lebih memahami, lihat posting torek yang indah di sini: git checkout --our tidak menghapus file dari daftar file yang tidak di-unmerged

Nicolas D
sumber
12

Pengguna VS Code (integrated Git) IDE:

Jika Anda ingin menerima semua perubahan yang masuk dalam file konflik maka lakukan langkah-langkah berikut.

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

Demikian pula yang dapat Anda lakukan untuk opsi lain seperti Terima Semua Keduanya, Terima Semua Saat Ini dll,

SridharKritha
sumber
2
Itu tampaknya hanya berfungsi untuk satu file, tidak semua file dengan konflik sekalipun.
Yoryo
1

Saya memiliki next-versioncabang yang sudah berjalan lama dengan banyak penghapusan file yang telah berubah develop, file yang telah ditambahkan di berbagai tempat di kedua cabang, dll.

Saya ingin mengambil seluruh isi next-versioncabang develop, semuanya dalam satu komit gabungan.

Kombinasi dari perintah di atas yang bekerja untuk saya adalah:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

Bukan jawaban baru, hanya menggabungkan bit dari banyak jawaban, sebagian untuk meyakinkan bahwa Anda mungkin membutuhkan semua jawaban ini.

Gordon
sumber
1

Jika Anda sudah dalam keadaan konflik, dan tidak ingin checkout jalur satu per satu. Anda boleh mencoba

git merge --abort
git pull -X theirs
Lee Chee Kiam
sumber
-1

dari https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

Ini pada dasarnya akan melakukan penggabungan palsu. Ini akan mencatat komit gabungan baru dengan kedua cabang sebagai orang tua, tetapi bahkan tidak akan melihat cabang tempat Anda bergabung. Ini hanya akan mencatat sebagai hasil dari gabungan kode yang tepat di cabang Anda saat ini.

$ git merge -s ours mundo

Merge dibuat oleh strategi 'kita'.

$ git diff HEAD HEAD~

Anda dapat melihat bahwa tidak ada perbedaan antara cabang tempat kami berada dan hasil penggabungan.

Hal ini sering berguna untuk menipu Git agar berpikir bahwa cabang sudah digabung ketika melakukan penggabungan nanti. Sebagai contoh, katakanlah Anda bercabang keluar dari cabang rilis dan telah melakukan beberapa pekerjaan di atasnya yang Anda ingin bergabung kembali ke cabang master Anda di beberapa titik. Sementara itu beberapa perbaikan bug pada master perlu di-backport ke cabang rilis Anda. Anda bisa menggabungkan cabang perbaikan bug ke cabang rilis dan juga menggabungkan -s cabang kami yang sama ke cabang master Anda (meskipun perbaikan sudah ada di sana) sehingga ketika Anda nanti menggabungkan cabang rilis lagi, tidak ada konflik dari perbaikan bug.

Suatu situasi yang saya temukan berguna jika saya ingin master untuk mencerminkan perubahan cabang topik baru. Saya perhatikan bahwa -Xtheirs tidak bergabung tanpa konflik dalam beberapa keadaan ... misalnya

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

Dalam hal ini solusi yang saya temukan adalah

$ git checkout topicFoo

dari topicFoo, penggabungan pertama dalam master menggunakan strategi -s kita, ini akan membuat komit palsu yang hanya keadaan dari topicFoo. $ git merge -s master kita

periksa komit gabungan yang dibuat

$ git log

sekarang checkout cabang utama

$ git checkout master

menggabungkan cabang topik kembali tetapi kali ini menggunakan strategi rekursif -Xtheirs, ini sekarang akan memberi Anda cabang utama dengan keadaan topicFoo.

$ git merge -X theirs topicFoo
Amos Folarin
sumber