Tại sao nghĩa của "của chúng ta" và "của họ" bị đảo ngược với git-svn


90

Tôi sử dụng git-svn và tôi nhận thấy rằng khi tôi phải khắc phục xung đột hợp nhất sau khi thực hiện a git svn rebase, ý nghĩa của các tùy chọn --ours--theirsđối với vd git checkoutsẽ bị đảo ngược. Đó là, nếu có xung đột và tôi muốn giữ lại phiên bản đến từ máy chủ SVN và loại bỏ những thay đổi tôi đã thực hiện cục bộ, tôi phải sử dụng ours, khi tôi mong đợi theirs.

Tại sao vậy?

Thí dụ:

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 đã cập nhật câu trả lời của tôi với rất nhiều sơ đồ để minh họa rõ hơn về mặt "của chúng ta" và "của chúng ta".
VonC

Câu trả lời:


230

Điều đó có vẻ phù hợp với những gì rebase làm.

  • git svn rebase sẽ tìm nạp các bản sửa đổi từ SVN cha của HEAD hiện tại và khôi phục lại hoạt động hiện tại (không cam kết với SVN) chống lại nó.

  • git rebasecó đề cập đến:
    Lưu ý rằng hợp nhất rebase hoạt động bằng cách phát lại từng cam kết từ nhánh làm việc trên đầu <upstream>nhánh.
    Do đó, khi xung đột hợp nhất xảy ra:

    • phía được báo cáo là của chúng tôi là loạt phim được phục hồi cho đến nay, bắt đầu bằng<upstream> ,
    • và của họ là nhánh làm việc .
      Nói cách khác, các bên được hoán đổi .

git rebase phát lại từng cam kết từ nhánh đang làm việc trên đầu <upstream>nhánh.

Nếu bạn dung hòa cả hai định nghĩa:

  • các cam kết đến từ SVN là những cam kết mà trên đó các cam kết Git cục bộ được phát lại. Chúng là một phần của "loạt phim được giảm giá cho đến nay" và được tham chiếu là "của chúng tôi" (trong trường hợp của bạn là test.txttệp có barnội dung)
  • nhánh làm việc (chứa Git cam kết không xác định với SVN, trong trường hợp của bạn, test.txttệp có baznội dung) là "của họ" và mỗi cam kết Git cục bộ đó đang được phát lại.

Nói cách khác, SVN hay không:

  • các " <upstream>" chi nhánh (trên đầu trang của bất cứ điều gì mà được tái hiện lại, và đó là một phần của cam kết cho đến nay rebased ") là" chúng ta ".
  • những gì đang được phát lại (nhánh làm việc) là " của họ ".

Tốt mũi mnemonic bởi CommaToast :

bất cứ điều gì HEAD trỏ tới là "của chúng tôi"

(và điều đầu tiên a git rebase upstreamthực hiện là kiểm tra upstreamnhánh trên cùng mà bạn muốn rebase: HEAD đề cập đến upstream- oursngay bây giờ.)


Sự nhầm lẫn có thể đến từ vai trò của nhánh làm việc trong một tác phẩm cổ điển git merge.
Khi bạn đang hợp nhất:

  • "chi nhánh làm việc" là chi nhánh chứa những gì được "hợp nhất cho đến nay" và được coi là "của chúng tôi",
  • trong khi cam kết khác đại diện cho những gì đang được - không được phát lại nhưng - hợp nhất trên đầu nhánh làm việc và được coi là "của chúng".

Như git rebasetrang người đàn ông đề cập, hợp nhất trong một rebase có nghĩa là các bên được hoán đổi.


Một cách khác để nói điều tương tự là xem xét rằng:

  • những gì chúng tôi có trên chi nhánh đã thanh toán là 'của chúng tôi ',
  • những gì chúng tôi đã có (và đang được hợp nhất hoặc phát lại) là ' của họ '.

Khi hợp nhất :

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

, chúng tôi không thay đổi nhánh hiện tại 'B', vì vậy những gì chúng tôi có vẫn là những gì chúng tôi đang làm việc (và chúng tôi hợp nhất từ ​​một nhánh khác)

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

Nhưng trên rebase , chúng tôi đổi bên vì điều đầu tiên mà rebase làm là kiểm tra nhánh ngược dòng! (để phát lại các cam kết hiện tại trên đó)

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

git rebase upstreamĐầu tiên A sẽ thay đổi HEADB thành nhánh ngược dòng HEAD(do đó chuyển đổi của 'của chúng ta' và 'của họ' so với nhánh làm việc "hiện tại" trước đó.)

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

và sau đó rebase sẽ phát lại các cam kết 'của họ' trên nhánh B mới của 'chúng tôi':

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

Bước bổ sung duy nhất git svn rebaselà "tìm nạp" svn được thực hiện đầu tiên trên nhánh từ xa Git đại diện cho các cam kết của SVN.
Ban đầu bạn có:

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

, trước tiên bạn cập nhật nhánh theo dõi SVN với các cam kết mới đến từ SVN

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

, sau đó bạn chuyển nhánh hiện tại sang phía SVN (trở thành "của chúng tôi")

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

, trước khi phát lại các cam kết mà bạn đã thực hiện (nhưng bây giờ là "của họ" trong quá trình rebase đó)

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
Wow, thật là một câu trả lời tuyệt vời, cảm ơn! Tôi phải đã hoàn toàn bị mất rằng nhận xét trong git rebasetrang người đàn ông ...
Marc Liyanage

@epologee: không có chi. Nó cũng hữu ích khi bạn chỉ sử dụng git, để hiểu những gì đang diễn ra trong quá trình rebase so với hợp nhất. Và nó bổ sung vào định nghĩa ngược dòng: stackoverflow.com/questions/2739376/…
VonC

5
Chúa tôi!!! Torvalds đã dùng những loại thuốc gì? Đây là cách quá phức tạp! Git là một công cụ rất nguy hiểm. Bạn có thể dễ dàng phá hủy tất cả công việc của mình nếu bạn cố gắng sử dụng kiến ​​thức bên ngoài hoặc trực giác của mình. Sự phát triển phần mềm đã đi xuống lỗ sâu!
ATL_DEV

@ user148298 Không có gì sai cho chức năng này. Bạn không cần phải biết tất cả những thứ đó trừ khi bạn là một chuyên gia về git. Và nếu bạn yêu cầu các chức năng nâng cao, bạn sẽ phải học nó trước.
Earth Engine
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.