Hướng Dẫn Rebase và Cập Nhật Pull Request: Các Bước Quan Trọng Để Tối Ưu Mã Nguồn Trên GitHub

Hướng Dẫn Rebase và Cập Nhật Pull Request: Các Bước Quan Trọng Để Tối Ưu Mã Nguồn Trên GitHub

Đóng góp vào các dự án mã nguồn mở là một cơ hội tuyệt vời để bạn cải thiện phần mềm và mang lại giá trị cho cộng đồng người dùng. Khi gửi pull request, bạn có thể cần thực hiện một số bước rebase, chỉnh sửa mã nguồn, và tối ưu hóa nhánh trước khi yêu cầu của bạn được chấp nhận.

DataOnline sẽ hướng dẫn bạn các bước quan trọng cần thực hiện sau khi gửi pull request để đảm bảo mã nguồn của bạn tuân thủ tiêu chuẩn dự án, tăng khả năng được chấp nhận và duy trì sự gọn gàng trong kho lưu trữ Git.

Yêu cầu tiên quyết

Hướng dẫn này sẽ giúp bạn hiểu rõ những bước cần thực hiện sau khi tạo pull request, vì vậy bạn nên đảm bảo rằng Git đã được cài đặt và bạn đã gửi hoặc đang có kế hoạch gửi pull request cho một dự án mã nguồn mở.

Từ tháng 11 năm 2020, GitHub đã loại bỏ phương thức xác thực bằng mật khẩu khi làm việc với repository qua dòng lệnh. Thay vào đó, bạn cần sử dụng Personal Access Token (PAT) hoặc cấu hình SSH Public Key để đảm bảo kết nối an toàn và tuân thủ các tiêu chuẩn bảo mật mới của GitHub.

Rebase mã nguồn và dọn dẹp các bình luận

Khi bạn đóng góp cho mã nguồn mở, có thể xảy ra xung đột giữa nhánh (branch) hoặc pull request của bạn với mã nguồn upstream. Bạn có thể nhận được thông báo lỗi như sau trong terminal:

Output
CONFLICT (content): Merge conflict in your-file.py
Automatic merge failed; fix conflicts and then commit the result.

Hoặc như trên giao diện pull request của GitHub:

Thiet ke chua co ten 8

Điều này có thể xảy ra nếu các maintainer không phản hồi pull request của bạn trong một thời gian hoặc nếu có nhiều người cùng đóng góp cho dự án cùng lúc. Khi điều này xảy ra và bạn vẫn muốn hợp nhất pull request, bạn sẽ phải giải quyết xung đột và thực hiện rebase mã nguồn.

Rebase cho phép chúng ta di chuyển nhánh bằng cách thay đổi commit mà nhánh đó dựa vào. Nhờ đó, chúng ta có thể rebase mã nguồn của mình để dựa vào các commit mới nhất của nhánh chính (main). Quá trình rebase cần được thực hiện cẩn thận, đảm bảo rằng bạn đang làm việc với đúng các commit và trên nhánh đúng trong suốt quá trình. Chúng ta cũng sẽ sử dụng lệnh git reflog ở dưới đây trong trường hợp bạn mắc lỗi.

Chuyển vào thư mục chứa mã nguồn:

cd repository

Tiếp theo, bạn cần đảm bảo rằng đang ở trên nhánh đúng bằng cách chuyển sang nhánh đó với lệnh git checkout:

git checkout new-branch

Sau đó, chạy lệnh git fetch để lấy phiên bản upstream mới nhất của mã nguồn:

git fetch origin

Sau khi đã fetch được phiên bản upstream của dự án, bạn có thể dọn dẹp các bình luận (commit messages) bằng cách squash hoặc chỉnh sửa lại nội dung commit để chúng dễ hiểu hơn đối với các maintainer của dự án. Nếu bạn không thực hiện nhiều commit nhỏ, việc này có thể không cần thiết.

Để bắt đầu quá trình này, bạn sẽ thực hiện một rebase tương tác (interactive rebase). Rebase tương tác cho phép bạn chỉnh sửa các commit message trước đó, gộp nhiều commit thành một, hoặc xóa/bỏ qua các commit không cần thiết. Để làm điều này, bạn cần tham chiếu các commit đã thực hiện, bằng số thứ tự hoặc chuỗi tham chiếu đến gốc của nhánh.

Để biết số lượng commit bạn đã thực hiện, bạn có thể xem toàn bộ commit của dự án với lệnh:

