Mặc dù bạn có thể không gặp vấn đề detached HEAD, nhưng quan trọng là biết về nó để tránh. Theo khuyến nghị, không nên commit trên detached HEAD nhưng nếu bạn làm, chúng ta sẽ chỉ cách lưu commit.
Nhắc lại
Để hiểu HEAD là gì, hãy làm lại cơ bản về cấu trúc dạng cây của Git.
- Working Directory (Thư mục làm việc): Hay working tree. Tham chiếu đến thư mục cục bộ và
git statuscho trạng thái thư mục làm việc. - HEAD: Chỉ là snapshot commit cuối của nhánh hiện tại. Nếu bạn chuyển nhánh với
git checkoutthì HEAD sẽ thay đổi thành commit cuối trên nhánh đó. - Index (Chỉ mục): Hay khu vực chuẩn bị (staging area), nên khi bạn
git addfile để commit nó thêm vào index này.
Hiểu Attached HEAD (HEAD gắn kết)
Bây giờ chúng ta hiểu HEAD chỉ là commit mới nhất trên nhánh bạn đang ở. Bằng git status nó sẽ báo nhánh v.d. On branch master và bằng git log nó sẽ cho lịch sử commit với thông tin như:
commit 38373004b8f651b58cea64cd629e1e2c18c164a0 (HEAD -> master, origin/master, origin/HEAD) Author: Felipe <email> Date: Wed Sep 29 22:57:59 2020 -0500
Sau đó nếu chúng ta đổi nhánh sang development branch với git checkout development thì HEAD sẽ di chuyển đến commit cuối. Vì vậy trong tất cả trường hợp bình thường head theo dõi chúng ta như nó nên gắn với commit cuối trên nhánh chúng ta đang ở.
Tách rời HEAD (Detaching the HEAD)
Có vài cách chúng ta có thể tách rời HEAD.
- Dùng lệnh
git checkout --detach. - Checkout đến commit hash. V.d. Nếu dùng commit từ trên
git checkout 38373004b8f651b58cea64cd629e1e2c18c164a0 - Thêm ^0 trên bất kỳ nhánh nào. V.d.
git checkout master^0.
Tôi không chắc bạn có muốn tách rời HEAD ý thức. Vì vậy trường hợp phổ biến nhất là nhầm lẫn bạn muốn checkout nhánh nhưng dùng commit hash thay vì tên nhánh.
Vậy sau detached HEAD xảy ra gì? Bạn có thể nhận cảnh báo như sau:
$ git checkout 38373004b8f651b58cea64cd629e1e2c18c164a0 Note: checking out '38373004b8f651b58cea64cd629e1e2c18c164a0'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout.
Một khi ở môi trường detached HEAD, nếu bạn làm git status ngay cả khi bạn làm thay đổi, nó sẽ nói kiểu:
HEAD detached at ac63806 nothing to commit, working tree clean
Vì vậy nó giống như bạn bị đóng băng trong thời gian và mọi thứ bạn làm bị mất, hoặc chỉ đơn giản không đi đâu. Tại sao? Vì HEAD không trỏ đến bất cứ thứ gì.
Một số người thấy điều này hữu ích để khám phá trạng thái trước của kho mà không lo làm hỏng.
Gắn lại HEAD (Re-Attaching the HEAD)
Bạn phải hiểu rằng bất kỳ nhánh nào sẽ không bị ảnh hưởng nếu bạn bao giờ rơi vào trạng thái tách rời. Cách tốt nhất để gắn lại HEAD là tạo nhánh mới.
Chúng ta có thể làm đơn giản như git checkout -b <tên-nhánh>.
Nếu chúng ta không nhận ra chúng ta không có HEAD và bắt đầu làm thay đổi? Vâng, ở đây chúng ta sẽ cần tạo nhánh tạm và hợp nhất với nhánh cần commit. Ví dụ:
git checkout -b temp-branch git checkout master git merge temp-branch
Điều này sẽ commit thay đổi từ nhánh tạm vào nhánh bạn cần. Trong trường hợp này là master.
Kết luận
Hôm nay chúng ta học cách tách rời HEAD (không phải nghĩa đen) và làm gì sau đó. Hiểu HEAD là gì trong cơ chế bên trong Git giúp chúng ta hiểu các trường hợp đặc biệt như detached HEAD.
Chúng ta cũng học không cần lo lắng nếu bao giờ rơi vào trạng thái detached HEAD. Chỉ cần nhớ rằng vì HEAD lỏng lẻo, thay đổi và commit sẽ không phản ánh bất cứ đâu. Vì vậy hãy chắc chắn bạn gắn lại HEAD tương ứng.