Pilih strategi Git merge untuk file tertentu ("milik kami", "milikku", "milik mereka")

207

Saya di tengah rebasing setelah a git pull --rebase. Saya punya beberapa file yang menggabungkan konflik. Bagaimana saya bisa menerima perubahan "mereka" atau "saya" untuk file tertentu?

$ git status
# Not currently on any branch.
# You are currently rebasing.
#   (fix conflicts and then run "git rebase --continue")
#   (use "git rebase --skip" to skip this patch)
#   (use "git rebase --abort" to check out the original branch)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:  CorrectlyMergedFile
#
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add <file>..." to mark resolution)
#
#       both modified: FileWhereIWantToAcceptTheirChanges
#       both modified: FileWhereIWantToAcceptMyChanges

Biasanya saya hanya membuka file atau alat gabungan dan secara manual menerima semua perubahan "mereka" atau "saya". Namun, saya curiga saya kehilangan perintah git yang mudah.

Juga, perhatikan bahwa saya hanya akan dapat memilih strategi penggabungan untuk setiap file ketika saya melihat file apa yang mengenai konflik dan kemungkinan konflik tersebut.

Steven Wexler
sumber
@AbeVoelker Saya tidak berpikir itu menyelesaikan masalah saya. Saya ingin memilih strategi gabungan untuk file tertentu. Juga, perhatikan bahwa saya hanya akan tahu apa yang menggunakan stragegy untuk digunakan ketika saya dalam rebase saya dan melihat file mana yang telah mencapai konflik dan apa konflik itu.
Steven Wexler
Saya mengedit pertanyaan ini menjadi lebih umum: stackoverflow.com/questions/278081/… . Mungkin kita bisa menutup pertanyaan ini sebagai duplikat dari itu? Apakah itu tepat?
@TheShadow Itu tampak masuk akal bagi saya.
Steven Wexler
Saya tidak yakin apakah itu tepat untuk mengubah judul pertanyaan lain dengan apa yang saya lakukan, karena saya mengambil bagian tentang menyelesaikan file biner. Saya mengembalikan pertanyaan lain ke sebelumnya, jadi pertanyaan saat ini masih menambah nilai.

Jawaban:

251

Untuk setiap file yang konflik yang Anda dapatkan, Anda dapat menentukan

git checkout --ours -- <paths>
# or
git checkout --theirs -- <paths>

Dari git checkoutdokumen

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
Saat memeriksa jalur dari indeks, periksa tahap # 2 ( ours) atau # 3 ( theirs) untuk jalur yang tidak digabungkan.

Indeks mungkin berisi entri yang tidak dihapus karena gabungan gagal sebelumnya. Secara default, jika Anda mencoba untuk memeriksa entri seperti itu dari indeks, operasi checkout akan gagal dan tidak ada yang akan diperiksa. Menggunakan -fakan mengabaikan entri yang tidak dihapus ini. Konten dari sisi tertentu dari gabungan dapat diperiksa dari indeks dengan menggunakan --oursatau --theirs. Dengan -m, perubahan yang dibuat pada file pohon kerja dapat dibuang untuk membuat kembali hasil gabungan yang konflik.