git log

Lệnh này sẽ cung cấp cho bạn kết quả tương tự như sau:

Output
commit 46f196203a16b448bf86e0473246eda1d46d1273
Author: username-2 <email-2>
Date:   Mon Dec 14 07:32:45 2015 -0400

    Commit details

commit 66e506853b0366c87f4834bb6b39d941cd034fe3
Author: username1 <email-1>
Date:   Fri Nov 27 20:24:45 2015 -0500

    Commit details

Log sẽ hiển thị tất cả các commit được thực hiện trên repository của dự án, do đó các commit của bạn sẽ được liệt kê cùng với các commit của người khác. Với các dự án có lịch sử commit rộng lớn của nhiều tác giả, bạn có thể chỉ định bản thân mình làm tác giả bằng cách dùng lệnh:

git log --author=your-username

Tham số --author=your-username sẽ giúp bạn đếm số lượng commit bạn đã thực hiện. Nếu bạn làm việc trên nhiều nhánh, bạn có thể thêm --branches[=<branch>] vào cuối lệnh để giới hạn theo nhánh.

Nếu bạn đã biết số lượng commit bạn đã thực hiện trên nhánh cần rebase, bạn có thể chạy lệnh git rebase như sau:

git rebase -i HEAD~x

Ở đây, -i nghĩa là rebase tương tác, và HEAD đề cập đến commit mới nhất từ nhánh chính. x sẽ là số lượng commit bạn đã thực hiện trên nhánh kể từ khi bạn fetch lần đầu.

Nếu bạn không biết mình đã có bao nhiêu commit trên nhánh, bạn cần tìm commit là gốc của nhánh bằng lệnh:

git merge-base new-branch main

Lệnh này sẽ trả về một chuỗi dài gọi là commit hash, ví dụ:

Output
66e506853b0366c87f4834bb6b39d341cd094fe9

Chúng ta sẽ dùng commit hash này cho lệnh git rebase:

git rebase -i 66e506853b0366c87f4834bb6b39d341cd094fe9

Với bất kỳ lệnh nào ở trên, trình soạn thảo văn bản dòng lệnh của bạn sẽ mở ra một file chứa danh sách tất cả các commit trên nhánh của bạn, và bây giờ bạn có thể chọn gộp các commit (squash) hoặc chỉnh sửa (reword) chúng.

Gộp Commit

Khi bạn squash các commit, bạn đang gộp hoặc kết hợp nhiều commit nhỏ thành một commit lớn hơn.

Trước mỗi commit, bạn sẽ thấy từ “pick”, vì vậy file của bạn sẽ trông như sau nếu có hai commit:

GNU nano 2.0.6 File: ...username/repository/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

Bây giờ, đối với mỗi dòng trừ dòng đầu tiên, bạn hãy thay từ “pick” thành “squash” để gộp các commit lại:

GNU nano 2.0.6 File: ...username/repository/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

Sau đó, bạn lưu và đóng file. Một file mới sẽ mở ra hiển thị nội dung kết hợp của tất cả các commit message. Bạn có thể chỉnh sửa nội dung commit message theo ý mình, sau đó lưu và đóng file.

Khi file đóng lại, bạn sẽ nhận được phản hồi:

GNU nano 2.0.6 File: ...username/repository/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature
squash 79c0e80 Here is another new feature

Bạn sẽ nhận được phản hồi sau khi đã đóng tệp:

Output
Successfully rebased and updated refs/heads/new-branch

Như vậy, bạn đã gộp tất cả các commit lại thành một commit duy nhất.

Chỉnh sửa Commit Messages

Chỉnh sửa (reword) commit message rất hữu ích khi bạn phát hiện lỗi chính tả hoặc nhận ra rằng các commit chưa sử dụng ngôn ngữ song song.

Sau khi thực hiện rebase tương tác với lệnh git rebase -i như mô tả ở trên, bạn sẽ thấy một file mở ra trông như sau:

GNU nano 2.0.6 File: ...username/repository/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

Bây giờ, đối với mỗi commit mà bạn muốn chỉnh sửa, hãy thay từ “pick” thành “reword”:

GNU nano 2.0.6 File: ...username/repository/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature
reword 79c0e80 Adding a second new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

Khi bạn lưu và đóng file, một file văn bản mới sẽ xuất hiện trong trình soạn thảo của terminal hiển thị nội dung commit message đã chỉnh sửa. Nếu cần, bạn có thể chỉnh sửa lại trước khi lưu và đóng file, đảm bảo rằng các commit message của bạn rõ ràng và nhất quán.

