🌱 Một số kỹ thuật Git nâng cao: Git Stash, Git Rebase, Git Cherry-Pick, Git Reset

🌱 Một số kỹ thuật Git nâng cao: Git Stash, Git Rebase, Git Cherry-Pick, Git Reset

    Git là một công cụ quản lý phiên bản phân tán giúp theo dõi và kiểm soát sự thay đổi của mã nguồn. Nó đặc biệt quan trọng trong các dự án lớn, giúp nhiều lập trình viên làm việc cùng nhau một cách hiệu quả.

    ➤ Giới thiệu về Git / Github và các khái niệm cơ bản về Git

    Bài viết này tiếp tục giới thiệu về một số kỹ thuật Git nâng cao như Git Stash, Git Rebase, Git Cherry-Pick, Git Reset và cách sử dụng chúng trong dự án thực tế.

Table of Contents

Git Stash - Temporarily Save Changes

    Khi làm việc với Git, có những lúc bạn cần lưu tạm thời các thay đổi để chuyển sang một nhánh khác hoặc thực hiện một nhiệm vụ khác mà không muốn commit. Lệnh git stash giúp bạn làm điều này.

    Git stash cho phép lưu trữ các thay đổi trên repository tạm thời theo cơ chế giống như stack.

git stash save "Lưu tạm thời công việc dở dang"

Git Stash

    ➤ Các câu lệnh với git stash

  1. # Stores all uncommitted changes (both staged and unstaged)
  2. $ git stash
  3. # Restores the most recent stashed changes and removes them from the stash list
  4. $ git stash pop
  5. # Applies the stashed changes without removing them from the stash (you can reapply them multiple times)
  6. $ git stash apply
  7. # Shows a list of all stashed changes
  8. $ git stash list
  9. # Deletes the most recent stash
  10. $ git stash drop
  11. # Deletes all stashes
  12. $ git stash clear

    Video giới thiệu cách sử dụng Git Stash

Git Rebase - Move Commit to a New Base Commit

    Git Rebase là một trong hai cách chính (cách còn lại là git merge) để tích hợp các nhánh trong Git. Git Rebase được sử dụng để viết lại lịch sử commit, giúp lịch sử commit trở nên gọn gàng và tuyến tính hơn.

Cách thức hoạt động của Rebase:

    Rebase hoạt động bằng cách "đặt" các thay đổi của một nhánh lên trên một nhánh khác. Ví dụ, giả sử bạn đang làm việc trên nhánh feature và muốn cập nhật nó với những thay đổi mới nhất từ nhánh main. Khi sử dụng Rebase, các commit của nhánh feature sẽ được áp dụng lên trên commit mới nhất của nhánh main theo thứ tự.

Ưu điểm của Rebase:

  • Lịch sử commit sạch: Rebase loại bỏ các điểm rẽ nhánh phức tạp do việc gộp nhánh gây ra, và tạo ra lịch sử dự án tuyến tính. Điều này đặc biệt hữu ích trong môi trường làm việc nhóm, giúp theo dõi và hiểu lịch sử commit dễ dàng hơn.
  • Lịch sử commit có thể chỉnh sửa: Trong quá trình Rebase, bạn có thể sửa đổi lịch sử commit hoặc loại bỏ các commit không cần thiết để làm gọn lịch sử commit.

Nhược điểm của Rebase:

  • Thay đổi lịch sử: Vì Rebase thay đổi lịch sử commit, việc áp dụng Rebase cho các nhánh đã được đẩy lên kho lưu trữ từ xa có thể nguy hiểm. Nếu người khác đang làm việc dựa trên nhánh đó, có thể xảy ra các vấn đề không mong muốn.
  • Xung đột: Có thể xảy ra xung đột trong quá trình Rebase, và bạn cần giải quyết chúng. Quá trình giải quyết xung đột có thể phức tạp.

Lưu ý khi sử dụng Rebase:

  • Không rebase nhánh đã được đẩy lên remote nếu có người khác đang làm việc trên đó: Tốt nhất là không nên sử dụng Rebase cho các nhánh đã được đẩy lên kho lưu trữ từ xa.
  • Sử dụng Rebase cho nhánh cá nhân: Khi làm việc trên nhánh cá nhân, bạn có thể tự do sử dụng Rebase để làm gọn lịch sử commit.
  • Luyện tập giải quyết xung đột: Điều quan trọng là phải làm quen với cách giải quyết xung đột có thể xảy ra trong quá trình Rebase.

