Sử dụng git hiệu quả trong một dự án phần mềm, dự án Drupal

Bài viết này được lấy từ http://www.expressmagazine.net, cảm ơn tác giả đã có bài viết rất hay. Mình xin copy về blog để chia sẻ cho các bạn.

Trong bài viết này mình sẽ nói về cách sử dụng git của mình trong thời gian qua. Cách mà mình tổ chức git branching cho hầu hết các Project của mình. Dĩ nhiên nó không phải là cách mà mình nghĩ ra. Đó chỉ là cách mà mình đọc được và được phần mềm quản lý SmartGit hổ trợ. Thấy nó rất hữu hiệu nên mình chia sẽ nó lên đây.

Awesome Git Branching Model

Awesome Git Branching Model

Why Git?

Mình đã từng sử dụng qua một vài hệ thống quản lý source như SVN hay Hg. Thì mình vẫn thích dùng Git hơn. Nó có rất nhiều điểm hay như phân tán, không cần kết nối với Central Repository khi commit…
Git đã thay đổi cách nghĩ của lập trình viên về merging và branching. Nó làm cho những công việc đó nhẹ nhàng, dễ chịu và đơn giản hơn rất nhiều. Trong các sách về SVN/CVS, thường thì merging và branching sẽ được giới thiệu vào các chương cuối. Tức là dành cho cho những người dùng nâng cao. Riêng với Git thì nó được giới thiệu vào khá sớm, vì đó chính là điểm mạnh của Git. Các bạn sẽ không sợ những công việc dễ gây conflict này nữa. Nó được giới thiệu ở Chương 3 của cuốn Pro Git
Các bạn có thể tham khảo thêm những điểm mạnh và yếu của Git tại hai địa chỉ dưới:

http://git-scm.com/about
https://git.wiki.kernel.org/index.php/GitSvnComparsion

Bây giờ chúng ta sẽ đi qua phần tiếp theo của câu chuyện, giới thiệu về Git Developing Model mà mình thường hay sử dụng. Mình nghĩ nó là cách thú vị và hay để mọi team có thể áp dụng để quản lý quá trình phát triển phần mềm của team mình.

Decentralized but centralized

Khi các bạn làm việc với git, thường thì các bạn sẽ làm việc với một Git Server nhưGitHubBitbucketGoogle Code hay tự setup một Git server (Công ty mình sử dụngGitlab). Về bản chất của Git. Đây không được xem là một server, vì nó ngang cấp vớilocal repository trên máy tính của bạn. Mình thì thích dùng cụm từ Central Truth Repository hơn. từ central ở đây là một ý niệm ngầm định vì Git là hệ thống quản lý phân tán. Và đây cũng là Git Repo chứa branch origin. Một cái tên quen thuộc mọi người dùng Git.

Sử dụng git hiệu quả trong một dự án phần mềm, dự án Drupal

Mô hình Central Truth Repository

Mọi lập trình viên đều pull và push lên origin. Nhưng bên cạnh việc những lập trình viên trong cùng 1 team có thể pull những thay đổi với nhau trong cùng một subteam. Điều này khá hữu ích cho những team làm việc với nhau để cùng phát triển một vài tính năng lớn, và trước khi push bản code hoàn chỉnh lên server, họ có thể làm việc chung với nhau mà không cần đến central repository. Việc này rất đơn giản là bạn chỉ cần add remote trỏ đến những repository của đồng nghiệp.

The main branches

Mình đã từng làm trong một project mà chỉ sử dụng một branch duy nhất là master. Điều này là không sai nhưng nó gây ra khá nhiều phiền toái. Và hệ thống CI rất hay báo build failed.
Central Repo chỉ cần chứa 2 branch duy nhất trong suốt quá trình phát triển dự án là

  • master
  • develop

Master branch thì dĩ nhiên quen thuộc với những Git user rồi. Nó là branch chứa code stable. Source code ở HEAD commit luôn ở trạng thái production-ready.
Develop branch là branch chứa code ở trạng thái sẳn sàng cho bản phát hành tiếp theo. Nó thường hay được gọi là “integration branch”. Các Nightly Build (Daily Build) thường được build từ branch này.

Một khi source code ở develop branch đạt đến trạng thái stable (Ít nhất là vượt qua được các Unit test case) thì mọi thay đổi trên develop branch sẽ được merge vào master branch và tagged với một release number.

Bằng cách kết hợp với các hệ thống CI hoặc git hook. Bạn hoàn toàn có thể tự động hóa mọi công việc build và release. Ví dụ sau (Mình viết bằng mã giả)

Nếu (master in orgin nhận được push)
  Hệ thống sẽ chạy test
  Nếu test result  = OK
    Build
    Nếu build OK
      Đẩy lên các CDN và sẳn sàng cho việc phát hành
    Nếu Build = False
      Email cho người quản trị
  Nếu Test result = False
    Rollback code ở master branch trên origin
    Thông báo cho người quản trị
  End
End

Tương tự với Develop branch. Mỗi bản build thành công sẽ được đẩy lên server chứaNightly Build

Supporting branches

bm002Bên cạnh sử dụng hai branch chính là master và develop thì nên có thêm những supporting branch chạy song song với 2 branch chính trong quá trình phát triển phần mềm. Mục đích của việc này nhằm giúp các developer team dễ dàng quản lý các tính năng, dễ dàng chuẩn bị cho các bản phát hành hoặc có thể nhanh chóng fix hệ thống nếu có những lỗi trong quá trình phát triển.

Không giống như 2 branch master và develop. Các branch này không chạy xuyên suốt dự án. Mà nó sẽ được mở và đóng khi cần thiết.
Có ba nhóm branchs mà các bạn nên sử dụng bao gồm

  • Feature branches
  • Release branches
  • Hotfix branches

Mỗi nhóm, theo như tên gọi của nó sẽ có những chức năng khác nhau tùy theo quy định của team mà sẽ được mở, đóng và merage vào những thời điểm thích hợp.
Về bản chất thì các branch này cũng là các branch Git đơn thuần, nhưng tùy vào mục đích sử dụng mà nó được đặt tên như vậy.

Feature branches

Thường được tách branch từ branch chính là developVà khi hoàn thành thì nên merge nó vào develop
Cách đặt tên: mọi cái tên ngoại trừ master, develop, release-*, or hotfix-*
Nên đặt là: feature-*

Feature branch thường được dùng cho quá trình phát triển một tính năng, chức năng của phần mềm. Nó thường được mở cho một hoặc một nhóm lập trình viên cùng nhau phát triển một tính năng mới.
Mục tiêu của branch này là sống trong quá trình phát triển feature đó để rồi cuối cùng sẽ được merge vào develop branch nếu tình năng đó hoàn thành hoặc sẽ bị hủy bỏ nếu tính năng đó quá tệ.
Một feature branch sẽ được đóng và merge vào develop branch. Không được merge vào master branch

Tạo ra một feature branch

Khi tạo ra một branch. Nó sẽ được tách brach từ develop branch

$ git checkout -b myfeature develop
Switched to a new branch “my feature”

Hoàn thành một feature branch trong quá trình development

Khi một feature hoàn thành, nó sẽ được merge vào develop branch để sẳn sàng cho quá trình phát hành ở phiên bản 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

Khi sử dụng cờ —no-ff thì git sẽ tạo ra một Merge commit point. Còn nếu không thì nó sẽ tạo ra một fast-forward. Sử dụng merge commit sẽ tốt hơn là fast-foward vì nó sẽ giúp bạn không bị mất dấu các commit của một feature branch, và theo dõi được quá trình phát triển của một feature branch hoặc nhầm lẫn các commit có trên develop branch. Giúp các thành viên trong team dễ dàng làm việc với nhau hơn.

merge-without-ff

Sau này, khi bạn cần review lại quá trình commit của dự án, bạn sẽ thấy được lịch sử các commit rất dễ dàng, thấy được những gì mình đã làm hơn là việc phải đi lần lại các commit, xem lại các commit mesgage. Giúp cho nhóm trưởng và các lập trình viên không bị đau đầu khi cần rollback hay reset code. Rất đơn giản, chỉ cần sử dụng cờ —no-ff. Dù nó có thể tạo ra một vài empty commit. Nhưng bạn sẽ nhận lại được nhiều lợi ích hơn là fast-foward commit.

Release branches

May branch off from: develop
Must merge back into: develop and master
Branch naming convention: release-*

Release branches giúp cho quá trình chuẩn bị để phát hành một phiên bản mới dễ dàng hơn. Nó cho phép bạn sửa các lỗi nhỏ của phần mềm, thay đổi các version number, build date hay các config nhỏ của ứng dụng cho lần phát triển tới. Việc này làm cho develop branch trông sạch sẽ, gọn gàng và bạn sẽ dễ dàng hiểu những gì mà team mình đã làm.

