git rebase ติดตาม 'ท้องถิ่น' และ 'ระยะไกล'


174

เมื่อทำการ git rebase ฉันมักจะมีปัญหาในการหาสิ่งที่เกิดขึ้นกับ 'local' และ 'remote' เมื่อแก้ไขข้อขัดแย้ง บางครั้งฉันก็รู้สึกว่าพวกเขาสลับข้างจากคนหนึ่งไปยังอีกคนหนึ่ง

อาจเป็น (แน่นอน) เพราะฉันยังไม่เข้าใจ

เมื่อทำการรีบูตใครคือ 'ท้องถิ่น' และใครคือ 'ระยะไกล'

(ฉันใช้ P4Merge เพื่อแก้ไขข้อขัดแย้ง)


เป็นไปได้ไหมที่การอ่านสิ่งนี้จะช่วยคุณได้? ส่วนที่เหลือของบทช่วยสอนก็มีประโยชน์เช่นกัน ....
ivans

อีกคอมไพล์ที่ยอดเยี่ยมทรัพยากร
ไม่ทราบ

จะstackoverflow.com/questions/2959443/...ความช่วยเหลือ? (ไม่ใช่สำหรับส่วน ' git svn' เพียงเพื่อส่วน ' git rebase')
VonC

@VonC ใช่นั่นแหละ หากคุณต้องการคัดลอกบิตที่เกี่ยวข้องของคำตอบของคุณมากกว่าที่นี่ฉันจะติ๊กมัน (ผมจะเวลานี้ฉันสัญญา!)
Benjol

ถูกต้อง ... ฉันจะกัด;) สารสกัดที่เกี่ยวข้องที่โพสต์
VonC

คำตอบ:


244

TL; DR;

เพื่อสรุป (เป็นความคิดเห็นBenubird ) เมื่อ:

git checkout A
git rebase   B    # rebase A on top of B
  • localคือB(rebase สู่ )
  • remote คือ A

และ:

git checkout A
git merge    B    # merge B into A
  • localคือA(รวมเข้าไป )
  • remote คือ B

สวิตช์ rebase ours(สาขาปัจจุบันก่อนที่จะเริ่ม rebase) และtheirs(สาขาที่ด้านบนที่คุณต้องการ rebase)


kutschkemชี้ให้เห็นว่าในบริบท GUI mergetool :

  • การอ้างอิงโลคัลที่กระทำต่อที่ถูกปฏิเสธบางส่วน : " ours" (สาขาต้นน้ำ)
  • ระยะไกลหมายถึงการเปลี่ยนแปลงที่เข้ามา : " theirs" - สาขาปัจจุบันก่อนที่จะ rebase

ดูภาพประกอบในส่วนสุดท้ายของคำตอบนี้


ผกผันเมื่อรีบูต

ความสับสนที่อาจจะเกี่ยวข้องกับการผกผันของoursและtheirsในช่วง rebase
(สารสกัดที่เกี่ยวข้อง)

git rebaseหน้าคน :

โปรดทราบว่าการรวม rebase จะทำงานโดยการเล่นซ้ำแต่ละการกระทำจากสาขาที่ทำงานอยู่ด้านบนของ<upstream>สาขา

ด้วยเหตุนี้เมื่อเกิดข้อขัดแย้งในการผสาน:

  • ด้านรายงานว่า ' ours' คือ rebased ดังนั้นไกลชุดเริ่มต้นด้วย<upstream>,
  • และ ' theirs' เป็นสาขาที่ทำงาน กล่าวอีกนัยหนึ่งคือสลับข้าง

ภาพประกอบการผกผัน

เมื่อรวมกัน

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

เราไม่เปลี่ยนสาขา 'B' ปัจจุบันดังนั้นสิ่งที่เรายังคงเป็นสิ่งที่เรากำลังทำอยู่ (และเรารวมจากสาขาอื่น)

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

ในการรีบูต:

แต่ในการ rebaseเราสลับข้างเพราะสิ่งแรกที่ rebase ทำคือการเช็คเอาสาขาต้นน้ำ! (เพื่อเล่นซ้ำกระทำปัจจุบันด้านบนของมัน)

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

