เหตุใดความหมายของ "ของเรา" และ "ของพวกเขา" จึงกลับกันด้วย git-svn


91

ฉันใช้ git-svn และฉันสังเกตเห็นว่าเมื่อฉันต้องแก้ไขข้อขัดแย้งในการผสานหลังจากดำเนินการ a git svn rebaseแล้วความหมายของ--oursและ--theirsตัวเลือกที่จะ eg git checkoutจะกลับรายการ นั่นคือถ้ามีความขัดแย้งและผมต้องการที่จะให้รุ่นที่มาจากเซิร์ฟเวอร์ SVN และโยนออกไปการเปลี่ยนแปลงที่ผมทำในประเทศผมต้องใช้เมื่อผมจะคาดหวังว่ามันจะourstheirs

ทำไมถึงเป็นเช่นนั้น?

ตัวอย่าง:

mkdir test
cd test
svnadmin create svnrepo
svn co file://$PWD/svnrepo svnwc
cd svnwc
echo foo > test.txt
svn add test.txt
svn ci -m 'svn commit 1'
cd ..
git svn clone file://$PWD/svnrepo gitwc
cd svnwc
echo bar > test.txt 
svn ci -m 'svn commit 2'
cd ..
cd gitwc
echo baz > test.txt 
git commit -a -m 'git commit 1'
git svn rebase

git checkout --ours test.txt
cat test.txt 
# shows "bar" but I expect "baz"

git checkout --theirs test.txt
cat test.txt 
# shows "baz" but I expect "bar"

Jut อัปเดตคำตอบของฉันด้วยไดอะแกรมจำนวนมากเพื่ออธิบายด้าน "ของเรา" และ "ของพวกเขา" ได้ดีขึ้น
VonC

คำตอบ:


232

ดูเหมือนว่าจะสอดคล้องกับสิ่งที่ rebase ทำ

  • git svn rebase จะดึงข้อมูลการแก้ไขจากพาเรนต์ SVN ของ HEAD ปัจจุบันและปรับฐานปัจจุบัน (ไม่ถูกคอมมิตกับ SVN) ทำงานกับมัน

  • git rebaseไม่กล่าวถึง:
    โปรดทราบว่าการผสาน rebase ทำงานโดยการเล่นซ้ำแต่ละคอมมิตจากสาขาการทำงานที่ด้านบนของ<upstream>สาขา
    ด้วยเหตุนี้เมื่อเกิดความขัดแย้งในการผสาน:

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

git rebase เล่นซ้ำแต่ละคอมมิตจากสาขาการทำงานที่ด้านบนของ<upstream>สาขา

หากคุณกระทบยอดคำจำกัดความทั้งสอง:

  • คอมมิตที่มาจาก SVN คือคอมมิตที่คอมมิตในเครื่องจะเล่นซ้ำ ซึ่งเป็นส่วนหนึ่งของ "ซีรีส์ที่มีการปรับปรุงใหม่" และอ้างอิงว่า "ของเรา" (ในกรณีของคุณคือtest.txtไฟล์ที่มีbarเนื้อหา)
  • สาขาการทำงาน (ที่มี Git คอมมิตที่ SVN ไม่รู้จักในกรณีของคุณtest.txtไฟล์ที่มีbazเนื้อหา) คือ "ของพวกเขา" และแต่ละคอมมิต Git ในเครื่องเหล่านั้นจะถูกเล่นซ้ำ

