/ git

Architecture and Design of Subversion - SVN (Part 2) (Vietnamese)

Chào chào mọi người,

Ở bài viết phần 1, chúng ta đã cùng nhau tìm hiểu sơ qua về SVN, cấu trúc cũng như một số khái niệm, cách hoạt động và tool sử dụng cho SVN.

Tiếp theo ở phần này, chúng ta sẽ đi sâu một chút về các vấn đề trong thiết kế SVN, cũng như một số khái niệm nâng cao trong việc sử dụng SVN.

Cuối cùng mình sẽ đưa ra 1 số mẹo sử dụng SVN mà mình tích cóp được trong quá trình phát triển phần mềm.

Trước tiên, để biết qua một số đặc tính của SVN, ta cùng ngó lại một hệ thống Version Control cũ hơn là CVS

CVS

CVS có kiến trúc client – server thông thường, trong đó server chạy Linux đóng vai trò lưu trữ dữ liệu của version control, các client sẽ kết nối tới server thông qua network, thực hiện các thao tác checkout, checkin hay update đối với dữ liệu mà CVS quản lý.

CVS hỗ trợ delta-compression cũng như phân branch cho project. Tuy nhiên, là 1 system tối cổ, CVS có 1 số nhược điểm như sau:

  • khi commit, revision được tăng lên theo từng file một
  • hỗ trợ Unicode hay các bảng mã khác rất chán
  • không tự động version các file bị rename hay move
  • commit không phải là 1 action atomic
  • các operation trên branch rất tốn tài nguyên
  • coi tất cả các file là text

Đồng thời có rất nhiều các feature mà các version contrl system sau này hỗ trợ nhưng CVS thì không, dẫn đến lần checkin code vào CVS cuối cùng đã xảy ra hơn 2 năm trước. Development coi như stop từ đó đến giờ.

SVN Features

Vậy so với CVS, SVN có rất nhiều tính năng mạnh mẽ như sau:

  • version cả folder (CVS chỉ version từng file)
  • lưu lại toàn bộ lịch sử của từng item được version
  • commit là 1 atomic operation – tức là nếu commit bị gián đoạn cũng không ảnh hưởng đến toàn vẹn dữ liệu trong SVN
  • hỗ trợ metadata cho từng item được version, metadata cũng được version tương tự item luôn
  • hỗ trợ SSH nhằm tăng tính bảo mật
  • xử lý toàn vẹn dữ liệu bằng thuật toán so sánh nhị phân hoạt động độc lập trên text cũng như binary, dữ liệu đồng thời được nén trên repository, dữ liệu gửi đi chỉ là sai khác về file, không phải toàn bộ file
  • xử lý hiệu quả branch và tag, không phụ thuộc vào kích thước project
  • code by C, đồng nghĩa với việc thư viện Subversion sở hữu APIs rất mạnh và hỗ trợ đa ngôn ngữ, đa nền tảng

SVN Package

SVN chứa các tool chính bao gồm:

  • svn: CLI của SVN
  • svnversion: report về info của working copy
  • svnlook: tìm kiếm và lọc thông tin trong reposirory
  • svnadmin: tạo và chỉnh sửa repository
  • svnserve: module cho Apache để khởi tạo SVN server

Versioning Solution

Khi thiết kế version control system, có 1 vấn đề cơ bản cần phải giải quyết: đó là hỗ trợ user có thể chia sẻ thông tin mà không khiến data của các user khác nhau bị overwrite lên nhau.
Tình huống này được mô tả như sau:

ch02dia2

  1. Đầu tiên, Harry và Sally cũng đọc thông tin file A từ repository
  2. Sau đó, họ cùng edit file này
  3. Harry xong trước, publish A’ lên repository
  4. Sally xong sau, publish A” lên repository

Kết quả: trên repository lưu A”, là bản chỉnh sửa A của Sally, và hoàn toàn mất dấu A’ của Harry. Vấn đề này có thể giải quyết bằng phương pháp Lock-Modify-Unlock.

ch02dia3

  1. Khi Harry đọc file, repository sẽ lock file A lại
  2. Sally đọc file và bị reject do Harry đã lấy quyền lock
  3. Harry sửa xong file A, write lên repository và release lock
  4. Lúc này, Sally có thể acquire lock, đọc file và sửa theo ý mình

