2010-04-22 37 views
14

Tôi đang đọc về việc sử dụng git như một ứng dụng svn ở đây:Yêu cầu git svn rebase trước git svn dcommit?

http://learn.github.com/p/git-svn.html

trang Điều đó cho thấy rằng bạn làm git svn rebase trước dcommit git svn, mà làm cho cảm giác hoàn hảo; nó giống như làm cập nhật svn trước khi thực hiện cam kết svn. Sau đó, tôi bắt đầu nhìn vào tài liệu hướng dẫn cho git svn dcommit (Tôi đã tự hỏi những gì mà 'd' là khoảng):

http://git-scm.com/docs/git-svn

Bạn phải cuộn xuống một chút để xem tài liệu trên dcommit, mà nói này:

Commit mỗi diff từ đầu quy định trực tiếp đến kho SVN, và sau đó rebase hoặc thiết lập lại (tùy thuộc vào có hay không có một diff giữa SVN và đầu).

Điều này gây nhầm lẫn cho tôi, bởi vì nếu bạn làm như trang đầu tiên cho biết, sẽ không có thay đổi nào để kéo xuống từ svn khi phần đầu tiên của quá trình kết thúc.

Tôi cũng bối rối bởi phần nói về việc đặt lại; không phải là git thiết lập lại để loại bỏ những thay đổi từ khu vực dàn dựng?

Tại sao sẽ rebase hoặc đặt lại theo dõi (phần đầu tiên) một dcommit?

Trả lời

19

Disclaimer: Tôi thường làm có xu hướng chạy git svn rebase trước khi làm một git svn dcommit. Tôi thường giữ những thay đổi của tôi trong một nhánh git khác, để việc rebase không có cơ hội thất bại. Tôi sử dụng git rebase master trong nhánh chủ đề của mình để cập nhật chi tiết. Sau đó, tôi chuyển sang chi nhánh master và sử dụng git merge để kết hợp các thay đổi từ nhánh chủ đề của tôi thành master (đây là một chuyển tiếp nhanh do việc rebase).

Giải thích của tôi dưới đây giải thích tại sao đây không phải là máy móc cần thiết, nhưng tôi đồng ý rằng bạn nên làm. Thay đổi của bạn có thể không gây xung đột về các khác biệt và hợp nhất, nhưng nếu bạn dcommit mã của mình mà không nhận được các thay đổi mới nhất từ ​​svn và xem lại hiệu ứng của chúng, bạn có thể cam kết mã svn không thực sự đúng.


Bạn không để git svn rebase trước khi chạy git svn dcommit. Nếu các sửa đổi bạn muốn dcommit là trong các tập tin mà không thay đổi trong svn kể từ khi bạn tìm nạp thay đổi cuối cùng, sau đó git-svn sẽ không hiển thị một cuộc xung đột. Bằng cách này, bạn có thể cam kết thay đổi một kho lưu trữ svn bằng cách sử dụng kho lưu trữ git mà không có tất cả các thay đổi mới nhất từ ​​svn.

Giả sử tôi bắt đầu kho lưu trữ svn chứa hai tệp, foo.txtbar.txt. Họ chỉ có một bản sửa đổi duy nhất cho đến nay. Tôi làm một git svn clone để bắt đầu theo dõi kho svn bằng git.

 
$ git log --oneline --decorate 
7e72290 (git-svn, master) Initial commit. 

Bạn thực hiện thay đổi để foo.txtgit commit họ master chi nhánh địa phương của bạn, vì vậy nó di chuyển về phía trước của git-svn.

 
$ git log --oneline --decorate 
aa70eca (master) Added a line to foo. 
7e72290 (git-svn) Initial commit. 

Những gì bạn đã không nhận ra là bạn của bạn đã cam kết thay đổi để bar.txt như phiên bản svn 2.

Bây giờ khi bạn chạy git svn dcommit từ master, git sẽ tìm kiếm changesets giữa bạn đang ở đâu và ở đâu git-svn bị tắt. Trong trường hợp này, bạn chỉ có một: aa70eca. git cố gắng gửi khác biệt đó đến kho lưu trữ svn của bạn.

 
$ git svn dcommit 
Committing to [svn repo address] ... 
     M  foo.txt 
Committed r3 
     M  bar.txt 