Ví dụ về lệnh Rebase:

main:   A---B---C
             \
feature:       D---E---F
 
# If you rebase feature onto main:
 $ git checkout feature
 $ git rebase main
 
# The history will be rewritten as:
main:   A---B---C
                \
feature:          D'---E'---F'
 
# Here, commits D, E, and F are replayed on top of main. This creates a cleaner, linear history without the need for a merge commit

Interactive Rebase

    Là một chế độ đặc biệt của git rebase, cho phép bạn tương tácchỉnh sửa lịch sử commit trước khi áp dụng chúng.

  • Khi sử dụng git rebase -i (interactive rebase), bạn có thể thực hiện các thao tác như:
    • Gộp commit (squash)
    • Sắp xếp lại commit
    • Xóa commit

💡 Điều này đáng nhắc đến vì nó giúp làm gọn lịch sử commit một cách có kiểm soát.

    Giả sử bạn muốn chỉnh sửa 3 commit gần nhất:

git rebase -i HEAD~3

    Lệnh này sẽ mở trình soạn thảo với danh sách các commit gần nhất:

pick 123abc Commit 1 pick 456def Commit 2 pick 789ghi Commit 3

    Bạn có thể thay đổi pick thành các lệnh khác như:

  • squash (s): Gộp commit này với commit trước đó.
  • edit (e): Chỉnh sửa commit.
  • reword (r): Chỉnh sửa nội dung commit message.
  • drop: Xóa commit.

Git Cherry-Pick - Merge Specific Commit

git cherry-pick là một lệnh trong Git cho phép bạn chọn một hoặc nhiều commit từ nhánh này và áp dụng chúng vào nhánh khác mà không cần merge toàn bộ nhánh.

Cách sử dụng Git Cherry-Pick

    Cú pháp cơ bản:

git cherry-pick <commit-hash>

    Trong đó:

  • <commit-hash> là mã hash của commit bạn muốn áp dụng vào nhánh hiện tại.

🔹 Ví dụ: Giả sử lịch sử commit của bạn như sau:

main: A --- B --- C --- D (đang checkout) feature: E --- F --- G

    Bây giờ bạn muốn lấy commit F từ feature và áp dụng nó vào main:

git checkout main git cherry-pick <hash-of-F>

    Sau đó, lịch sử sẽ trở thành:

main: A --- B --- C --- D --- F'

    Commit F đã được sao chép sang main với một mã hash mới.

Chọn nhiều commit một lúc

    Bạn có thể cherry-pick nhiều commit cùng lúc bằng cách liệt kê chúng:

git cherry-pick <commit1-hash> <commit2-hash> <commit3-hash>

    Hoặc chọn một khoảng commit bằng cách dùng ^ hoặc dấu ..:

git cherry-pick A^..C # Chọn tất cả commit từ A đến C (bao gồm cả A và C)

Giải quyết xung đột khi Cherry-Pick

    Khi cherry-pick, nếu có xung đột (conflict), Git sẽ thông báo và yêu cầu bạn giải quyết. Bạn cần:

  1. Chỉnh sửa file bị xung đột.
  2. Sau khi giải quyết xong, chạy lệnh:
    git add <file-bị-xung-đột> git cherry-pick --continue
  3. Nếu muốn hủy cherry-pick, dùng:
    git cherry-pick --abort

Cherry-Pick và Tùy Chọn Hữu Ích

LệnhChức năng
git cherry-pick -n <commit-hash>Cherry-pick commit nhưng chưa commit ngay (cho phép chỉnh sửa trước khi commit).
git cherry-pick -x <commit-hash>Thêm dòng tham chiếu gốc ((cherry picked from commit <hash>)) vào commit mới.
git cherry-pick --edit <commit-hash>Sửa nội dung commit message trước khi commit.

Khi Nào Nên Dùng Git Cherry-Pick?

✅ Khi bạn chỉ muốn lấy một hoặc vài commit cụ thể từ một nhánh khác.
✅ Khi bạn không muốn merge toàn bộ nhánh vì có quá nhiều commit không liên quan.
✅ Khi bạn cần sao chép một commit đã bị mất từ một nhánh khác.


Khi Nào Không Nên Dùng Git Cherry-Pick?

