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 có để 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.txt
và bar.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.txt
và git 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
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
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
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