Hoàn thành quá trình Rebase

Khi bạn đã hài lòng với số lượng commit và nội dung commit message, bạn nên hoàn thành việc rebase nhánh của mình lên phiên bản mới nhất của mã nguồn upstream của dự án. Để làm điều này, hãy chạy lệnh sau từ thư mục repository:

git rebase origin/main

Tại thời điểm này, Git sẽ bắt đầu áp dụng lại các commit của bạn lên phiên bản mới nhất của nhánh main. Nếu có xung đột xảy ra trong quá trình này, Git sẽ tạm dừng và yêu cầu bạn giải quyết xung đột trước khi tiếp tục. Nếu không có gì cần giải quyết, bạn sẽ nhận được thông báo:

Output
Current branch new-branch is up to date.

Sau khi đã giải quyết các xung đột, bạn chạy:

git rebase --continue

Lệnh này báo cho Git biết rằng bạn đã sẵn sàng tiếp tục áp dụng lại các commit của mình. Nếu bạn đã gộp commit bằng lệnh squash, bạn chỉ cần giải quyết xung đột một lần.

Cập nhật Pull Request với Force-Push

Sau khi thực hiện rebase, lịch sử của nhánh của bạn sẽ thay đổi, và bạn sẽ không thể sử dụng lệnh git push thông thường vì đường dẫn trực tiếp đã bị thay đổi.

Thay vào đó, bạn sẽ phải sử dụng cờ –force hoặc -f để force-push các thay đổi, thông báo cho Git rằng bạn hoàn toàn nhận thức được những gì mình đang push.

Trước hết, hãy đảm bảo rằng cấu hình push.default của bạn là simple (mặc định trong Git 2.0+), bằng cách cấu hình như sau:

git config --global push.default simple

Tiếp theo, hãy chắc chắn rằng bạn đang ở trên nhánh làm việc bằng cách chuyển sang nhánh đó:

git checkout new-branch
Output
Already on 'new-branch'
. . .

Giờ đây, bạn có thể thực hiện force-push:

git push -f

Sau khi force-push, bạn sẽ nhận được phản hồi về các thay đổi của mình cùng với thông báo rằng đây là một bản cập nhật bắt buộc. Pull request của bạn đã được cập nhật.

Khôi phục các Commit bị mất

Nếu tại một thời điểm nào đó bạn vô tình xóa bỏ một commit mà bạn rất muốn tích hợp vào dự án, bạn có thể sử dụng Git để khôi phục lại các commit đã bị bỏ qua.

Chúng ta sẽ sử dụng lệnh git reflog để tìm các commit bị mất và sau đó tạo một nhánh mới từ commit đó.

Reflog (viết tắt của “reference logs“) ghi lại thời điểm các tip của nhánh và các tham chiếu khác được cập nhật trong repository cục bộ.

Từ thư mục cục bộ của repository, hãy chạy lệnh:

git reflog

Sau khi chạy lệnh này, bạn sẽ nhận được kết quả tương tự như:

Output
46f1962 HEAD@{0}: checkout: moving from branch-1 to new-branch
9370d03 HEAD@{1}: commit: code cleanups
a1f29a6 HEAD@{2}: commit: brand new feature 
38f2fc2 HEAD@{3}: commit: remove testing methods 
. . .

Các thông điệp commit sẽ cho bạn biết commit nào là commit bạn đã bỏ lỡ, chuỗi ký tự ở bên trái (trước thông tin HEAD@{x}) chính là commit hash cần thiết.

Giờ bạn có thể dùng thông tin đó để tạo một nhánh mới từ commit tương ứng:

git checkout -b new-new-branch a1f29a6

Trong ví dụ trên, chúng ta đã tạo một nhánh mới từ commit thứ ba hiển thị, commit này chứa tính năng tính năng hoàn toàn mới, được đại diện bởi chuỗi a1f29a6.

Tùy thuộc vào việc bạn cần làm gì tiếp theo, bạn có thể làm theo các bước thiết lập nhánh như trong hướng dẫn tạo pull request, hoặc quay lại đầu hướng dẫn này để tiếp tục rebase nhánh mới.

Lưu ý: Nếu bạn vừa chạy lệnh git gc để dọn dẹp các file không cần thiết và tối ưu hóa repository cục bộ, có thể bạn sẽ không khôi phục được các commit đã mất.