Phương pháp này có nhược điểm rất lớn là:

  • Vấn đề xử lý quyền administrator: khi Harry lock file, không ai khác có thể access dẫn đến phí phạm thời gian
  • Các user không thể cùng edit một file dù họ sửa ở những phần hoàn toàn độc lập
  • Các file bị lock độc lập nếu phụ thuộc vào nhau sẽ gây mất toàn vẹn dữ liệu

Một phương pháp khác ra đời nhằm khắc phục các nhược điểm trên được gọi là Copy-Modify-Merge

ch02dia4

  1. Đầu tiên, Harry và Sally cùng read file A từ repository
  2. Họ đồng thời edit file này
  3. Sally xong trước, write bản A” lên repository
  4. Harry xong sau, write bản A’ lên repository và sẽ gặp lỗi out-of-date

ch02dia5

  1. Lúc này, Harry một lần nữa read file A từ repository
  2. Harry so sánh và gộp các thay đổi từ A” sang A’ của mình được A*
  3. Harry write A* lên repository
  4. Sally read A* từ repository
  5. Lúc này, Harry, Sally và repository đều chứa A* với các thay đổi từ cả Harry và Sally

Phương pháp này tồn tại 1 case mà việc merge gặp lỗi, đó là khi Harry và Sally cùng sửa 1 đoạn code hay 1 hàm mà không thể tự merge, case này được gọi là conflict. Các version control system hiện nay đều có khả năng auto-merge, tuy nhiên khi gặp conflict thì user sẽ buộc phải tự xem xét để resolve.

Revision

SVN track các item theo revision của từng file, và tồn tại 1 chỉ số revision chung cho toàn bộ working copy. Chỉ có các file được modify tại 1 lần commit mới mang revision của lần commit đó, các file không ảnh hưởng sẽ giữ revision gần nhất của nó. Working copy và repository sẽ mang revision của lần commit gần nhất. Do SVN lưu toàn bộ history nên với SVN, ta sẽ không bao giờ mất thông tin dù có delete file, rename hay làm gì item. Ta luôn có thể revert lại 1 revision nào đó để lấy lại nội dung của item tại revision đó, kể cả ở revision sau đó, item đó bị xóa hay rename. Khi sử dụng SVN với branch, tag, chúng ta sẽ gặp tình huống cần các action như merge, switch hay log, diff. Các action này khi nhảy vào project thật sẽ có ích hơn là lý thuyết.

Tips & Tricks

Trong quá trình làm việc với SVN, mình có 1 số kết luận rút ra cho bản thân như sau, mọi người có thể tham khảo:

  • khi tạo SVN directory structure, nên sử dụng cấu trúc branches/tags/trunk
  • khi SVN chứa nhiều project, nên apply cấu trúc trên cho từng directory riêng của từng project
  • không commit bất kì item gì chứa local properties, như các file settings hay các file chứa local path do Eclipse sinh ra, nên ignore các item này
  • không commit bất kì item gì được sinh ra từ quá trình build project, như các file object, dll, .class,… nên ignore các item này
  • không commit bất kì item gì có thể được tạo ra từ các item khác, ví dụ file cấu hình project cmake.in, nên tạo ra file cấu hình example.in.config và để user tự tạo ra file config của họ khi checkout SVN
  • thông thường, /bin, /gen, /obj là các directory nên được ignore ngay từ khi tạo SVN
  • việc create/merge branch/tag nên do 1 người trong team làm để đảm bảo tính thống nhất của SVN structure
  • khi làm việc với các project cá nhân, nhiều khi ta muốn sử dụng SVN để thuật tiện, ta có thể dùng các dịch vụ SVN free trên mạng, điển hình như Google Code, nhược điểm là project sẽ phải để open access, nếu muốn private có thể tham khảo Assembla

Okay, bài hôm nay đến đây là hết. Hẹn gặp lại các bạn trong các bài tiếp theo. Mình đang muốn làm 1 bài về Mercurial và Git cũng như hệ thống code review Gerrit nhưng thời gian khó khăn quá.

Chúc mọi người một ngày làm việc hiệu quả.