git rebase, theo dõi 'cục bộ' và 'từ xa'


174

Khi thực hiện một cuộc nổi loạn git, tôi thường gặp khó khăn khi tìm hiểu những gì đang xảy ra với 'cục bộ' và 'từ xa' khi giải quyết xung đột. Đôi khi tôi có ấn tượng rằng họ trao đổi bên từ một cam kết sang tiếp theo.

Điều này có lẽ (chắc chắn) bởi vì tôi vẫn chưa hiểu đúng.

Khi nổi loạn, ai là 'người địa phương' và ai là 'người ở xa'?

(Tôi sử dụng P4Merge để giải quyết xung đột)


Có thể đọc sẽ giúp bạn? Phần còn lại của hướng dẫn cũng rất hữu ích ....
ivans

Một nguồn tài nguyên git tuyệt vời .
Không biết

Sẽ stackoverflow.com/questions/2959443/ giúp đỡ? (không dành cho phần ' git svn', chỉ dành cho phần ' git rebase')
VonC

@VonC, vâng, chính xác là như vậy. Nếu bạn muốn sao chép một chút câu trả lời có liên quan của bạn ở đây, tôi sẽ đánh dấu vào đó (tôi thực sự sẽ đến lúc này, tôi hứa đấy!)
Stewol

được rồi ... tôi sẽ cắn;) Các trích đoạn có liên quan được đăng.
VonC

Câu trả lời:


243

TL; DR;

Để tóm tắt (Như Benubird bình luận ), khi:

git checkout A
git rebase   B    # rebase A on top of B
  • localB(rebase lên ),
  • remoteA

Và:

git checkout A
git merge    B    # merge B into A
  • localA(hợp nhất thành ),
  • remoteB

Một rebase chuyển ours(nhánh hiện tại trước khi bắt đầu rebase) và theirs(nhánh trên đó bạn muốn rebase).


kutschkem chỉ ra rằng, trong bối cảnh GUI mergetool :

  • tham chiếu cục bộ các cam kết bị từ chối một phần : " ours" (nhánh ngược dòng)
  • từ xa đề cập đến các thay đổi đến : " theirs" - nhánh hiện tại trước khi rebase.

Xem hình minh họa trong phần cuối của câu trả lời này.


Đảo ngược khi rebase

Sự nhầm lẫn có thể liên quan đến sự đảo ngược ourstheirstrong một cuộc nổi loạn .
(trích xuất có liên quan)

git rebasetrang nam :

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 đỉnh của <upstream>nhánh.

Bởi vì điều này, khi một cuộc xung đột hợp nhất xảy ra:

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

Minh họa đảo ngược

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 chi 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 chi nhánh khác)

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

Trên một cuộc nổi loạn:

Nhưng trên một rebase , chúng tôi chuyển sang bên vì điều đầu tiên một 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 đầu trang)

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 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 '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

Lưu ý: khái niệm "ngược dòng" là tập hợp dữ liệu tham chiếu (tất cả repo hoặc, như ở đây, một nhánh, có thể là một nhánh cục bộ ) từ đó dữ liệu được đọc hoặc dữ liệu mới được thêm / tạo.


' local' và ' remote' so với ' mine' và ' theirs'

Pandawood thêm vào trong các ý kiến :

Đối với tôi, câu hỏi vẫn còn, đó là "cục bộ" và ai là "từ xa" (vì thuật ngữ "của chúng tôi" và "của họ" không được sử dụng khi nổi loạn trong git, đề cập đến chúng dường như làm cho một câu trả lời khó hiểu hơn) .

GUI git mergetool

kutschkem thêm, và đúng như vậy:

Khi giải quyết xung đột, git sẽ nói điều gì đó như:

local: modified file and remote: modified file. 

Tôi khá chắc chắn rằng câu hỏi nhằm vào định nghĩa của địa phương và từ xa tại thời điểm này. Tại thời điểm đó, dường như với kinh nghiệm của tôi rằng:

  • tham chiếu cục bộ các cam kết bị từ chối một phần : " ours" (nhánh ngược dòng)
  • từ xa đề cập đến các thay đổi đến : " theirs" - nhánh hiện tại trước khi rebase.

git mergetoolthực sự đề cập đến 'địa phương' và 'từ xa' :

Merging:
f.txt

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

Chẳng hạn, KDiff3 sẽ hiển thị độ phân giải hợp nhất như vậy :

kdiff3

meld cũng sẽ hiển thị nó :

Meld khác

Tương tự cho VimDiff , hiển thị :

