12/08/2018, 13:01

Một số thủ thuật nhỏ làm việc với GIT

Là một developer mới được tiếp xúc với GIT chưa lâu, mình thấy rõ được sự "kỳ diệu" của công cụ quản lý code này. GIT kỳ diệu như thế nào thì còn phải phân tích nhiều; nhưng ít ra, bạn có thể thoải mái code mà không lo ngại sẽ lỡ tay làm hỏng, hay là phá cả hủy hệ thống... =)). Tìm hiểu chi ...

git_logo.png

Là một developer mới được tiếp xúc với GIT chưa lâu, mình thấy rõ được sự "kỳ diệu" của công cụ quản lý code này. GIT kỳ diệu như thế nào thì còn phải phân tích nhiều; nhưng ít ra, bạn có thể thoải mái code mà không lo ngại sẽ lỡ tay làm hỏng, hay là phá cả hủy hệ thống... =)). Tìm hiểu chi tiết ở đây

Một khái niệm cực kỳ quan trọng trong GIT đó là commit. Làm việc với GIT thì chắc là sẽ rất hay gặp. Bạn có thể đọc thêm ở bài viết này hoặc là chịu khó google search nhé

Bài viết này, mình xin chia sẻ một số thủ thuật nhỏ mà mình đã sử dụng trong dự án gần đây để thao tác với commit. Tất nhiên, nó sẽ không hoàn toàn phù hợp cho tất cả các trường hợp và cũng có thể không phải là cách tối ưu nhất, nhưng bạn có thể áp dụng cho một số trường hợp cụ thể

Thủ thuật được đề cập ở đây là cherry-pick với commit

Cherry-pick

1. Đặt vấn đề

Giả sử bạn phải làm việc trên nhánh base là master có 2 file với nội dung như sau

  • ####File file1.txt origin content of file1
  • ####File file2.txt origin content of file2

Mỗi khi tiến hành code một task mới (code trên file file2.txt) thì bạn cần phải thêm một đoạn code sau vào cuối file file1.txt. Nó là điều kiện để bạn có thể chạy được ứng dụng ở trên local

Tuy nhiên khi bạn đã code xong cho task, trước khi push code lên để tạo pull request thì bạn phải bỏ phần code điều kiện này đi, và chỉ để lại phần code cho task của bạn ở file file2.txt

Nếu chỉ như trên thì không có gì phải bàn luận, trường hợp mình muốn nói tới ở đây là, có nhiều task cùng cần một cái điều kiện như vậy (ở đây là đoạn code trong file file1.txt mình nhắc đến ở trên) thì sẽ giải quyết như thế nào?

Bạn có thể cứ mỗi khi tạo nhánh làm task mới thì bạn sẽ thêm điều kiện này vào một cách thủ công. Nhưng như thế thì rất bị động, và với phần điều kiện có nhiểu thay đổi thì rất bất tiện khi làm việc

Dưới đây là 2 cách thao tác với GIT có thể dùng để giải quyết được việc này

2. Giải quyết

C1. Cách cổ điển - rebase

Trước tiên, từ master, bạn tạo một nhánh mới để chứa phần code điều kiện. Ở đây mình tạo nhánh pre-run

Tiến hành code cho phần điều kiện ở trên nhánh pre-run. Giả sử sau khi thay đổi thì 2 file trên sẽ như sau

origin content of file1
content of prepare to run # new line

=====================================

origin content of file2

commit để tổ chức phần code điều kiện này như bình thường. Khi đó, kiểm tra log ở nhánh này ta có như bên dưới

$ git log --oneline
eead22b prepare to run
2879ed2 Improve the README and create test_file
fb4a53b init repo

Tiếp đó, từ pre-run, tạo mới nhánh branch-1 và tiến hành code cho task của mình. 2 file đó sẽ thành

origin content of file1
content of prepare to run # new line

=====================================

origin content of file2
content of branch-1 # new line

Ta cũng commit cho phần này và kiểm tra lại log

$ git log --oneline
af8507b code for branch-1
eead22b prepare to run
2879ed2 Improve the README and create test_file
fb4a53b init repo

