Sử dụng git trong thực tế
Tại sao lại là git?
Git mang lại cho chúng ta 1 cách tiếp cận mới, nó thay đổi cách nghĩ của người phát triển phần mềm về việc merging và branching. Với những công cụ truyền thống là CVS/Subversion thì nguời phát triển luôn luôn lo lắng, e ngại mỗi lúc mergeing/branching với những confict tiềm tàng ẩn chứa rủi ro.Nhưng đối với git, việc đó trở nên dễ dàng và an toàn hơn bao giờ hết, việc mergeing và branching đã trở thành những công việc thường ngày mà chúng ta làm trong quá trình phát triển. Trong những ebook hướng dẫn sử dụng với CVS/Subversion thì hướng dẫn branching và merging thường được đề cập ở những chap cuối của sách (phần nâng cao) dành cho những người đã thông thạo, còn với git thì nó lại thuộc phần basic (cơ bản), điều này dễ dàng cho ta thấy việc sử dụng git để merging và branching dễ dàng và an toàn hơn so với các phương thức cổ điển.
Những cải tiến suất sắc trong merging và branching của git so với những công cụ truyền thống đã giúp cho việc quản lý version của source code trở nên đơn giản và nhẹ nhàng hơn rất nhiều, vì vậy mà các nhà phát triển dần dần đã chuyển sang sử dụng git để thay thế các phương pháp truyền thống.
Vậy sử dụng git trong thực tế như thế nào, tổ chức và quản lý các branch, tiến hành mergeing như thế nào là đúng đắn??? Sau đây sẽ là hướng dẫn cụ thể việc sử dụng git trong phát triển phần mềm thực tế, sẽ giúp các bạn nắm rõ hơn cách tổ chức 1 bộ source bằng git trong quá trình phát triển.
Decentralized but centralized (phân tán nhưng tập trung)
Với 1 source được quản lý bởi git, luôn chỉ có duy nhất 1 "central truth repo" (1 repo gốc, sẽ được sử dụng để deploy trong quá trình release hệ thống thật) gọi là "origin" (remote origin) → thuật ngữ rất phổ biến với git users.
Mỗi developer sẽ push và pull lên remote origin → centralized, tuy nhiên ta vẫn có thể tổ chức những nhóm riêng (sub team) sử dụng remote riêng để phục vụ cho quá trình phát triển.
Ví dụ giống như hình trên, mỗi khi phát triển 1 feature lớn, cần có 1 team gồm nhiều thành viên để phát triển thì ta sẽ tiến hành tổ chức các remote khác nhau để hỗ trợ. Các developer sẽ push lên các remote của sub team trước khi push lên remote origin, trong hình trên ta thấy được subteam được tổ chức giữa Alice và Bob, Alice và David, Clair và David. => Alice đơn giản chỉ là khai báo 1 remote, ví dụ tên bob, trỏ vào local repo của Bob.
The main branches (Những branch chính)
Main banrches là những branch sẽ tồn tại mãi mãi, gồm có 2 branch sau: master develop 2 branch này được phát triển vả tồn tại song song với nhau. Và chú ý là source code HEAD của branch origin/master chính là phiên bản sẵn sàng để phát hành ra thực tế. Còn đối với origin/develop là branch mà source code HEAD của nó là phiên bản phát hành cuối cùng để sẵn sàng cho lần release tiếp theo. Ngoài ra nó còn được gọi là "integration branch".
Khi source code trong branch develop đã đạt được mục tiêu của lần release tiếp theo thì code của nó sẽ được merge trở lại vào master, được tag với 1 dãy số release (release version, ví dụ v1.0.1). Về release version ta sẽ đề cập ở phần cuối của bài này.
Mỗi lần ta merge vào master có nghĩa là có 1 sản phẩm mới, 1 phiên bản mới sẽ được phát hành, và sẽ phải rất cẩn thận rong quá trình release này, ta có thể sử dụng 1 đoạn git hook script để tự động build và roll-out source code thành phiên bản thực tế mỗi lần ta commit lên master.
Supporting branches (những branch hỗ trợ)
Sau main branch, developer còn sử dụng rất nhiều những supporting branches để tiến hành phát triển song song giữa các thành viên trong team, dễ dàng theo dõi các features, chuẩn bị cho quá trính release cũng nhưng để fix những bug của sản phẩm. Không giống như main branch, những suporting branch luôn có thời gian tồn tại nhất định. Supporting branches gồm những loại sau:
- Feature branches
- Release branches
- Hotfix branches
Hệ thống branch
Feature branches
- branch off từ: develop
- merge vào: develop
- Quy luật đặt tên: bất kể gì trừ master, develop, release-, hay hotfix-
Tạo feature branch:
$ git checkout -b myfeature develop
Switched to a new branch "myfeature"
Kết thúc phát triển sẽ được merge lại vào develop và sẽ được add thêm trong lần release tiếp theo:$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop
–no-ff flag có nghĩa là việc merge sẽ luôn
luôn tạo ra 1 đối thượng commit, kể cả nếu việc merge có thể được thực
thi với fast-forward. Nó chống lại việc mất thông tin về quá trình phát
triển của feature và nhóm lại với nhau, hình sau sẽ giúp ta dễ hình dung
hơn:Với việc sử dụng flag
–no-ff thì những log về commit
trong branch cũ vẫn được lưu giữ lại việc này giúp cho chùng ta lần lại
được log của tất cả những commit trong quá khứ, xem được những thay đổi
trong mỗi lần commit đấy. Sử dụng flag này tránh được rắc rối khi chúng
ta kiểm tra lại sự thay đổi của project trong quá trình phát triển, khi
mà lúc merge xong thì mọi commit trong branch cũ được kết hợp lại làm
một.Tuy nhiên chưa có cách config nào để biến flag này thành mặc định, nhưng nó sẽ có khả năng có trong tương lai.
Release branches
- Được branch off từ:develop
- Được merge vào develop và master.
- Quy tắc đặt tên: release-*
Khi tạo branch release từ develop thì branch develop lúc đó phải thể hiện rõ (mang đủ những tính năng) của product trong lần release mới này. Tối thiểu tất cả những features của lần release mới này phải được merge vào develop rồi.
Chính xác thì khi strat 1 release branch thì nó sẽ được gán 1 version mới (sự thay đổi version release, ko phải fix bug, → sẽ nói kỹ càng hơn ở phần cuối của mục "sử dụng trong thực tế"). Nó được gọi là "project’s rules on version number va chạm" → quy tắc đặt tên version.
Tạo release branch: được tạo từ branch develop. Ví dụ phiên bản hiện tại của product là 1.1.5 và chúng ta đang tiến hành release 1 phiên bản mới. Lúc này phiên bản release mới sẽ là 1.2.0 thay vì 1.1.6 hay 2.0. Ví dụ:
$ git checkout -b release-1.2 develop
→ tạo mới và chuyển sang "release-1.2"
$ ./bump-version.sh 1.2
→ bump (nâng version) new version (config thông tin của product thành version mới)
$ git commit -a -m "Bumped version number to 1.2"
→commit state mới
Sau khi tạo mới release branch và chuyển qua nó, chúng
ta tiến hành bump số version của product. bump-version.sh là 1 đoạn
shell script mà nó sẽ thay đổi nội dung 1 số file để khớp với số version
release mới. Rồi bumped số version mới được commit lên.Có thể tồn tại những branch khác trong quá trình branch release được tiến hành, cho đến khi sự release co thể bị xoay ngược lại. Trong khoảng thời gian này, việc fix bug có thể được apply vào branch này (nhanh hơn so với develop). Việc thêm những tính năng lớn ở giai đoạn này bị cấm tuyệt đối. Chúng sẽ được merge vào develop và chờ cho tới lần release tiếp theo.
Hoàn thành release branch Khi trạng thái của branch release đã sẵn sàng để thành 1 release thực sự, cần phải cẩn thận một số hành động tại thời điểm này. Đầu tiên, branch release phải được merge vào master (nhớ là khi mọi commit trên master là đã được quy định). Tiếp theo, những commit trên master phải được tag để trong tương lai ta có thể ánh xạ lại được những version cũ của product trong quá khứ. Và cuối cùng là những thay đổi trên release branch phải được merge ngược trở lại vào develop để đảm bảo tương thích (những bug đã được fix hay những tính năng nhỏ khác được tiến hành trên branch release) cho lần release tiếp theo.
2 bước đầu tiên trên git
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
$ git tag -a 1.2
Relese done, và được tag cho lần release này.
Và như nói ở trên, ta phải merge ngược lại vào develop. In Git:$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
Bước này có thể bị confict, ta phải fix chúng rồi commit lên develop.
Tiếp theo chúng ta xoá release branch đi nếu như chúng ta không còn dùng đến nó nữa:$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).
Hotfix Branches
- Branch off from: master
- được merge vào: develop and master
- Quy tắc đặt tên: hotfix-*
Lúc này thì công việc của team vẫn được tiến hành bình thường trên branch develop, sẽ có 1 vài người được chỉ định để fix bug nhanh chóng trên product.
Branch hotfix được tạo từ master. Ví dụ 1.2 là phiên bản hiện tại của product trong thực tế và xuất hiện 1 bug nghiêm trọng cần thiết phải sửa chữa ngay lập tức thì công việc sẽ được hình dung cụ thể như sau:
$ git checkout -b hotfix-1.2.1 master
Tạo mới và chuyển sang branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)
Đừng bao giờ quên bump the version number sau khi branching off!
Và tiếp theo, tiến hành sửa lỗi và commit lên$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)
Finishing a hotfix branch
Khi kết thúc sửa lỗi, branch hotfix cần phải merge ngược lại vào cả master và develop.Đầu tiên, update master và tag phiên bản release.
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2.1
Và merge vào develop$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
Có một ngoại lệ đặc biệt ở đây là khi mà branch release
đang tồn tại thì branch hotfix sẽ được merge vào branch release thay vì
develop. Vì sau này khi merge branch release và branch develop thì những
gì của branch hotfix vẫn sẽ được ốp vào develop.Bước cuối cùng là xoá branch hotfix:
$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).
Release number- Phase Number: phụ thuộc kế hoạch phát triển của product (phase number là level lớn nhất)
- Release Number: sau phase number là release number, trong mỗi phase sẽ được chia ra từng giai đoạn release, chính là những quá trình thêm các tính năng lớn vào product. Tương ứng với branch release.
- Fixbug number: mỗi lần fix bug trên master thì lại tăng số này lên.
git merge --no-ff myfeature
ReplyDelete–no-ff flag có nghĩa là việc merge sẽ luôn luôn tạo ra 1 đối thượng commit, kể cả nếu việc merge có thể được thực thi với fast-forward. Nó chống lại việc mất thông tin về quá trình phát triển của feature và nhóm lại với nhau