git rebase, melacak 'lokal' dan 'jauh'

174

Ketika melakukan git rebase, saya sering mengalami kesulitan untuk mengetahui apa yang terjadi dengan 'lokal' dan 'remote' ketika menyelesaikan konflik. Terkadang saya memiliki kesan bahwa mereka bertukar sisi dari satu komit ke yang berikutnya.

Ini mungkin (pasti) karena saya masih belum mengerti dengan baik.

Saat rebasing, siapa yang 'lokal' dan siapa yang 'jauh'?

(Saya menggunakan P4Merge untuk menyelesaikan konflik)

Benjol
sumber
Mungkinkah membaca ini akan membantu Anda? Sisa tutorial ini juga sangat membantu ....
ivans
Sumber daya git lain yang luar biasa .
Tidak diketahui
Apakah stackoverflow.com/questions/2959443/… membantu? (bukan untuk bagian ' git svn', hanya untuk bagian ' git rebase')
VonC
@VonC, ya, memang begitu. Jika Anda ingin menyalin sedikit jawaban Anda yang relevan di sini, saya akan mencentangnya (saya benar-benar akan kali ini, saya janji!)
Benjol
baiklah ... saya akan gigit;) Ekstrak yang relevan diposting.
VonC

Jawaban:

244

TL; DR;

Untuk meringkas (Seperti komentar Benubird ), ketika:

git checkout A
git rebase   B    # rebase A on top of B
  • localadalah B(rebase ke ),
  • remote adalah A

Dan:

git checkout A
git merge    B    # merge B into A
  • localadalah A(bergabung ke ),
  • remote adalah B

Saklar rebase ours(cabang saat ini sebelum rebase dimulai) dan theirs(cabang di atasnya Anda ingin rebase).


kutschkem menunjukkan bahwa, dalam konteks GUI mergetool :

  • referensi lokal komitmen sebagian rebased : " ours" (cabang hulu)
  • remote merujuk pada perubahan yang masuk : " theirs" - cabang saat ini sebelum rebase.

Lihat ilustrasi di bagian terakhir dari jawaban ini.


Pembalikan saat rebase

Kebingungan mungkin terkait dengan inversi oursdan theirsselama rebase .
(ekstrak yang relevan)

git rebasehalaman manual :

Perhatikan bahwa gabungan rebase berfungsi dengan memutar ulang setiap komit dari cabang kerja di atas <upstream>cabang.

Karena itu, ketika konflik gabungan terjadi:

  • sisi yang dilaporkan sebagai ' ours' adalah seri rebased sejauh ini, dimulai dengan <upstream>,
  • dan ' theirs' adalah cabang kerja. Dengan kata lain, sisi-sisinya ditukar.

Pembalikan diilustrasikan

Sedang digabung

x--x--x--x--x(*) <- current branch B ('*'=HEAD)
    \
     \
      \--y--y--y <- other branch to merge

, kami tidak mengubah cabang saat ini 'B', jadi apa yang kami miliki masih apa yang sedang kami kerjakan (dan kami bergabung dari cabang lain)

x--x--x--x--x---------o(*)  MERGE, still on branch B
    \       ^        /
     \     ours     /
      \            /
       --y--y--y--/  
               ^
              their

Pada rebase:

Tetapi pada rebase , kami beralih sisi karena hal pertama rebase lakukan adalah untuk checkout cabang hulu! (untuk memutar ulang komit saat ini di atasnya)

x--x--x--x--x(*) <- current branch B
    \
     \
      \--y--y--y <- upstream branch

A git rebase upstreamakan pertama-tama mengubah HEADB ke cabang hulu HEAD(oleh karena itu pergantian 'milik kami' dan 'milik mereka' dibandingkan dengan cabang kerja "saat ini" sebelumnya.)

x--x--x--x--x <- former "current" branch, new "theirs"
    \
     \
      \--y--y--y(*) <- upstream branch with B reset on it,  
                       new "ours", to replay x's on it

, dan kemudian rebase akan memutar ulang komitmen 'mereka' pada cabang B 'baru' kami:

x--x..x..x..x <- old "theirs" commits, now "ghosts", available through reflogs
    \
     \
      \--y--y--y--x'--x'--x'(*) <-  branch B with HEAD updated ("ours")
               ^
               |
        upstream branch

Catatan: gagasan "hulu" adalah kumpulan data referensial (semua repo atau, seperti di sini, cabang, yang dapat berupa cabang lokal ) dari mana data dibaca atau dari mana data baru ditambahkan / dibuat.


' local' dan ' remote' vs. ' mine' dan ' theirs'

Pandawood menambahkan dalam komentar :

Bagi saya, pertanyaannya masih ada, yaitu "lokal" dan siapa yang "jauh" (karena istilah "milik kita" dan "milik mereka" tidak digunakan ketika rebasing di git, merujuk pada mereka sepertinya membuat jawaban lebih membingungkan) .

GUI git mergetool

kutschkem menambahkan, dan memang demikian:

Saat menyelesaikan konflik, git akan mengatakan sesuatu seperti:

local: modified file and remote: modified file. 

Saya cukup yakin pertanyaannya mengarah pada definisi lokal dan jarak jauh pada saat ini. Pada titik itu, menurut saya dari pengalaman saya bahwa:

  • referensi lokal komitmen sebagian rebased : " ours" (cabang hulu)
  • remote merujuk pada perubahan yang masuk : " theirs" - cabang saat ini sebelum rebase.

git mergetoolmemang menyebutkan 'lokal' dan 'jauh' :