A git rebase upstreamจะเปลี่ยนHEADB เป็นสาขาต้นน้ำเป็นครั้งแรกHEAD(ดังนั้นการสลับของ 'ของเรา' และ 'ของพวกเขา' เมื่อเปรียบเทียบกับสาขาที่ทำงาน "ปัจจุบัน" ก่อนหน้านี้)

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

และจากนั้นการรีบูตจะเล่นซ้ำ 'การกระทำของพวกเขาในสาขา B ของเรา:

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

หมายเหตุ: แนวคิด"อัพสตรีม"เป็นชุดข้อมูลอ้างอิง (repo ทั้งหมดหรือเช่นที่นี่สาขาซึ่งอาจเป็นสาขาท้องถิ่น ) ซึ่งข้อมูลจะถูกอ่านหรือมีการเพิ่ม / สร้างข้อมูลใหม่


' local' และ ' remote' กับ ' mine' และ ' theirs'

Pandawoodเพิ่มในความคิดเห็น :

สำหรับฉันคำถามยังคงอยู่ซึ่งเป็น "ท้องถิ่น" และใครคือ "ระยะไกล" (เนื่องจากข้อกำหนด "ของเรา" และ "ของพวกเขา" ไม่ได้ใช้เมื่อรีบูตในคอมไพล์หมายถึงพวกเขาดูเหมือนจะทำให้คำตอบสับสนมากขึ้น) .

GUI git mergetool

kutschkemเพิ่มและถูกต้องดังนั้น:

เมื่อแก้ไขข้อขัดแย้ง git จะพูดดังนี้:

local: modified file and remote: modified file. 

ฉันค่อนข้างมั่นใจว่าคำถามนี้มีจุดมุ่งหมายที่คำจำกัดความของท้องถิ่นและระยะไกล ณ จุดนี้ ณ จุดนั้นดูเหมือนว่าฉันจากประสบการณ์ของฉันที่:

  • การอ้างอิงโลคัลที่กระทำต่อที่ถูกปฏิเสธบางส่วน : " ours" (สาขาต้นน้ำ)
  • ระยะไกลหมายถึงการเปลี่ยนแปลงที่เข้ามา : " theirs" - สาขาปัจจุบันก่อนที่จะ rebase

git mergetoolไม่พูดถึง 'ท้องถิ่น' และ 'ระยะไกล' อย่างแน่นอน :

Merging:
f.txt

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

ตัวอย่างเช่นKDiff3จะแสดงความละเอียดผสานดังนี้:

kdiff3

และmeldก็จะแสดงมันเช่นกัน:

Meld ต่างกัน

เหมือนกันสำหรับvimdiff , ซึ่งแสดง :

เรียกใช้ Vimdiff เป็น mergetool ด้วย git mergetool -t gvimdiff Git เวอร์ชันล่าสุดเรียกใช้ Vimdiff ด้วยเค้าโครงหน้าต่างต่อไปนี้:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
  • LOCAL:
    ไฟล์ชั่วคราวที่มีเนื้อหาของไฟล์ในสาขาปัจจุบัน
  • BASE:
    ไฟล์ชั่วคราวที่มีฐานร่วมสำหรับการผสาน
  • REMOTE:
    ไฟล์ชั่วคราวที่มีเนื้อหาของไฟล์ที่จะผสาน
  • MERGED:
    ไฟล์ที่มีเครื่องหมายข้อขัดแย้ง

Git ดำเนินการแก้ไขข้อขัดแย้งโดยอัตโนมัติให้ได้มากที่สุดเท่าที่จะเป็นไปได้และสถานะของไฟล์นี้เป็นการรวมกันของทั้งคู่LOCALและREMOTEกับตัวทำเครื่องหมายความขัดแย้งที่ล้อมรอบสิ่งใดก็ตามที่ Git ไม่สามารถแก้ไขได้ ควรเขียนผลมาจากมติให้ไฟล์นี้
mergetool


13
สำหรับฉันคำถามยังคงอยู่ซึ่งเป็น "ท้องถิ่น" และใครคือ "ระยะไกล" (เนื่องจากข้อกำหนด "ของเรา" และ "ของพวกเขา" ไม่ได้ใช้เมื่อรีบูตในคอมไพล์หมายถึงพวกเขาดูเหมือนจะทำให้คำตอบสับสนมากขึ้น) . คำถามคือ "ใครเป็นคนท้องถิ่นและคนที่อยู่ห่างไกล" - ดังนั้นคำตอบก็ต้องพูดถึงคำว่า "ท้องถิ่น" และ "ห่างไกล"
PandaWood

