May mắn thay cho những người trong chúng ta vẫn buộc phải sử dụng CVS, git cung cấp các công cụ khá tốt để thực hiện chính xác những gì bạn muốn làm. Đề xuất của tôi (và những gì chúng tôi làm ở đây tại $ work):
Tạo bản sao ban đầu
Sử dụng git cvsimport
để sao chép lịch sử sửa đổi CVS vào kho lưu trữ git. Tôi sử dụng lời kêu gọi sau:
% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
-A /path/to/authors/file cvs_module_to_checkout
Các -A
tùy chọn không bắt buộc nhưng nó giúp để làm nên lịch sử sửa đổi của bạn mà của nhập khẩu từ CVS trông git-like (xem man git-cvsimport
để biết thêm về cách thức này được thiết lập).
Tùy thuộc vào kích thước và lịch sử của kho CVS, lần nhập đầu tiên này sẽ mất rất nhiều thời gian. Bạn có thể thêm -v vào lệnh trên nếu bạn muốn yên tâm rằng thực tế có điều gì đó đang xảy ra.
Khi quá trình này hoàn tất, bạn sẽ có một master
nhánh phản ánh HEAD của CVS (ngoại trừ việc git cvsimport
theo mặc định bỏ qua các cam kết có giá trị 10 phút cuối để tránh bắt một cam kết đã hoàn thành một nửa). Sau đó git log
, bạn có thể sử dụng và bạn bè để kiểm tra toàn bộ lịch sử của kho lưu trữ giống như thể nó đã sử dụng git ngay từ đầu.
Chỉnh sửa cấu hình
Có một số điều chỉnh cấu hình sẽ giúp nhập khẩu gia tăng từ CVS (cũng như xuất khẩu) dễ dàng hơn trong tương lai. Những điều này không được ghi lại trên git cvsimport
trang người đàn ông nên tôi cho rằng chúng có thể thay đổi mà không cần thông báo trước nhưng, FWIW:
% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT
Tất cả các tùy chọn này có thể được chỉ định trên dòng lệnh nên bạn có thể bỏ qua bước này một cách an toàn.
Nhập khẩu gia tăng
Tiếp theo git cvsimport
sẽ nhanh hơn nhiều so với lời kêu gọi đầu tiên. Tuy nhiên, nó thực hiện cvs rlog
trên mọi thư mục (ngay cả những thư mục chỉ có tệp trong đó Attic
) nên vẫn có thể mất vài phút. Nếu bạn đã chỉ định cấu hình được đề xuất ở trên, tất cả những gì bạn cần làm là thực thi:
% git cvsimport
Nếu bạn chưa thiết lập cấu hình của mình để chỉ định các giá trị mặc định, bạn sẽ cần chỉ định chúng trên dòng lệnh:
% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout
Dù bằng cách nào, hai điều cần ghi nhớ:
- Đảm bảo rằng bạn đang ở trong thư mục gốc của kho lưu trữ git của mình. Nếu bạn ở bất kỳ nơi nào khác, nó sẽ cố gắng làm mới
cvsimport
một lần nữa sẽ mất mãi mãi.
- Đảm bảo rằng bạn đang ở
master
chi nhánh của mình để các thay đổi có thể được hợp nhất (hoặc khôi phục) vào các chi nhánh địa phương / chủ đề của bạn.
Thực hiện các thay đổi cục bộ
Trên thực tế, tôi khuyên bạn nên luôn thực hiện các thay đổi trên các nhánh và chỉ hợp nhất master
khi bạn đã sẵn sàng xuất những thay đổi đó trở lại kho CVS. Bạn có thể sử dụng bất kỳ quy trình làm việc nào bạn thích trên các chi nhánh của mình (hợp nhất, khôi phục, thu nhỏ, v.v.) nhưng tất nhiên các quy tắc khôi phục tiêu chuẩn sẽ được áp dụng: không rebase nếu bất kỳ ai khác đang căn cứ vào các thay đổi của họ trên chi nhánh của bạn.
Xuất các thay đổi sang CVS
Các git cvsexportcommit
lệnh cho phép bạn xuất khẩu một cam kết duy nhất ra đến máy chủ CVS. Bạn có thể chỉ định một ID cam kết duy nhất (hoặc bất kỳ thứ gì mô tả một cam kết cụ thể như được định nghĩa trong man git-rev-parse
). Sau đó, một điểm khác biệt được tạo, áp dụng cho kiểm tra CVS và sau đó (tùy chọn) cam kết với CVS bằng cách sử dụng cvs
khách hàng thực tế . Bạn có thể xuất từng cam kết vi mô trên các nhánh chủ đề của mình nhưng nói chung, tôi muốn tạo một cam kết hợp nhất cập nhật master
và xuất cam kết hợp nhất duy nhất đó sang CVS. Khi bạn xuất một cam kết hợp nhất, bạn phải cho git biết cha mẹ cam kết nào sử dụng để tạo ra sự khác biệt. Ngoài ra, điều này sẽ không hoạt động nếu hợp nhất của bạn là một tua đi nhanh (xem phần "CÁCH LÀM VIỆC CỦA MERGE" man git-merge
để biết mô tả về hợp nhất tua đi nhanh) vì vậy bạn phải sử dụng--no-ff
khi thực hiện hợp nhất. Đây là một ví dụ:
# on master
% git merge --no-ff --log -m "Optional commit message here" topic/branch/name
% git cvsexportcommit -w /path/to/cvs/checkout -u -p -c ORIG_HEAD HEAD
Bạn có thể xem mỗi tùy chọn đó có ý nghĩa gì trên trang man cho git-cvsexportcommit . Bạn có tùy chọn thiết lập -w
tùy chọn trong cấu hình git của mình:
% git config cvsexportcommit.cvsdir /path/to/cvs/checkout
Nếu bản vá không thành công vì bất kỳ lý do gì, kinh nghiệm của tôi là bạn (không may) có lẽ tốt hơn nên sao chép các tệp đã thay đổi theo cách thủ công và cam kết sử dụng ứng dụng khách cvs. Tuy nhiên, điều này sẽ không xảy ra, nếu bạn đảm bảo rằng master
CVS được cập nhật trước khi hợp nhất nhánh chủ đề của bạn vào.
Nếu cam kết không thành công vì bất kỳ lý do gì (sự cố mạng / quyền, v.v.), bạn có thể lấy lệnh được in ra thiết bị đầu cuối của mình ở cuối đầu ra lỗi và thực thi nó trong thư mục làm việc CVS của bạn. Nó thường trông giống như sau:
% cvs commit -F .msg file1 file2 file3 etc
Lần tiếp theo bạn thực hiện git cvsimport
(đợi ít nhất 10 phút), bạn sẽ thấy bản vá của cam kết đã xuất của bạn được nhập lại vào kho lưu trữ cục bộ của bạn. Chúng sẽ có các ID cam kết khác nhau vì CVS cam kết sẽ có một dấu thời gian khác và có thể là một tên người cam kết khác (tùy thuộc vào việc bạn có thiết lập tệp tác giả ở phần đầu của bạn cvsimport
ở trên hay không).
Nhân bản bản sao CVS của bạn
Nếu bạn có nhiều người cần thực hiện cvsimport
, sẽ hiệu quả hơn nếu có một kho lưu trữ git duy nhất thực hiện cvsimport và có tất cả các kho lưu trữ khác được tạo dưới dạng bản sao. Điều này hoạt động hoàn hảo và kho lưu trữ nhân bản có thể thực hiện cvsexportcommits giống như mô tả ở trên. Tuy nhiên, có một cảnh báo. Do cách CVS cam kết quay trở lại với các ID cam kết khác nhau (như đã mô tả ở trên), bạn không muốn nhánh nhân bản của mình theo dõi kho lưu trữ git trung tâm. Theo mặc định, đây là cách git clone
định cấu hình kho lưu trữ của bạn nhưng điều này có thể dễ dàng khắc phục:
% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge
Sau khi bạn đã xóa các cấu hình này, bạn sẽ phải nói rõ ràng sẽ lấy từ đâu và lấy gì khi bạn muốn lấy các cam kết mới từ kho lưu trữ trung tâm:
% git pull origin master
Nhìn chung, tôi thấy luồng công việc này khá dễ quản lý và "điều tốt nhất tiếp theo" khi chuyển hoàn toàn sang git là không thực tế.