Giải pháp đơn giản: Xóa chi nhánh 'công việc' sau khi hợp nhất
Câu trả lời ngắn: Bạn có thể sử dụng git theo cách bạn thích (xem bên dưới để biết quy trình làm việc đơn giản), bao gồm cả hợp nhất. Chỉ cần đảm bảo theo dõi từng ' công việc hợp nhất git ' với ' công việc git chi nhánh ' để xóa chi nhánh công việc tạm thời.
Giải thích cơ bản:
Vấn đề hợp nhất / dcommit là bất cứ khi nào bạn 'git svn dcommit' một nhánh, lịch sử hợp nhất của nhánh đó là 'phẳng': git quên về tất cả các hoạt động hợp nhất đã đi vào nhánh này: Chỉ nội dung tệp được giữ nguyên, nhưng thực tế là nội dung này (một phần) đến từ một chi nhánh cụ thể khác bị mất. Xem: Tại sao git svn dcommit mất lịch sử hợp nhất cam kết cho các chi nhánh địa phương?
(Lưu ý: git-svn không thể làm được gì nhiều: svn đơn giản là không hiểu sự hợp nhất git mạnh hơn nhiều. Vì vậy, trong kho svn, thông tin hợp nhất này không thể được trình bày theo bất kỳ cách nào.)
Nhưng đây là toàn bộ vấn đề. Nếu bạn xóa nhánh 'công việc' sau khi nó được sáp nhập vào 'nhánh chính' thì kho git của bạn sạch 100% và trông giống hệt như kho lưu trữ svn của bạn.
Quy trình làm việc của tôi:
Tất nhiên, lần đầu tiên tôi đã sao chép kho lưu trữ svn từ xa vào kho lưu trữ git cục bộ (việc này có thể mất một chút thời gian):
$> git svn clone <svn-repository-url> <local-directory>
Tất cả công việc sau đó xảy ra bên trong "thư mục cục bộ". Bất cứ khi nào tôi cần nhận cập nhật từ máy chủ (như 'svn update'), tôi sẽ:
$> git checkout master
$> git svn rebase
Tôi làm tất cả công việc phát triển của mình trong một 'công việc' riêng biệt được tạo ra như thế này:
$> git checkout -b work
Tất nhiên, bạn có thể tạo bao nhiêu nhánh cho công việc của mình theo ý muốn và hợp nhất và khởi động lại giữa chúng theo ý muốn (chỉ cần xóa chúng khi bạn hoàn thành chúng --- như được thảo luận dưới đây). Trong công việc bình thường của tôi, tôi cam kết rất thường xuyên:
$> git commit -am '-- finished a little piece of work'
Bước tiếp theo (git rebase -i) là tùy chọn --- nó chỉ làm sạch lịch sử trước khi lưu trữ nó trên svn: Khi tôi đạt được một viên đá ổn định mà tôi muốn chia sẻ với người khác, tôi viết lại lịch sử của 'tác phẩm' này phân nhánh và dọn sạch các thông điệp cam kết (các nhà phát triển khác không cần phải xem tất cả các bước nhỏ và lỗi mà tôi đã thực hiện trên đường --- chỉ là kết quả). Đối với điều này, tôi làm
$> git log
và sao chép hàm băm sha-1 của lần xác nhận cuối cùng tồn tại trong kho svn (như được chỉ định bởi git-svn-id). Sau đó tôi gọi
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
Chỉ cần dán băm sha-1 của cam kết svn cuối cùng của chúng tôi thay vì của tôi. Bạn có thể muốn đọc tài liệu với 'git help rebase' để biết chi tiết. Nói tóm lại: lệnh này trước tiên sẽ mở một trình soạn thảo trình bày các cam kết của bạn ---- chỉ cần thay đổi 'chọn' thành 'squash' cho tất cả các cam kết mà bạn muốn xóa sổ với các cam kết trước đó. Tất nhiên, dòng đầu tiên sẽ ở dạng 'chọn'. Bằng cách này, bạn có thể ngưng tụ nhiều cam kết nhỏ của mình thành một hoặc nhiều đơn vị có ý nghĩa. Lưu và thoát khỏi trình soạn thảo. Bạn sẽ nhận được một trình soạn thảo khác yêu cầu bạn viết lại các thông điệp nhật ký cam kết.
Tóm lại: Sau khi tôi hoàn thành 'hack mã', tôi xoa bóp nhánh 'công việc' của mình cho đến khi nó trông giống như cách tôi muốn trình bày nó với các lập trình viên khác (hoặc cách tôi muốn xem công việc trong vài tuần khi tôi duyệt lịch sử) .
Để đẩy các thay đổi vào kho svn, tôi làm:
$> git checkout master
$> git svn rebase
Bây giờ chúng tôi đã quay lại nhánh 'chủ' cũ được cập nhật với tất cả các thay đổi xảy ra trong thời gian trung bình trong kho svn (những thay đổi mới của bạn được ẩn trong nhánh 'công việc').
Nếu có những thay đổi có thể xung đột với những thay đổi 'công việc' mới của bạn, bạn phải giải quyết chúng cục bộ trước khi bạn có thể đẩy công việc mới của mình (xem chi tiết bên dưới). Sau đó, chúng tôi có thể đẩy các thay đổi của mình lên svn:
$> git checkout master
$> git merge work # (1) merge your 'work' into 'master'
$> git branch -d work # (2) remove the work branch immediately after merging
$> git svn dcommit # (3) push your changes to the svn repository
Lưu ý 1: Lệnh 'git Branch -d work' khá an toàn: Nó chỉ cho phép bạn xóa các nhánh mà bạn không cần nữa (vì chúng đã được sáp nhập vào nhánh hiện tại của bạn). Nếu bạn thực hiện lệnh này do nhầm lẫn trước khi hợp nhất công việc của bạn với nhánh 'chính', bạn sẽ nhận được thông báo lỗi.
Lưu ý 2: Đảm bảo xóa chi nhánh của bạn bằng 'git Branch -d work' giữa việc hợp nhất và dcommit: Nếu bạn cố xóa chi nhánh sau dcommit, bạn sẽ nhận được thông báo lỗi: Khi bạn thực hiện 'git svn dcommit', hãy quên đi chi nhánh của bạn đã được hợp nhất với 'chủ nhân'. Bạn phải xóa nó bằng 'git chi nhánh -D work' mà không thực hiện kiểm tra an toàn.
Bây giờ, tôi lập tức tạo một nhánh 'công việc' mới để tránh việc vô tình hack vào nhánh 'chủ':
$> git checkout -b work
$> git branch # show my branches:
master
* work
Tích hợp 'công việc' của bạn với các thay đổi trên svn:
Đây là những gì tôi làm khi 'git svn rebase' tiết lộ rằng những người khác đã thay đổi kho svn trong khi tôi đang làm việc trên nhánh 'công việc' của mình:
$> git checkout master
$> git svn rebase # 'svn pull' changes
$> git checkout work # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed
$> git checkout master # try again to push my changes
$> git svn rebase # hopefully no further changes to merge
$> git merge integration # (1) merge your work with theirs
$> git branch -d work # (2) remove branches that are merged
$> git branch -d integration # (2) remove branches that are merged
$> git svn dcommit # (3) push your changes to the svn repository
Có nhiều giải pháp mạnh mẽ hơn:
Quy trình công việc được trình bày rất đơn giản: Nó chỉ sử dụng sức mạnh của git trong mỗi vòng 'update / hack / dcommit' --- nhưng để lại lịch sử dự án dài hạn giống như kho lưu trữ svn. Điều này là ổn nếu bạn chỉ muốn bắt đầu sử dụng git sáp nhập trong các bước đầu tiên nhỏ trong một dự án svn kế thừa.
Khi bạn trở nên quen thuộc hơn với việc hợp nhất git, hãy thoải mái khám phá các quy trình công việc khác: Nếu bạn biết bạn đang làm gì, bạn có thể kết hợp git với sáp nhập svn ( Sử dụng git-svn (hoặc tương tự) chỉ để giúp hợp nhất với svn? )