@PandaWood: "local" คือ "สาขาปัจจุบัน" (ซึ่งกลายเป็น "พวกเขา") "remote" คือ "upstream branch" (ซึ่งกลายเป็น "ours")
VonC

3
ดังนั้นเพื่อสรุป: เมื่อคุณgit checkout A; git rebase Bท้องถิ่น B, A. ระยะไกลทั้งหมดที่ฉันต้องการจะรู้ว่า ...
Benubird

1
git เป็นกลุ่มของการใช้งาน นี้ทำให้รู้สึกไม่: เมื่อคุณgit checkout A; git rebase Bท้องถิ่น B, ระยะไกลเป็น หากฉันcheckout Aแล้วตอนนี้ฉันกำลังดูไฟล์ตามที่มีอยู่Aแล้วระยะไกลนั้นเป็นอย่างไร? (ฉันไม่ได้พูดว่า Benubird ผิดฉันกำลังพูดว่า git มีคนโง่ UX)
Rafa

1
@VonC แน่นอน; จุดของฉัน (คุยโว) คือไม่ควรอ่านเอกสารดูที่ไดอะแกรมและต้องเรียกดู StackOverflow หากมีเพียงคำสั่งที่ให้ข้อเสนอแนะที่ชัดเจนและชัดเจน ตัวอย่างเช่นแทนที่จะแสดงเฉพาะในพื้นที่ / ห่างไกล / ของพวกเขา / ของเรา / ของฉัน / ของคุณเพียงแสดง{branch A}และ{branch B}หรือคล้ายกัน
Rafa

45

บรรทัดล่างสุด

git rebase

  • LOCAL = ฐานที่คุณกำลัง rebasing บน
  • REMOTE = การคอมมิชชันที่คุณกำลังทำอยู่ด้านบน

คอมไพล์ผสาน

  • LOCAL = สาขาดั้งเดิมที่คุณกำลังรวมเข้าด้วยกัน
  • REMOTE = สาขาอื่นที่คุณกำลังรวมอยู่

กล่าวอีกนัยหนึ่งLOCALเป็นต้นฉบับเสมอและREMOTEมักจะเป็นคนที่ไม่เคยมีมาก่อนเพราะพวกเขาถูกรวมเข้าด้วยกันหรือถูกไล่ออกจากด้านบน

พิสูจน์สิ!

อย่างแน่นอน อย่าเอาคำพูดของฉันไป! นี่คือการทดลองง่ายๆที่คุณสามารถทำได้เพื่อดูด้วยตัวคุณเอง

ขั้นแรกตรวจสอบให้แน่ใจว่าคุณได้กำหนดค่า git mergetool อย่างถูกต้อง (ถ้าคุณทำไม่ได้คุณอาจจะไม่อ่านคำถามนี้อยู่ดี) จากนั้นหาไดเรกทอรีที่จะใช้งาน

ตั้งค่าที่เก็บของคุณ:

md LocalRemoteTest
cd LocalRemoteTest

สร้างการคอมมิทเริ่มต้น (ด้วยไฟล์ว่าง):

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."

สร้างการมอบหมายในสาขาที่ไม่ใช่ผู้เชี่ยวชาญ:

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

สร้างการมอบหมายในสาขาหลัก:

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

gitk --all

ณ จุดนี้ที่เก็บของคุณควรมีลักษณะเช่นนี้:

พื้นที่เก็บข้อมูลที่มีฐานกระทำและสองสาขาหนึ่งกระทำ

ตอนนี้สำหรับการทดสอบการรีบูต:

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

ตอนนี้การทดสอบผสาน ปิด mergetool ของคุณโดยไม่บันทึกการเปลี่ยนแปลงใด ๆ จากนั้นยกเลิก rebase:

git rebase --abort

แล้ว:

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

ผลลัพธ์ของคุณควรเหมือนกับสิ่งที่ปรากฏอยู่ด้านบน


1
+1 ที่ชี้แจงlocal/ remoteด้านฉันต่อสู้กับในคำตอบของตัวเองข้างต้น (ซึ่งเป็นเรื่องเกี่ยวกับการผกผันของoursVS theirsต่อไป)
VonC

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.