Sửa lỗi 'error: The branch is not fully merged' Khi Xóa Branch Git

beginner📦 Git2026-06-27| Git 2.x trên Linux, macOS, Windows (Git Bash / WSL)

Error Message

error: The branch 'feature/my-feature' is not fully merged. If you are sure you want to delete it, run 'git branch -D feature/my-feature'.
#git#branch#merge#xóa branch

Chuyện gì vừa xảy ra

Bạn chạy git branch -d feature/my-feature để dọn dẹp sau khi hoàn thành một task, và Git từ chối:

error: The branch 'feature/my-feature' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature/my-feature'.

Những commit trên feature/my-feature không thể truy cập được từ branch hiện tại của bạn — thường là main hoặc develop. Xóa ngay bây giờ và Git sẽ dọn rác chúng sau. Công sức đổ sông đổ bể.

Sau là từ then chốt ở đây. Các commit vẫn còn tồn tại ngay lúc này. Bạn có thời gian để điều tra trước khi có chuyện xấu xảy ra.

Tại sao Git chặn việc xóa

git branch -d (chữ thường) là biến thể an toàn. Nó kiểm tra xem mọi commit trên branch có thể truy cập được từ upstream hoặc từ HEAD hay không. Nếu tìm thấy một commit không thỏa điều kiện, nó sẽ từ chối.

Bốn tình huống kích hoạt lỗi này:

  • Branch đã được merge qua squash merge hoặc rebase — các commit SHA gốc không tồn tại trên main, chỉ có một phiên bản squash hoặc rebase mới.
  • Branch đã được merge vào một branch khác chứ không phải branch bạn đang đứng.
  • Pull request đã bị đóng mà không merge và bạn sắp mất công sức thực sự.
  • Ai đó đã merge từ xa và bạn chưa fetch về.

Bước 1 — Xác định những gì thực sự chưa được merge

Trước khi dùng -D, hãy dành 30 giây cho việc này:

# Các commit trên feature branch KHÔNG có trên main
git log main..feature/my-feature --oneline

Không có output nghĩa là branch thực tế trống so với main — xóa cưỡng bức vẫn an toàn. Nếu bạn thấy commit, hãy đọc các message. Chúng có trông giống công việc bạn đã thấy xuất hiện trên main với một hash khác không?

# Đối chiếu: những gì đã xuất hiện trên main gần đây?
git log --oneline main | head -20

Cũng nên kiểm tra xem remote đã dọn dẹp sau một PR đã merge chưa:

git fetch --prune
git branch -r

Tình huống A — Branch đã được merge qua squash hoặc rebase (phổ biến nhất)

Chín trong mười trường hợp, đây là thủ phạm. Nút "Squash and merge" mặc định của GitHub và tùy chọn "Squash commits" của GitLab đều viết lại lịch sử commit — PR xuất hiện trên main dưới dạng một commit mới duy nhất với SHA hoàn toàn mới, nên Git không nhận ra các commit branch gốc là đã được merge.

Kiểm tra nhanh:

# Sẽ trống nếu code đã nằm trên main
git diff main...feature/my-feature

Diff trống? Code đã an toàn trên main. Xóa cưỡng bức branch local:

git branch -D feature/my-feature

Tình huống B — Branch được merge vào một branch khác

Feature có thể đã xuất hiện trong develop trong khi bạn đang đứng trên main. Kiểm tra với đúng branch:

git log develop..feature/my-feature --oneline

Trống? Chuyển sang branch đó và dùng lệnh xóa an toàn:

git checkout develop
git branch -d feature/my-feature

Hoặc bỏ qua bước checkout khi bạn đã xác nhận công việc ở đó:

git branch -D feature/my-feature

Tình huống C — Công việc thực sự chưa được merge

Nếu git log main..feature/my-feature --oneline hiển thị các commit bạn chưa từng thấy trên main, hãy dừng lại. Chưa xóa vội. Bạn có ba lựa chọn:

Lựa chọn 1 — Merge ngay bây giờ:

git checkout main
git merge feature/my-feature
git branch -d feature/my-feature

Lựa chọn 2 — Cherry-pick chỉ những commit cần thiết:

# Lấy hash từ output của git log
git cherry-pick <commit-hash>

Lựa chọn 3 — Tạo tag trước khi xóa (mạng lưới an toàn):

git tag backup/feature-my-feature feature/my-feature
git branch -D feature/my-feature

Tag giữ commit có thể truy cập mãi mãi. Để khôi phục sau này: git checkout -b feature/my-feature backup/feature-my-feature.

Lựa chọn mạnh tay — và khi nào dùng được

git branch -D feature/my-feature

Chữ hoa -D bỏ qua toàn bộ kiểm tra merge. Dùng khi:

  • Bạn đã chạy git diff main...feature/my-feature và không thấy gì khác biệt.
  • PR đã được squash-merge hoặc rebase-merge và bạn chỉ đang dọn dẹp các ref local cũ.
  • Đây là một thử nghiệm tạm thời mà bạn cố tình muốn loại bỏ.

Đừng dùng bừa bãi. Lỗi này là Git đang nhắc bạn suy nghĩ hai giây trước khi xóa sạch công việc mà bạn có thể cần đến.

Dọn dẹp cả các remote tracking reference

Xóa branch local để lại remote tracking reference phía sau. Hãy dọn dẹp nó:

# Xóa remote branch nếu nó vẫn còn tồn tại trên server
git push origin --delete feature/my-feature

# Hoặc prune các remote reference cũ sau khi server đã xóa
git fetch --prune

Xác nhận đã xử lý xong

# Branch phải biến mất ở local
git branch | grep feature/my-feature
# (không có output = tốt)

# Xác nhận các commit đã nằm trên main
git log main --oneline | head -10

# Kiểm tra các remote ref còn lơ lửng
git remote prune origin --dry-run

Tham khảo nhanh

# Chẩn đoán
git log main..feature/my-feature --oneline   # những gì chưa có trên main?
git diff main...feature/my-feature            # có sự khác biệt nào không?

# Xóa an toàn (sau khi xác minh)
git branch -D feature/my-feature

# Mạng lưới an toàn trước khi xóa công việc chưa merge
git tag backup/feature-my-feature feature/my-feature
git branch -D feature/my-feature

Related Error Notes