sumber
9
Apakah mungkin untuk menerima file mereka untuk semua file yang dibiarkan tidak aktif?
aslakjo
41
@aslakjo git rebase -s recursive -X <ours/theirs>atau git merge -s recursive -X <ours/theirs>. Perlu diingat bahwa untuk rebase, "milik kita" dan "milik mereka" dibalik dari apa yang mereka lakukan saat penggabungan. Anda mungkin bisa menggunakan file / shell glob juga, seperti git checkout --theirs -- *.txt.
2
Terima kasih banyak, @Cupcake, pembalikan tak terduga ours/theirsdengan rebase membuatku gila !! (Masuk akal sekarang bahwa saya berpikir tentang bagaimana rebase sebenarnya bekerja, tetapi sama sekali tidak intuitif.)
Dan Lenski
2
@DanLenski rebase secara umum hanyalah alat yang benar-benar rumit untuk dipahami orang pada awalnya, tetapi begitu Anda memahami cara kerjanya, Anda dapat melakukan segala macam hal yang sangat kuat dengannya.
1
@VincentSels sebenarnya, Anda perlu menutupi karakter *, jika tidak, shell akan mencoba memperluasnya. jadi dalam kasus Anda git checkout --outs -- "**/*.csproj"akan melakukan apa yang Anda maksudkan. Hal yang sama berlaku misalnya untuk git lfs track "*.jpg". Jika Anda memiliki beberapa file jpg di CWD Anda, tanpa tanda kutip, hanya ini yang akan dilacak.
eFloh
117

Meskipun pertanyaan ini dijawab, berikan contoh tentang apa arti "milik mereka" dan "milik kita" dalam kasus git rebase vs merge. Lihat tautan ini

Git Rebase
theirs sebenarnya adalah cabang saat ini dalam kasus rebase . Jadi set perintah di bawah ini sebenarnya menerima perubahan cabang Anda saat ini atas cabang jarak jauh.

# see current branch
$ git branch
... 
* branch-a
# rebase preferring current branch changes during conflicts
$ git rebase -X theirs branch-b

Git Merge
Untuk menggabungkan , arti theirsdan oursdibalik. Jadi, untuk mendapatkan efek yang sama selama penggabungan , yaitu, pertahankan perubahan cabang Anda saat ini ( ours) di atas cabang jarak jauh yang digabungkan ( theirs).

# assuming branch-a is our current version
$ git merge -X ours branch-b  # <- ours: branch-a, theirs: branch-b
Abe
sumber
2
yah, ini perbedaan yang cukup penting! terima kasih telah mengklarifikasi.
verboze
26

Catatan yang git checkout --ours|--theirsakan menimpa file sepenuhnya , dengan memilih salah satu theirsatau oursversi, yang mungkin atau mungkin tidak apa yang ingin Anda lakukan (jika Anda memiliki perubahan yang tidak bertentangan datang dari sisi lain, mereka akan hilang).

Jika Anda ingin melakukan penggabungan tiga arah pada file tersebut, dan hanya menyelesaikan bakhil yang berkonflik dengan menggunakan --ours|--theirs, sambil tetap mempertahankan bakhil yang tidak berkonflik dari kedua sisi, Anda mungkin ingin menggunakan git merge-file; lihat detail dalam jawaban ini .

jakub.g
sumber
1
Mengenai "perubahan yang tidak bertentangan" yang akan hilang - ini merujuk hanya pada file di mana ada perubahan yang tidak bertentangan pada baris tertentu di mana dalam file yang sama, atau semua perubahan dari semua file dalam sejarah yang selaras?
ktamlyn
2
@ktamlyn oleh "perubahan yang tidak bertentangan" Maksud saya adalah perubahan pada file yang sama. Misalnya, ada dua bakhil yang diubah (bagian) example.txtdalam oursversi, yang satu bertentangan (juga diubah dalam theirsrevisi), yang lain tidak-berkonflik. Jika Anda melakukannya git checkout --theirs example.txt, itu hanya akan membabi buta membaca seluruh file pada theirsrevisi, dan bagian yang tidak konflik dari diff akan hilang.
jakub.g
1
Terima kasih! Ini adalah klarifikasi yang perlu bagi saya, meskipun "perubahan dalam file yang sama" paling masuk akal dalam konteks ini.
ktamlyn
Ini harus menjadi jawaban yang diterima, meskipun tidak benar-benar memberikan jawaban, tetapi menunjukkan masalah penting dalam solusi yang diusulkan lainnya.
tomasyany
1
Jika Anda ingin kembali ke file asli yang bertentangan, Anda dapat menjalankannya git checkout --merge <path>.
Andrew Keeton