Apa arti tepat dari "milik kita" dan "milik mereka" dalam git?

323

Ini mungkin terdengar seperti pertanyaan yang terlalu mendasar, tetapi saya telah mencari jawaban dan sekarang saya lebih bingung daripada sebelumnya.

Apa arti "milik kita" dan "milik mereka" dalam git saat menggabungkan cabang saya ke cabang saya yang lain? Kedua cabang adalah "milik kita".

Dalam konflik gabungan, apakah "milik kita" selalu di atas dari dua versi yang ditampilkan?

Apakah "milik kita" selalu merujuk ke cabang yang ditunjuk KEPALA saat penggabungan dimulai? Jika demikian maka mengapa tidak menggunakan referensi posesif yang jelas seperti "cabang saat ini" alih-alih menggunakan kata ganti posesif seperti "milik kami" yang secara rancu ambigu (karena kedua cabang secara teknis milik kami)?

Atau cukup gunakan nama cabang (alih-alih mengucapkan "milik kita", katakan saja "tuan lokal" atau semacamnya)?

Bagian yang paling membingungkan bagi saya adalah jika saya menentukan dalam file .gitattributes cabang tertentu. Katakanlah di cabang tes saya memiliki file .gitattributes berikut:

config.xml merge=ours

Sekarang saya checkout dan arahkan HEAD untuk dikuasai kemudian bergabung dalam ujian . Karena master adalah milik kita, dan atribut .git tes tidak dicentang, apakah akan berpengaruh? Jika itu memang berpengaruh, karena tuan sekarang adalah "milik kita", lalu apa yang akan terjadi?

CommaToast
sumber

Jawaban:

375

Saya curiga Anda bingung di sini karena pada dasarnya membingungkan. Untuk membuat segalanya lebih buruk, semua barang kita / mereka berganti peran (menjadi mundur) ketika Anda melakukan rebase.

Pada akhirnya, selama git merge, yang "kita" cabang mengacu pada cabang Anda penggabungan ke :

git checkout merge-into-ours

dan cabang "milik mereka" merujuk ke cabang (tunggal) yang Anda gabungkan:

git merge from-theirs

dan di sini "kita" dan "mereka" cukup masuk akal, karena meskipun "mereka" mungkin Anda pula, "mereka" adalah bukan yang Anda berada di saat Anda berlari git merge.

Meskipun menggunakan nama cabang yang sebenarnya mungkin sangat keren, itu berantakan dalam kasus yang lebih kompleks. Misalnya, alih-alih yang di atas, Anda dapat melakukan:

git checkout ours
git merge 1234567

tempat Anda bergabung dengan ID komit mentah. Lebih buruk lagi, Anda bahkan dapat melakukan ini:

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

dalam hal ini tidak ada nama cabang yang terlibat!

Saya pikir ini sedikit membantu di sini, tetapi pada kenyataannya, dalam gitrevisionssintaksis , Anda bisa merujuk ke jalur individual dalam indeks dengan nomor, selama penggabungan yang bertentangan

git show :1:README
git show :2:README
git show :3:README

Tahap # 1 adalah leluhur umum dari file, tahap # 2 adalah versi cabang-target, dan tahap # 3 adalah versi yang Anda gabungkan.


Alasan gagasan "milik kami" dan "milik mereka" dipertukarkan rebaseadalah karena rebase bekerja dengan melakukan serangkaian pemetik ceri, ke cabang anonim (mode HEAD yang terlepas). Cabang target adalah cabang anonim, dan cabang gabungan dari adalah cabang asli Anda (pra-rebase): jadi "--kami" berarti yang dibuat oleh salah satu rebase sementara "--theirs" berarti "cabang kami direstrukturisasi" .


Adapun entri gitattributes: itu bisa memiliki efek: "milik kita" benar-benar berarti "gunakan tahap # 2" secara internal. Tetapi seperti yang Anda perhatikan, itu sebenarnya tidak ada pada saat itu, jadi seharusnya tidak memiliki efek di sini ... well, tidak kecuali Anda menyalinnya ke pohon kerja sebelum Anda mulai.

Juga, omong-omong, ini berlaku untuk semua penggunaan milik kami dan milik mereka, tetapi beberapa berada pada tingkat file keseluruhan ( -s oursuntuk strategi penggabungan; git checkout --oursselama konflik penggabungan) dan beberapa menggunakan sepotong demi sepotong ( -X oursatau -X theirsselama -s recursivemenggabungkan). Yang mungkin tidak membantu dengan kebingungan.