Việc còn lại là chúng ta sẽ dùng câu lệnh rebase để đẩy branch-1 về ngay sau master mà không phải qua pre-run nữa. Ta dùng cấu trúc git rebase --onto target-branch source-branch và kiểm tra lại log

$ git rebase --onto master pre-run

$ git log --oneline
a6668fc code for branch-1
2879ed2 Improve the README and create test_file
fb4a53b init repo

Bạn có thể xem kĩ hơn về rebase --onto tại đây

Thay đổi hiện tại của bạn sẽ là (1)

origin content of file1

=====================================

origin content of file2
content of branch-1 # new line

Hoàn thành. Việc còn lại là đẩy code lên remote thôi

Với task mới thì bước đầu tiên là sẽ rebase nhánh pre-run đã có về master (đã ở version mới tại thời điểm đó) và project sẽ trở về trạng thái như (1)

Tiếp đó, lại tạo nhánh mới để code và tiếp tục tiến hành như trên

C2. cherry-pick commit

Tạo ra nhánh new-pre-run chứa code điều kiện cho task mới

Bạn chỉ cần lần về trước, kiểm tra log để tìm xem commit nào chứa phần điều kiện. Ở đây, đó là commit có mã SHA rút gọn eead22b ở nhánh pre-run bên trên

Từ nhánh new-pre-run, chúng ta chỉ cần cherry-pick commit đó để đưa code điều kiện vào đây

$ git cherry-pick eead22b

Ta có thể hiểu đơn giản là nếu rebase và merge thao tác với các nhánh thì cherry-pick lại là câu lệnh chỉ thao tác với các commit. Bạn có thể xem thêm chi tiết ở đây hoặc dùng lệnh để đọc doc

$ git cherry-pick --help

Quay trở lại, câu lệnh này sẽ tiến hành sao chép những thay đổi trong commitcó mã eead22bở trên và tạo ra một 'commit' mới với nội dung hoàn toàn giống, chỉ khác nhau mã SHA. Mã commit mới này là 13b0749 Kiểm tra log

$ git log --oneline
13b0749 prepare to run
2879ed2 Improve the README and create test_file
fb4a53b init repo

Đến đây thì nhánh new-pre-run đã nghiễm nhiên có toàn bộ phần code điều kiện để chúng ta làm việc. Chúng ta sẽ tiến hành code ngay trên nhánh new-pre-run này luôn với 2 file như sau

origin content of file1
content of prepare to run # new line

==============================================

origin content of file2
content of branch-3 for cherry-pick # new line

Sau khi code xong thì cũng commit để tổ chức code như bình thường

$ git log --oneline
528a5bd code for cherry-pick test
13b0749 prepare to run
2879ed2 Improve the README and create test_file
fb4a53b init repo

Đến đây, chúng ta lại về nhánh master và tiến hành cherry-pick commit 528a5bd và kiểm tra kết quả

$ git log --oneline
3f2092f code for cherry-pick test
2879ed2 Improve the README and create test_file
fb4a53b init repo

Và ta lại có được phần code như mong muốn tương tự (1) . Với task mới thì cũng làm hoàn toàn tương tự

2. Lời kết

Với cách dùng rebase thì bạn có thể chỉ cần tạo ra một nhánh duy nhất chưa phần code điều kiện đó để dùng cho nhiều task

Còn với cách dùng cherry-pick thì mỗi task bạn tạo ra một nhánh trung gian để chứa phần code điều kiện, nhưng có thể tiến hành code ngay trên nhánh trung gian đó luôn. Rất tiện lợi

Tất nhiên, trong quá trình sử dụng cherry-pick cũng như rebase, bạn phải nhuần nhuyễn khái niệm fix conflict đấy. =))

Tài liệu

  • https://viblo.asia/nguyen.van.ngoc/posts/n157G5NZvAje
  • https://viblo.asia/tand/posts/w5WQvzBnvk3E
  • https://git-scm.com/docs/git-cherry-pick
  • http://makandracards.com/makandra/10173-git-how-to-rebase-your-feature-branch-from-one-branch-to-another

Cám ơn bạn đã theo dõi bài viết, mình sẽ cố gắng tìm hiểu để có những bài viết hay hơn!

tribeo
0