Merging:
f.txt

Normal merge conflict for 'f.txt':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (kdiff3):

Sebagai contoh, KDiff3 akan menampilkan resolusi gabungan seperti :

kdiff3

Dan berbaur akan menampilkannya juga :

Meld diff

Sama untuk VimDiff , yang menampilkan :

Aktifkan Vimdiff sebagai mergetool dengan git mergetool -t gvimdiff. Versi terbaru dari Git memanggil Vimdiff dengan tata letak jendela berikut:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
  • LOCAL:
    File sementara yang berisi konten file di cabang saat ini.
  • BASE:
    File sementara yang berisi basis umum untuk penggabungan.
  • REMOTE:
    File sementara yang berisi konten file yang akan digabungkan.
  • MERGED:
    File yang mengandung penanda konflik.

Git telah melakukan resolusi konflik otomatis sebanyak mungkin dan keadaan file ini adalah kombinasi dari keduanya LOCALdan REMOTEdengan penanda konflik yang mengelilingi apapun yang tidak dapat diselesaikan oleh Git sendiri.
The mergetoolharus menulis hasil resolusi ke berkas ini.

VONC
sumber
13
Bagi saya, pertanyaannya masih tetap, yaitu "lokal" dan siapa yang "jauh" (karena istilah "milik kita" dan "milik mereka" tidak digunakan ketika rebitting di git, merujuk pada mereka sepertinya membuat jawaban lebih membingungkan) . Pertanyaannya adalah "siapa yang lokal & siapa yang jauh" - jadi jawaban pasti mengharuskan menyebutkan kata "lokal" dan "jauh"
PandaWood
@PandaWood: "lokal" adalah "cabang saat ini" (yang menjadi "milik mereka"), "jarak jauh" adalah "cabang hulu" (yang menjadi "milik kami").
VonC
3
Jadi, untuk meringkas: ketika Anda git checkout A; git rebase Blokal adalah B, jarak jauh adalah A. Yang saya perlu tahu ...
Benubird
1
git adalah clusterfk dari kegunaan. ini tidak masuk akal: bila Anda git checkout A; git rebase Blokal B, remote A . Jika saya checkout Amaka saya saya sedang melihat file karena mereka ada di A, bagaimana itu dengan cara apapun yang terpencil ? (Saya tidak mengatakan Benubird salah; Saya katakan git memiliki UX bodoh)
Rafa
1
@VonC yakin; Maksud saya (ranting) adalah tidak perlu membaca dokumentasi, melihat diagram, dan harus menelusuri StackOverflow. Jika saja perintahnya memberikan umpan balik yang jelas dan tidak ambigu. Misalnya, alih-alih lokal / jauh / milik mereka / milik kita / milikku / milikmu, hanya tampilkan {branch A}dan {branch B}atau serupa.
Rafa
45

Garis bawah

git rebase

  • LOCAL = dasar Anda rebasing ke
  • REMOTE = komit yang bergerak di atas

git bergabung

  • LOCAL = cabang asli tempat Anda bergabung
  • REMOTE = cabang lain yang melakukan Anda bergabung

Dengan kata lain, LOCAL selalu yang asli, dan REMOTE selalu orang yang komitnya tidak ada di sana sebelumnya, karena mereka digabung atau di-rebase di atas

Buktikan itu!

Pasti. Jangan mengambil kata-kata saya untuk itu! Inilah eksperimen mudah yang dapat Anda lakukan untuk melihatnya sendiri.

Pertama, pastikan git mergetool Anda terkonfigurasi dengan benar. (Jika tidak, Anda mungkin tidak akan membaca pertanyaan ini.) Kemudian cari direktori untuk bekerja.

Siapkan repositori Anda:

md LocalRemoteTest
cd LocalRemoteTest

Buat komit awal (dengan file kosong):

git init
notepad file.txt  (use the text editor of your choice)
  (save the file as an empty file)
git add -A
git commit -m "Initial commit."

Buat komit di cabang yang bukan master:

git checkout -b notmaster
notepad file.txt
  (add the text: notmaster)
  (save and exit)
git commit -a -m "Add notmaster text."

Buat komit di cabang master:

git checkout master
notepad file.txt
  (add the text: master)
  (save and exit)
git commit -a -m "Add master text."

gitk --all

Pada titik ini repositori Anda akan terlihat seperti ini:

Repositori dengan komit dasar dan dua cabang komit satu

Sekarang untuk tes rebase:

git checkout notmaster
git rebase master
  (you'll get a conflict message)
git mergetool
  LOCAL: master
  REMOTE: notmaster

Sekarang tes penggabungan. Tutup mergetool Anda tanpa menyimpan perubahan apa pun, lalu batalkan rebase:

git rebase --abort

Kemudian:

git checkout master
git merge notmaster
git mergetool
  LOCAL: master
  REMOTE: notmaster
git reset --hard  (cancels the merge)

Hasil Anda harus sama dengan apa yang ditampilkan di bagian atas.

Ryan Lundy
sumber
1
+1. Bahwa mengklarifikasi yang local/ remoteaspek aku berjuang dengan jawaban saya sendiri di atas (yang lebih tentang inversi oursvs theirspula)
VonC
3

Saya tidak mendapatkan masalah Anda dengan tepat tetapi saya pikir diagram berikut ini menyelesaikan masalah Anda. (Rebase: Repositori Jarak Jauh ---> Workspace)

http://assets.osteele.com/images/2008/git-transport.png

Sumber: Alur Kerja Git Saya

Chathuranga Chandrasekara
sumber