Tapi saya tidak pernah menemukan nama yang lebih baik untuk ini. Dan: lihat jawaban VonC untuk pertanyaan lain, di mana git mergetoolmemperkenalkan lebih banyak nama untuk ini, menyebut mereka "lokal" dan "jauh"!

torek
sumber
28
+1. Tentang kami dan mereka dibalik selama rebase, lihat juga: stackoverflow.com/a/2960751/6309 dan stackoverflow.com/a/3052118/6309
VonC
1
Dua hal "bergabung satu sama lain". Ketika penggabungan terjadi kedua belah pihak bergabung "menjadi" satu sama lain. Saya merasa tidak benar untuk mengatakan bahwa salah satu dari kedua belah pihak adalah "tidak menggabungkan apa pun". Jika tidak ada nama cabang yang terlibat (seperti yang Anda tunjukkan) maka ada nama komit yang terlibat (Anda bisa mengatakan "7777777" dan "1234567" bukan "milik kami" dan "milik mereka"). Saya mengerti apa yang terjadi selama rebase dan saya tidak merasa itu membingungkan sama sekali. Saya pikir "KEPALA" dan "yang masuk" akan bekerja lebih baik daripada "milik kita" dan "milik mereka" karena selalu ada "KEPALA" (terlepas atau tidak).
CommaToast
15
Saya kira karena kepala adalah pusat pikiran, yang merupakan sumber identitas, yang merupakan sumber dari diri sendiri, lebih masuk akal untuk memikirkan apa pun yang menunjuk KEPALA sebagai "milikku" ("milik kita", karena Saya kira saya dan KEPALA membuat dua). Jika tidak lebih, itu hanya akan menjadi perangkat mnemonik yang baik.
CommaToast
1
Yang sedang berkata, saya masih ingin membuat salinan fisik dari seluruh repo sebelum melakukan sesuatu seperti rebasing ...: D
CommaToast
3
"dalam hal ini tidak ada nama cabang yang terlibat!" ... Jadi, gunakan komentar komit / hash sebagai gantinya. Apa pun yang bisa didapatkan. Praktis apa pun akan lebih baik daripada "milik kita" dan "milik mereka". Saya bertanya-tanya berapa ribu jam dev kebingungan ini telah menguap. jawaban git untuk C ++ "most vexing parse";)
Jarrod Smith
49

' Milik kita ' dalam Git mengacu pada cabang kerja asli yang memiliki bagian otoritatif / kanonik dari sejarah git.

' Milik mereka ' mengacu pada versi yang menyimpan pekerjaan untuk diubah kembali (perubahan harus diputar ulang ke cabang saat ini).

Ini mungkin tampak ditukar dengan orang-orang yang tidak sadar bahwa melakukan rebasing (mis. git rebase) Sebenarnya menahan pekerjaan Anda (yang adalah milik mereka ) untuk memutar ulang ke kanonik / sejarah utama yang menjadi milik kita , karena kita rebasing kami berubah karena pekerjaan pihak ketiga.

Dokumentasi untuk git-checkoutselanjutnya diklarifikasi dalam Git> = 2.5.1 sesuai f303016komit :

--ours --theirs

Saat memeriksa jalur dari indeks, periksa tahap # 2 ('milik kami') atau # 3 ('milik mereka') untuk jalur yang tidak digabungkan.

Perhatikan bahwa selama git rebasedan git pull --rebase, 'milik kita' dan 'milik mereka' mungkin tampak ditukar; --oursmemberikan versi dari cabang perubahan diubah menjadi ulang, sementara --theirsmemberikan versi dari cabang yang menahan pekerjaan Anda yang sedang dirubah.

Ini karena rebasedigunakan dalam alur kerja yang memperlakukan sejarah di remote sebagai yang kanonik bersama, dan memperlakukan pekerjaan yang dilakukan pada cabang yang Anda rebasing sebagai pekerjaan pihak ketiga yang akan diintegrasikan, dan Anda sementara mengambil peran untuk sementara penjaga sejarah kanonik selama rebase. Sebagai penjaga sejarah kanonik, Anda perlu melihat sejarah dari jarak jauh sebagai ours(yaitu "sejarah kanonik bersama kami"), sedangkan apa yang Anda lakukan di cabang samping Anda sebagai theirs(yaitu "karya satu kontributor di atasnya").

Untuk git-mergeitu jelaskan dengan cara berikut:

milik kita

Opsi ini memaksa orang-orang yang bertikai untuk diselesaikan secara otomatis dengan memilih versi kami. Perubahan dari pohon lain yang tidak bertentangan dengan pihak kami tercermin pada hasil penggabungan. Untuk file biner, seluruh konten diambil dari pihak kami.

Ini tidak boleh disamakan dengan strategi penggabungan kita, yang bahkan tidak melihat apa yang dikandung pohon lain sama sekali. Itu membuang semua yang dilakukan pohon lain, menyatakan sejarah kita mengandung semua yang terjadi di dalamnya.

milik mereka

Ini kebalikan dari kita.

Lebih jauh lagi, di sini dijelaskan cara menggunakannya:

Mekanisme penggabungan ( git mergedan git pullperintah) memungkinkan strategi gabungan backend untuk dipilih dengan -sopsi. Beberapa strategi juga dapat mengambil pilihan mereka sendiri, yang dapat diteruskan dengan memberikan -X<option>argumen kepada git mergedan / atau git pull.


Jadi kadang-kadang bisa membingungkan, misalnya:

  • git pull origin masterdi mana -Xourslokal kami, -Xtheirsadalah cabang (jarak jauh) mereka
  • git pull origin master -rdi mana -Xoursmilik mereka (jarak jauh), -Xtheirsmilik kita

Jadi contoh ke-2 berlawanan dengan yang pertama, karena kami rebasing cabang kami di atas yang jauh, jadi titik awal kami adalah yang jauh, dan perubahan kami diperlakukan sebagai eksternal.

Mirip untuk git mergestrategi ( -X oursdan -X theirs).

kenorb
sumber
2
jawaban ini tampaknya ketinggalan zaman => "git merge --ours" bukan pilihan yang valid
Alexander Mills
@AlexanderMills Jawabannya tidak berbicara tentang git merge, tetapi git pulldan git checkoutsebagai contoh. Jika Anda ingin menggunakan parameter ini dengan git merge, Anda harus menggunakan -X ours. Anda masih dapat menggunakan --ourssintaks untuk git checkout. Saya sudah mengklarifikasi jawabannya lebih jauh.
kenorb
46

Saya tahu ini telah dijawab, tetapi masalah ini membuat saya bingung berkali-kali saya membuat situs web referensi kecil untuk membantu saya mengingat: https://nitaym.github.io/ourstheirs/

Berikut adalah dasar-dasarnya:

Gabung:

$ git checkout master 
$ git merge feature

Jika Anda ingin memilih versi di master:

$ git checkout --ours codefile.js

Jika Anda ingin memilih versi di feature:

$ git checkout --theirs codefile.js

Rebases:

$ git checkout feature 
$ git rebase master 

Jika Anda ingin memilih versi di master:

$ git checkout --ours codefile.js

Jika Anda ingin memilih versi di feature:

$ git checkout --theirs codefile.js

(Ini untuk file lengkap, tentu saja)

Nitay
sumber
1
Situs web itu sangat membantu. Gaya diagram alir dan kata-kata berkode warna membuat situs web lebih mudah dipahami daripada jawaban SO. Terima kasih.
Ron
10
  • Milik kami : Ini adalah cabang tempat Anda saat ini.
  • Milik mereka : Ini adalah cabang lain yang digunakan dalam tindakan Anda.

Jadi jika Anda menggunakan rilis cabang / 2.5 dan Anda menggabungkan fitur cabang / tombol-baru ke dalamnya, maka konten seperti yang ditemukan di rilis / 2.5 adalah apa yang kami rujuk dan konten seperti yang ditemukan di fitur / tombol-baru adalah apa yang mereka rujuk untuk. Selama aksi penggabungan, ini cukup lurus ke depan.