Những điều cần mong đợi trong quá trình code review

Khi bạn gửi pull request, bạn đang bước vào một cuộc đối thoại với một dự án lớn. Gửi pull request là cách mời người khác cùng thảo luận về công việc của bạn, giống như cách bạn chia sẻ và bàn luận về mã nguồn của mình.

Để có một cuộc trao đổi hiệu quả, bạn cần truyền đạt lý do bạn tạo pull request qua các commit message của mình, do đó hãy cố gắng viết càng rõ ràng và chính xác càng tốt.

Quá trình review pull request có thể kéo dài và chi tiết, tùy thuộc vào dự án. Hãy coi quá trình này như một trải nghiệm học hỏi và là cơ hội để cải thiện mã nguồn, làm cho pull request của bạn trở nên tốt hơn và phù hợp hơn với nhu cầu của dự án. Các maintainer sẽ ghi nhận các ghi chú, cập nhật và các cuộc thảo luận cùng với pull request của bạn. Bạn có thể phải thực hiện một vài commit bổ sung trong quá trình này trước khi pull request được chấp nhận. Đây là điều hoàn toàn bình thường và là cơ hội tốt để bạn cùng nhóm cải thiện và chỉnh sửa mã nguồn.

Pull request của bạn sẽ được duy trì thông qua Git và tự động cập nhật khi bạn tiếp tục thêm commit vào cùng một nhánh và push chúng lên fork của bạn.

Mặc dù bạn đang đưa mã nguồn của mình ra cho cộng đồng đánh giá, bạn không bao giờ nên cảm thấy rằng quá trình review mang tính cá nhân. Hãy đọc các file CONTRIBUTION.md hoặc Code of Conduct liên quan để đảm bảo rằng các commit của bạn phù hợp với hướng dẫn của dự án. Nếu bạn cảm thấy không thoải mái, có thể dự án đó không xứng đáng với sự đóng góp của bạn. Cộng đồng mã nguồn mở luôn có nhiều không gian chào đón và dù phản hồi của bạn có được xem xét kỹ lưỡng, tất cả đều phải chuyên nghiệp và lịch sự.

Chấp nhận Pull Request và xóa Nhánh

Nếu pull request của bạn đã được chấp nhận, bạn đã đóng góp thành công cho một dự án phần mềm mã nguồn mở!

Lúc này, bạn cần kéo các thay đổi bạn đã thực hiện về fork của mình thông qua repository cục bộ. Đây chính là việc bạn đã làm khi đồng bộ fork của mình. Bạn có thể thực hiện việc này bằng các lệnh sau trong terminal:

git checkout main
git pull --rebase origin main
git push -f origin main

Giờ đây, bạn nên dọn dẹp cả nhánh cục bộ và nhánh remote bằng cách xóa nhánh mà bạn đã tạo vì nó không còn cần thiết. Đầu tiên, hãy xóa nhánh cục bộ:

git branch -d new-branch

Cờ -d của lệnh git branch sẽ xóa nhánh mà bạn chỉ định, trong ví dụ trên là new-branch.

Tiếp theo, xóa nhánh remote:

git push origin --delete new-branch

Với việc xóa nhánh, bạn đã dọn dẹp repository và các thay đổi của bạn giờ đây đã nằm trong repository chính. Hãy nhớ rằng vì các thay đổi bạn thực hiện thông qua pull request đã trở thành một phần của repository chính, nên đối với người dùng cuối tải về các bản phát hành công khai, chúng có thể không hiển thị ngay lập tức. Nói chung, các maintainer sẽ gộp một số tính năng mới và các bản sửa lỗi lại với nhau thành một bản phát hành công khai.

Kết luận

Hướng dẫn này đã giúp bạn nắm rõ những bước quan trọng cần thực hiện sau khi gửi pull request cho một repository mã nguồn mở, giúp bạn tối ưu hóa quy trình đóng góp và tăng khả năng được chấp nhận.

Việc đóng góp vào các dự án mã nguồn mở không chỉ giúp bạn phát triển kỹ năng mà còn tạo cơ hội trở thành một thành viên tích cực trong cộng đồng lập trình viên. Khi bạn thường xuyên đóng góp cho các phần mềm mà mình sử dụng, bạn không chỉ giúp cải thiện chất lượng phần mềm mà còn đảm bảo rằng nó tiếp tục mang lại giá trị và lợi ích cho cộng đồng người dùng trên toàn thế giới.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *