Đừng hoảng loạn khi Terminal báo lỗi
Màn hình hiện thông báo lỗi đỏ rực ngay trước giờ deploy là cơn ác mộng của mọi lập trình viên. Mình từng chứng kiến một bạn đồng nghiệp suýt khóc khi làm mất toàn bộ code của một tuần chỉ vì gõ nhầm git reset --hard.
Git rất linh hoạt nhưng cũng đầy cạm bẫy nếu bạn chưa hiểu rõ cơ chế con trỏ (pointers). Thay vì xóa thư mục rồi git clone lại từ đầu, hãy học cách làm chủ nó. Dưới đây là 10 tình huống trớ trêu nhất và cách giải quyết gọn gàng bằng tư duy kỹ thuật.
Git thực tế là một cỗ máy thời gian
Mọi thứ trong Git gần như không bao giờ mất đi nếu bạn đã từng commit. Git lưu lại mọi biến động trong một cuốn nhật ký ngầm gọi là Reference Logs (reflog). Khi nắm được chìa khóa này, bạn sẽ thấy Git không còn là một hệ thống khó nắm bắt nữa.
1. Lỗi “Detached HEAD” – Khi bạn lơ lửng giữa hư không
Lỗi này xuất hiện khi bạn git checkout về một commit ID cụ thể thay vì một nhánh. Lúc này, HEAD không trỏ vào bất kỳ tên nhánh nào. Bạn vẫn code được, nhưng các commit mới sẽ không thuộc về nhánh nào cả.
# Thông báo thường gặp:
# You are in 'detached HEAD' state.
Cách xử lý: Nếu lỡ code thêm vài tính năng ở trạng thái này, hãy tạo ngay một nhánh mới để giữ lại công sức của mình.
# Tạo nhánh mới ngay tại vị trí hiện tại
git checkout -b recovery-branch
# Quay về nhánh chính và merge lại
git checkout main
git merge recovery-branch
2. Push Rejected (Non-fast-forward)
Bạn push code và nhận về thông báo: [rejected] main -> main (fetch first). Điều này xảy ra khi một đồng nghiệp đã push code lên server trước bạn. Repository trên máy bạn hiện đang cũ hơn so với server.
Cảnh báo: Tuyệt đối không dùng git push --force trong dự án chung. Lệnh này sẽ ghi đè và xóa sạch lịch sử commit của cả team trên server.
Cách xử lý an toàn:
# Cách 1: Rebase (giúp lịch sử commit thẳng và đẹp)
git pull --rebase origin main
git push origin main
# Cách 2: Merge truyền thống
git pull origin main
# Xử lý conflict nếu có rồi mới push
3. Commit nhầm vào nhánh Main
Đáng lẽ phải làm trên feature-login, nhưng bạn lại hì hục code thẳng trên main. Tình huống này rất phổ biến khi làm việc vội vã.
Cách xử lý: Chuyển các commit đó sang nhánh đúng và đưa main về trạng thái ban đầu.
# 1. Tạo nhánh mới để giữ lại các commit vừa rồi
git branch feature-login
# 2. Reset nhánh main lùi lại (ví dụ lùi 3 commit)
git reset --hard HEAD~3
# 3. Sang nhánh feature để tiếp tục làm việc
git checkout feature-login
4. Cứu dữ liệu sau khi lỡ `git reset –hard`
Đây là lúc git reflog tỏa sáng. Giả sử bạn vừa xóa nhầm 5 commit quan trọng bằng lệnh reset. Đừng lo, Git vẫn còn lưu vết của chúng.
git reflog
# Tìm dòng có nội dung commit bạn vừa làm mất, ví dụ: ab12345
# Khôi phục lại chính xác thời điểm đó
git reset --hard ab12345
5. Sửa tin nhắn commit vừa thực hiện
Bạn vừa commit xong thì thấy sai lỗi chính tả hoặc quên chưa git add một file cấu hình. Thay vì tạo thêm một commit mới gây loãng lịch sử, hãy dùng --amend.
# Thêm file còn thiếu
git add config.json
# Ghi đè vào commit gần nhất
git commit --amend --no-edit
# Nếu chỉ muốn đổi nội dung tin nhắn
git commit --amend -m "Tin nhắn mới chuẩn hơn"
6. Hủy bỏ quá trình Merge/Rebase đang lỗi
Đôi khi việc giải quyết xung đột (conflict) quá phức tạp khiến code rối tung. Bạn muốn quay lại trạng thái trước khi merge để tính toán lại.
# Dừng ngay lập tức và đưa code về ban đầu
git merge --abort
# Tương tự nếu đang rebase dở dang
git rebase --abort
7. File nằm trong .gitignore nhưng vẫn bị theo dõi
Bạn đã thêm .env vào .gitignore nhưng Git vẫn báo có thay đổi mỗi khi bạn sửa file này. Nguyên nhân là do file đã được lưu vào bộ nhớ đệm (cache) của Git từ trước đó.
Cách xử lý: Xóa file khỏi cache nhưng không xóa khỏi ổ cứng.
git rm --cached .env
git add .gitignore
git commit -m "Ngừng theo dõi file môi trường"
8. Lỡ commit file dung lượng quá lớn
Bạn vô tình commit file log 500MB hoặc thư mục node_modules. Dù bạn có xóa ở commit sau, file này vẫn nằm trong lịch sử và làm nặng file .git.
Cách xử lý: Sử dụng công cụ git-filter-repo hoặc bfg. Tránh dùng filter-branch vì lệnh này rất chậm và đã bị Git khuyến cáo không nên dùng nữa.
# Ví dụ dùng BFG để xóa file lớn nhanh chóng
bfg --strip-blobs-with-ids-larger-than 50M
9. Đổi tên nhánh nhanh chóng
Việc gõ sai tên nhánh như feture-ui thay vì feature-ui rất thường gặp. Bạn có thể sửa tên ở máy mình rồi cập nhật lên server.
# Đổi tên ở local
git branch -m feture-ui feature-ui
# Xóa nhánh sai trên server và push nhánh đúng
git push origin --delete feture-ui
git push origin feature-ui
10. Lỗi Case-Sensitivity (Chữ hoa/Chữ thường)
Windows không phân biệt User.js và user.js, nhưng Linux (Server) thì có. Điều này thường gây lỗi khi deploy. Git đôi khi không nhận ra bạn vừa đổi tên file từ chữ thường sang chữ hoa.
Cách xử lý: Ép Git nhận diện việc đổi tên bằng lệnh git mv.
git mv user.js User.js
# Hoặc cấu hình để Git luôn phân biệt hoa thường
git config core.ignorecase false
Kinh nghiệm thực tế từ dự án
Làm việc với Git cũng giống như vận hành một hệ thống, sai sót là điều khó tránh. Tuy nhiên, thay vì lạm dụng --force, hãy ưu tiên các lệnh an toàn.
Mẹo nhỏ của mình: Trước khi thực hiện các lệnh can thiệp sâu vào lịch sử như rebase hay filter-branch, hãy tạo một nhánh backup. Nếu có hỏng hóc, bạn chỉ mất 5 giây để quay lại trạng thái cũ. Chúc các bạn có những commit sạch đẹp và không còn phải thức trắng đêm vì lỗi Git!