Satu-satunya masalah yang membuat kebanyakan orang jatuh hati adalah kasus rebase . Jika Anda melakukan re-base alih-alih penggabungan normal, peran tersebut ditukar. Bagaimana dengan itu? Ya, itu hanya disebabkan oleh cara rebasing bekerja. Pikirkan rebase untuk bekerja seperti itu:

  1. Semua komit yang telah Anda lakukan sejak tarikan terakhir Anda dipindahkan ke cabang mereka sendiri, sebut saja BranchX .
  2. Anda checkout kepala cabang Anda saat ini, membuang semua perubahan lokal yang Anda miliki tetapi dengan cara itu mengambil semua perubahan yang orang lain dorong untuk cabang itu.
  3. Sekarang setiap komit di BranchX dipilih ceri agar tua ke baru ke cabang Anda saat ini.
  4. BranchX dihapus lagi dan karenanya tidak akan pernah muncul di riwayat apa pun.

Tentu saja, itu tidak benar-benar apa yang terjadi tetapi itu adalah model pikiran yang baik untuk saya. Dan jika Anda melihat 2 dan 3, Anda akan mengerti mengapa peran tersebut dipertukarkan sekarang. Mulai 2, cabang Anda saat ini adalah cabang dari server tanpa ada perubahan, jadi ini milik kami (cabang tempat Anda berada). Perubahan yang Anda buat sekarang berada di cabang berbeda yang bukan milik Anda saat ini ( BranchX ) dan dengan demikian perubahan ini (meskipun perubahan yang Anda buat) adalah milik mereka (cabang lain yang digunakan dalam tindakan Anda).

Itu berarti jika Anda bergabung dan Anda ingin perubahan Anda selalu menang, Anda akan memberitahu git untuk selalu memilih "kita" tetapi jika Anda rebase dan Anda ingin semua perubahan Anda selalu menang, Anda memberi tahu git untuk selalu memilih "milik mereka".

Mecki
sumber
3

Saya tahu itu tidak menjelaskan artinya tetapi saya telah membuat diri saya sedikit gambar, sebagai referensi untuk mengingatkan yang akan digunakan:

masukkan deskripsi gambar di sini

Semoga ini bisa membantu!

PS - Beri tanda centang juga ke tautan dalam jawaban Nitay 🙂

Kamafather
sumber
3

Saya akan memposting memo saya di sini, karena saya harus kembali ke sini lagi dan lagi.

SKENARIO 1. Pengembang normal: Anda adalah pengembang yang tidak dapat bergabung masterdan harus bermain dengan featurecabang saja.

Kasus 1: tuan adalah raja. Anda ingin menyegarkan featurecabang Anda (= rebase to master), karena masterberisi pembaruan dependensi baru dan Anda ingin menimpa perubahan sederhana Anda.

git checkout master
git pull

git checkout feature
git rebase -X ours master

Kasus 2: Anda adalah raja. Anda ingin rebase featurecabang Anda ke masterperubahan. Tetapi Anda melakukan lebih dari yang dimiliki kolega Anda dan ingin menggunakan perubahan Anda sendiri dalam prioritas.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

PENTING: Seperti yang Anda lihat, pengembang normal harus memilih rebasedan mengulanginya setiap pagi seperti latihan / kopi.

SKENARIO 2. Penggabungan-sensei: Anda adalah pemimpin tim dan ingin menggabungkan cabang lain dan mendorong hasil gabungan langsung ke master. masteradalah cabang yang akan Anda ubah.

Kasus 1: master adalah raja Anda ingin menggabungkan cabang pihak ketiga, tetapi mastermerupakan prioritas. featureadalah cabang yang senior Anda lakukan.

git checkout feature
git pull

git checkout master
git merge -X ours master

Kasus 2: perubahan baru adalah raja Ketika pengembang senior Anda merilis yang keren featuredan Anda ingin menimpa yang lama di mastercabang.

git checkout feature
git pull

git checkout master
git merge -X theirs master

INGAT: Untuk mengingat di tengah malam yang satu untuk memilih: masteradalah oursSELALU. Dan theirsitu featureyang mereka lakukan.

DenisKolodin
sumber
2

Dari git checkoutpenggunaan:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

Saat menyelesaikan konflik gabungan, Anda bisa melakukannya git checkout --theirs some_file, dan git checkout --ours some_fileuntuk mereset file ke versi saat ini dan versi yang masuk masing-masing.

Jika sudah selesai git checkout --ours some_fileatau git checkout --theirs some_fileingin mengatur ulang file ke versi penggabungan 3 arah file, Anda bisa melakukannya git checkout --merge some_file.

Joshua Ryan
sumber