r2 = 12b95b96e11f782f31b07a78756660cb82437ca2 (refs/remotes/git-svn) 
     M  foo.txt 
r3 = d4a7b84e0383f3af5fb0db439169c9f1b8af1152 (refs/remotes/git-svn) 
W: aa70ecae4121854ac3754fb882a483b67d706a4a and refs/remotes/git-svn differ, using rebase: 
:100644 100644 5771152459bfaa7cc62caa3b6b4d24e52ab8e447 dbfaecb10330d0509e092f1891a4a7e673802413 M  bar.txt 
First, rewinding head to replay your work on top of it... 
Nothing to do. 

$ git log --oneline --decorate 
d4a7b84 (git-svn, master) Added a line to foo. 
12b95b9 Added to bar. 
7e72290 Initial commit. 

Bạn có thể thấy rằng các cam kết thành công như phiên bản svn 3. Khi git-svn sau đó đồng bộ sau lịch sử svn địa phương của bạn với kho svn, nó lấy tất cả các cam kết mới bao gồm sự thay đổi bạn chỉ cần nộp cho svn. Bạn sẽ nhận thấy rằng thay đổi này (d4a7b84) có hàm băm SHA khác với mã băm mà bạn đã từng sử dụng trong git (aa70eca). Điều này là do nhiều thứ: dấu thời gian cam kết khác nhau, tên tác giả có khả năng khác nhau, git-svn-id trong nhật ký của cam kết tìm nạp từ svn và tổ tiên khác nhau — svn r3 được tìm nạp có r2 làm cha mẹ của nó, nhưng cam kết git của bạn là hậu duệ từ r1.

Trong trường hợp này, có một lỗi được tìm thấy sau khi tìm nạp giữa đầu git hiện tại (master) và SVN, vì nội dung trong r2 thay đổi foo.txt. Do đó, git-svn sẽ rebase.

Nếu tôi thực hiện thay đổi và không có cam kết svn khác xảy ra trong thời gian chờ đợi (hoặc tôi đã chạy git svn rebase để cập nhật), thì git-svn sẽ không tìm thấy sự khác biệt giữa đầu và SVN, vì vậy nó có thể đặt lại:

 
$ git svn dcommit 
Committing to [svn repo address] ... 
     M  foo.txt 
Committed r4 
     M  foo.txt 
r4 = 533f7337999778628cf39fcd9155d085eb1c2b89 (refs/remotes/git-svn) 
No changes between current HEAD and refs/remotes/git-svn 
Resetting to the latest refs/remotes/git-svn 
+0

re git svn rebase không bắt buộc trước khi "cam kết": bằng cách cam kết, nghĩa là git svn dcommit phải không? Riêng biệt, bạn có nghĩa là không có gì sẽ bị nhầm lẫn sau này nếu tôi đẩy các thay đổi từ git cục bộ sang svn từ xa bằng cách sử dụng git svn dcommit giả sử tôi chưa chạm vào bất kỳ tệp nào đã thay đổi trong svn kể từ lần git svn rebase cuối cùng của tôi? Tôi cũng nhầm lẫn về một số điều trong đoạn thứ hai của bạn. 1) Có bất kỳ điểm nào trong việc tái nhập khẩu không? 2) Bạn có nói rằng bạn đã phỏng đoán điều này từ nội dung của thông điệp cam kết không? – allyourcode

+0

3) Bạn có ý nghĩa gì bởi "git-svn có thể đặt lại thành nội dung tìm nạp-từ-svn"? Tôi nghĩ rằng git reset được sử dụng để loại bỏ những thay đổi từ khu vực dàn dựng; trong khi đó, bạn dường như đang nói rằng các thay đổi thiết lập lại mà sửa đổi các chi nhánh hiện tại trỏ đến. 4) Làm thế nào có thể thay đổi không được đẩy vào svn sau khi thực hiện git svn dcommit? Không lệnh đó đẩy tất cả các thay đổi từ repo git địa phương của tôi để repo svn từ xa ?? – allyourcode

+0

Tôi đã viết lại hầu hết câu trả lời của mình để bao gồm các ví dụ minh họa lý do tại sao tìm nạp + rebasing sau khi dcommit là rất quan trọng. Tôi hy vọng nó sẽ giải quyết các điểm 1 & 2. – MikeSep

Các vấn đề liên quan