🚫 Khi bạn cần hợp nhất toàn bộ thay đổi – dùng git merge hoặc git rebase sẽ phù hợp hơn.
🚫 Khi làm việc với nhánh remote có nhiều người – vì cherry-pick có thể tạo commit mới với hash khác, gây khó khăn khi đồng bộ lịch sử commit.

Git Reset - Undo Change

git reset là một lệnh mạnh mẽ trong Git, cho phép bạn quay lại trạng thái trước đó của commit, stage, hoặc working directory. Nó thường được dùng để hoàn tác commit hoặc thay đổi cục bộ một cách linh hoạt.


Các chế độ của git reset

git reset có 3 chế độ chính, tùy thuộc vào phạm vi bạn muốn hoàn tác:

Chế ĐộẢnh Hưởng Đến CommitẢnh Hưởng Đến Staging Area (git add)Ảnh Hưởng Đến Working Directory
--soft✅ Hoàn tác commit❌ Giữ nguyên❌ Giữ nguyên
--mixed (Mặc định)✅ Hoàn tác commit✅ Gỡ khỏi staging❌ Giữ nguyên
--hard✅ Hoàn tác commit✅ Gỡ khỏi staging✅ Xóa thay đổi trong working directory

Cách sử dụng git reset

🔹 Reset commit nhưng giữ lại thay đổi (--soft)

Tình huống: Bạn vừa commit nhưng muốn chỉnh sửa thêm trước khi commit lại.

git reset --soft HEAD~1

💡 Kết quả:

  • Commit bị hoàn tác (tức là commit gần nhất sẽ bị xóa khỏi lịch sử Git).
  • Các thay đổi vẫn còn trong staging area (git status sẽ hiển thị chúng đã được staged).
  • Có thể chỉnh sửa thêm rồi commit lại.

🔹 Reset commit và bỏ staging (--mixed, mặc định)

Tình huống: Bạn đã git add . nhưng muốn hoàn tác staging trước khi commit.

git reset --mixed HEAD~1

💡 Kết quả:

  • Commit bị hoàn tác.
  • Các file đã git add sẽ bị đưa trở lại trạng thái chưa được staged.
  • Các thay đổi vẫn còn trong working directory, có thể chỉnh sửa tiếp hoặc git add lại.

🔹 Reset commit và xóa tất cả thay đổi (--hard)

Tình huống: Bạn muốn quay lại trạng thái sạch hoàn toàn như chưa từng thay đổi gì.

git reset --hard HEAD~1

💡 Kết quả:

  • Commit bị hoàn tác.
  • Các thay đổi bị xóa hoàn toàn khỏi staging và working directory (⚠️ Không thể khôi phục nếu không có backup).

Reset về một commit cụ thể

    Thay vì HEAD~1 (commit gần nhất), bạn có thể reset về bất kỳ commit nào bằng cách dùng commit hash:

git reset --hard <commit-hash>

Ví dụ:

git reset --mixed 3f5e3b2

💡 Điều này sẽ làm cho branch hiện tại trỏ về commit 3f5e3b2, loại bỏ tất cả commit sau đó.

❗ Tuy nhiên, có một điểm cần chú ý đó là git reset --hard không thể hoàn tác nếu không có backup! Nếu lỡ dùng git reset --hard, bạn có thể thử tìm lại commit đã mất bằng:

git reflog

    Sau đó, khôi phục commit bằng:

git reset --hard <commit-hash-cũ>

Khi nào nên dùng git reset?

✅ Khi muốn hoàn tác commit gần nhất nhưng vẫn giữ lại thay đổi (--soft).
✅ Khi muốn gỡ bỏ staging nhưng không mất thay đổi (--mixed).
✅ Khi cần xóa sạch tất cả thay đổi cục bộ (--hard).


Khi nào không nên dùng git reset?

🚫 Khi branch đã được đẩy lên remote và người khác đang làm việc trên đó (reset có thể làm mất commit của họ).
🚫 Khi muốn giữ lại lịch sử commit – trong trường hợp này, git revert có thể là một lựa chọn tốt hơn.

>>>>>> Follow ngay <<<<<<<

Để nhận được những bài học miễn phí mới nhất nhé 😊
Chúc các bạn học tập tốt 😊

Nguyễn Văn Nghĩa

Mình là một người thích học hỏi và chia sẻ các kiến thức về Nhúng IOT.

Đăng nhận xét

Mới hơn Cũ hơn
//