กล่าวอีกนัยหนึ่ง SVN หรือไม่:

  • ว่า " <upstream>สาขา" (ด้านบนของที่อะไรจะย้อนและซึ่งเป็นส่วนหนึ่งของการกระทำ rebased เพื่อให้ห่างไกล ") คือ" เรา "
  • สิ่งที่กำลังเล่นซ้ำ (สาขาการทำงาน) คือ "ของพวกเขา "

เคล็ดลับช่วยในการจำที่ดีโดยCommaToast :

สิ่งที่ HEAD ชี้ไปคือ "ของเรา"

(และสิ่งแรกคือการgit rebase upstreamชำระเงินupstreamสาขาที่คุณต้องการ rebase: HEAD หมายถึงupstream- oursตอนนี้)


git mergeความสับสนที่มีแนวโน้มที่จะมาจากบทบาทของสาขาการทำงานในแบบคลาสสิก
เมื่อคุณกำลังรวม:

  • "สาขาการทำงาน" คือสาขาที่มีสิ่งที่ "รวมกันแล้ว" และถือเป็น "ของเรา"
  • ในขณะที่การกระทำอื่น ๆ แสดงถึงสิ่งที่กำลังเป็นอยู่ - ไม่ได้เล่นซ้ำ แต่ - รวมอยู่ด้านบนของสาขาการทำงานและถือว่าเป็น "ของพวกเขา"

ตามที่git rebaseหน้าคนกล่าวถึงการผสานระหว่าง rebase หมายถึงการสลับด้าน


อีกวิธีหนึ่งในการพูดสิ่งเดียวกันคือการพิจารณาว่า:

  • สิ่งที่เรามีในสาขาที่เช็คเอาท์คือ 'ของเรา '
  • สิ่งที่เรามี (และกำลังถูกรวมหรือเล่นซ้ำ) คือ 'ของพวกเขา '

ในการรวม :

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

จากนั้น rebase จะเล่นซ้ำ 'การกระทำของพวกเขา' ใน 'สาขา 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

ขั้นตอนพิเศษเพียงอย่างเดียวgit svn rebaseคือ svn "fetch" จะถูกดำเนินการก่อนบน Git remote branch ที่เป็นตัวแทนของ SVN commits
ในตอนแรกคุณมี:

x--x--x--x--x(*) <- current branch B, "ours" for now.
    \                                   
     \
      \--y--y--y <- SVN tracking branch, "theirs for now"

ก่อนอื่นคุณอัปเดตสาขาการติดตาม SVN ด้วยคอมมิตใหม่ที่มาจาก SVN

x--x--x--x--x(*) <- current branch B, still "ours", not for long
    \                                   
     \
      \--y--y--y--y'--y' <- SVN tracking branch updated

จากนั้นคุณเปลี่ยนสาขาปัจจุบันเป็นด้าน SVN (ซึ่งกลายเป็น "ของเรา")

x--x--x--x--x <- for "B", now "their" during the rebase
    \                                   
     \
      \--y--y--y--y'--y'(*) <- SVN tracking branch updated, and branch B: 
                               now "ours" (this is "what we now have")

ก่อนที่จะเล่นคอมมิตที่คุณกำลังทำซ้ำ (แต่ตอนนี้เป็น "ของพวกเขา" ในระหว่างการรีเบสนั้น)

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

9
ว้าวเป็นคำตอบที่ดีมากขอบคุณ! ฉันคงพลาดคำพูดนั้นไปแล้วในgit rebaseหน้าคน ...
Marc Liyanage

@epologee: ยินดีต้อนรับ นอกจากนี้ยังมีประโยชน์เมื่อคุณใช้เฉพาะ git เพื่อทำความเข้าใจว่าเกิดอะไรขึ้นระหว่าง rebase เทียบกับการผสาน และเพิ่มความหมายของต้นน้ำ: stackoverflow.com/questions/2739376/…
VonC

5
พระเจ้า!!! Torvalds ใช้ยาชนิดใด? มันซับซ้อนเกินไป! Git เป็นเครื่องมือที่อันตรายมาก คุณสามารถทำลายงานทั้งหมดของคุณได้อย่างง่ายดายหากคุณพยายามใช้ความรู้ภายนอกหรือสัญชาตญาณของคุณ การพัฒนาซอฟแวร์ได้ลงรูหนอนแล้ว!
ATL_DEV

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