Gọi Vimdiff như là một mergetool với git mergetool -t gvimdiff. Các phiên bản gần đây của Git gọi Vimdiff với bố cục cửa sổ sau:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
  • LOCAL:
    Một tệp tạm thời chứa nội dung của tệp trên nhánh hiện tại.
  • BASE:
    Một tệp tạm thời chứa cơ sở chung cho việc hợp nhất.
  • REMOTE:
    Một tệp tạm thời chứa nội dung của tệp sẽ được hợp nhất.
  • MERGED:
    Tập tin chứa các dấu xung đột.

Git đã thực hiện càng nhiều giải quyết xung đột tự động càng tốt và trạng thái của tệp này là sự kết hợp của cả hai LOCALREMOTEvới các dấu xung đột xung quanh bất cứ điều gì mà Git không thể tự giải quyết.
Các mergetoolnên viết là kết quả của các giải pháp cho tập tin này.


13
Đối với tôi, câu hỏi vẫn còn, đó là "cục bộ" và ai là "từ xa" (vì thuật ngữ "của chúng tôi" và "của họ" không được sử dụng khi nổi loạn trong git, đề cập đến chúng dường như làm cho một câu trả lời khó hiểu hơn) . Câu hỏi là "ai là người địa phương & ai là người ở xa" - vì vậy một câu trả lời chắc chắn yêu cầu đề cập đến các từ "địa phương" và "từ xa"
PandaWood

@PandaWood: "local" là "nhánh hiện tại" (trở thành "của họ"), "remote" là "nhánh ngược dòng" (trở thành "nhánh của chúng ta").
VonC

3
Vì vậy, để tóm tắt: khi bạn git checkout A; git rebase Bđịa phương là B, từ xa là A. Tất cả những gì tôi cần biết ...
Benubird

1
git là một clusterfk khả năng sử dụng. điều này làm cho không có ý nghĩa: khi bạn git checkout A; git rebase Bở địa phương là B, vùng xa là Một . Nếu tôi checkout Athì hiện tại tôi đang xem các tập tin khi chúng tồn tại A, làm thế nào là điều khiển từ xa ? (Tôi không nói Benubird sai; Tôi đang nói git có một UX ngu ngốc)
Rafa

1
@VonC chắc chắn; Điểm (tán gẫu) của tôi là không nên đọc tài liệu, xem sơ đồ và phải duyệt StackOverflow. Nếu chỉ có lệnh cho phản hồi rõ ràng, rõ ràng. Ví dụ: thay vì cục bộ / từ xa / của họ / của chúng tôi / của tôi / của bạn, chỉ hiển thị {branch A}{branch B}tương tự.
Rafa

45

Điểm mấu chốt

git rebase

  • LOCAL = cơ sở bạn đang rebasing lên
  • GHI NHỚ = các cam kết bạn đang di chuyển lên trên

hợp nhất git

  • LOCAL = chi nhánh ban đầu bạn đang hợp nhất vào
  • GHI NHỚ = chi nhánh khác có cam kết bạn đang hợp nhất

Nói cách khác, LOCAL luôn là bản gốc và REMote luôn là người có cam kết không có ở đó trước đó, bởi vì họ đang được hợp nhất hoặc nổi loạn lên hàng đầu

Chứng minh điều đó!

Chắc chắn rồi. Đừng tin lời tôi! Đây là một thử nghiệm dễ dàng bạn có thể làm để tự mình xem.

Trước tiên, hãy chắc chắn rằng bạn đã git mergetool được cấu hình đúng. (Nếu bạn không, có lẽ bạn sẽ không đọc câu hỏi này.) Sau đó tìm một thư mục để làm việc.

Thiết lập kho lưu trữ của bạn:

md LocalRemoteTest
cd LocalRemoteTest

Tạo một cam kết ban đầu (với một tệp trống):

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

Tạo một cam kết trên một nhánh không phải là chủ:

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

Tạo một cam kết trên nhánh chính:

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

gitk --all

Tại thời điểm này, kho lưu trữ của bạn sẽ trông như thế này:

Kho lưu trữ với một cam kết cơ sở và hai nhánh một cam kết

Bây giờ cho bài kiểm tra rebase:

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

Bây giờ kiểm tra hợp nhất. Đóng mergetool của bạn mà không lưu bất kỳ thay đổi nào, và sau đó hủy rebase:

git rebase --abort

Sau đó:

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

Kết quả của bạn phải giống như những gì được hiển thị trên cùng.


1
+1. Đề cập đến những local/ remotekhía cạnh tôi phải vật lộn với trong câu trả lời của riêng tôi ở trên (đó là thêm về nghịch đảo của oursvs theirsanyway)
VonC

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.