Tại sao release branch được tách ra từ develop branch và merge vào master hay develop.
Mục tiêu của việc này giúp cho hai công việc và phát triển chức năng và chuẩn bị release có thể được thực hiện bởi hai lập trình viên khác nhau và song song với nhau. Bạn có thể chuẩn bị để release và chờ cho các features khác hoàn thiện. Hoặc là team của bạn đã chuẩn bị xong cho quá trình release rồi nhưng vẫn chưa đến thời gian phát hành thì có thể merge vào develop branch và chờ đến thời điểm thích hợp thì có thể merge vào master branch.

Creating a release branch

Tương tự như việc mở ra một feature branch. Khi mà một phiên bản ở develop branch đã đạt đến trạng thái sẵn sàng phát hành bạn có thể tách ra một release branch để chuẩn bị cho quá trình phát hành.

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

Theo ví dụ trên, bằng cách tạo ra một release branch và chạy script cho quá trình chuẩn bị.

Sự tồn tại của một releash branch thường rất ngắn. và nó sẽ được đóng khi phiên bản đó được phát hành ra. Trong quá trình nó tồn tại. Bạn có thể fix bug ở trên branch này, nhưng không được thêm các chức năng lớn trên branch này.

Finishing a release branch

Khi một release branch sẵn sàng. Nó cần được merge vào master để phát hành. Và bạn cần nhớ là mọi commit trên master branch nên là những bản phát hành. Nó sẽ làm bạn dễ dàng theo dõi quá trình phát triển hơn. Cuối cùng mọi thay đổi trên release branch và master branch cần được merage vào develop branch để đồng bộ code cho pharse kế tiếp.

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2

Nên tagging cho code để dễ tracking quá trình phát triển.

Sau đó thì các bạn merge vào develop

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

Nếu có conflic thì các bạn có thể fix rồi commit.
Và cuối cùng là xóa releash branch đi.

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

Hotfix branches

hotfix-branches1

May branch off from: master
Must merge back into: develop and master
Branch naming convention: hotfix-*

Hotfix rất giống với release branches. vì nó đều nằm trong quá trình chuẩn bị phát hành nhưng để sửa những lỗi không nằm trong kế hoạch. Khi một lỗi của ứng dụng được phát hiện và cần phải sửa ngay, Hotfix sẽ giúp điểu này dễ dàng hơn. Một hotfix branch sẽ được tách ra từ một commit mang version tag trên master branch. Hotfix củng giúp cho việc tương tác công việc giữa các thành viên trong team dễ dàng hơn vì lúc đó một developer sẽ thực hiện công việc fix bug trên hotfix branch trong khi mọi thành viên khác trong team thì phát triển các tính năng cho bản kế tiếp ở develop branch.

Creating the hotfix branch

Hotfix branch được tạo ra từ master branch, ví dụ như bản 1.2 đang là phiên bản hiện tại, và phát hiện ra có một vào bug. Trong lúc đó bản trên develop branch vẫn chưa hoàn thành. Thì chúng ta có thể tách một hotfix branch và bắt đầu quá trình sửa lỗi.

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, 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 quên thay đổi version number
Sau đó commit các thay đổi

$ 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 hoàn thành những sửa lỗi cần thiết. Hotfix branch cần được merge vào master, và cũng cần được merge vào develop branch để đảm bảo rằng những bugfix này cũng sẽ có trong bản phát hành kế tiếp.

$ 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

Sau đó

$ 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 trường hợp ngoại lệ cho quá trình này là nếu như khi hoàn thành một bugfix release và đang tồn tại một release branch thì hotfix release cần được merge vào release branch. Vì release branch cũng sẽ được merge vào master và develop.
Cuối dùng là xóa hotfix branch đó đi:

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).

Tổng kết

Có lẽ qua bài viết này các bạn sẽ nhận thấy rằng việc sử dụng một công cụ hiệu quả như Git theo một cách hiệu quả hơn sẽ mang lại năng suất cho công việc. Mình biết một tool hổ trợ rất tốt developing model này là SmartGit. Sẽ giới thiệu nó kỹ hơn ở một bài viết khác.

Bài viết được tham khảo từ: http://nvie.com/posts/a-successful-git-branching-model/
Bài viết giới thiệu Git-Flow trên SmartGit: http://www.syntevo.com/smartgithg/whatsnew

{ 1 comment… add one }

Leave a Comment

Next post:

Previous post: