Tại sao repo Git của tôi vào trạng thái CHÍNH tách ra?


387

Tôi đã kết thúc với một cái đầu tách ra ngày hôm nay, cùng một vấn đề như được mô tả trong: git đẩy nói mọi thứ cập nhật mặc dù tôi có những thay đổi cục bộ

Theo như tôi biết tôi đã không làm bất cứ điều gì khác thường, chỉ cam kết và thúc đẩy từ repo địa phương của tôi.

Vì vậy, làm thế nào tôi kết thúc với một detached HEAD?


18
Kiểm tra một chi nhánh từ xa có vẻ như là cách phổ biến nhất để vô tình làm điều này; một cách phổ biến khác là kiểm tra branch-name@{n}, vị trí thứ n trước đó branch-name. Nhưng dù thế nào đi chăng nữa, đến một lúc nào đó cũng phải có một git checkout <rev>. Nếu điều đó không rung chuông, thì có lẽ bạn đã làm những gì Will đã đề cập - đã cố gắng thực hiện git checkout <file>và quản lý để chỉ định sửa đổi một cách tình cờ.
Cascabel

3
Để hoàn tác trạng thái ĐẦU bị tách ra, hãy xem Khắc phục đầu bị tách Git? .

Repo của tôi đã kết thúc trong trạng thái này khi gặp phải xung đột trong khi nổi loạn. May mắn thay, Git đã nói tôi phải làm gì khi tôi chạy git status:all conflicts fixed: run "git rebase --continue"
Paul

2
Cũng xảy ra nếu bạn vô tình gõ git checkout remotes/origin/my-branchthay vì git checkout my-branchhoặc git checkout origin/my-branch.
Adam Libuša

@adam Libusa, Cảm ơn nó đã làm việc cho tôi. Sự khác biệt giữa điều khiển từ xa git / origin / my-Branch và git checkout my-Branch. Có phải nó không giống nhau. nhưng những gì bạn nói đã làm việc cho tôi. Vì tò mò tôi đang hỏi.
karunakar booseyari

Câu trả lời:


281

Bất kỳ kiểm tra nào của một cam kết không phải là tên của một trong các chi nhánh của bạn sẽ giúp bạn có được một ĐẦU tách ra. Một SHA1 đại diện cho đầu của một nhánh vẫn cho một ĐẦU tách ra. Chỉ có một kiểm tra của một tên chi nhánh địa phương tránh chế độ đó.

Xem cam kết với một ĐẦU tách ra

Khi ĐẦU được tách ra, các cam kết hoạt động như bình thường, ngoại trừ không có nhánh nào được đặt tên được cập nhật. (Bạn có thể coi đây là một nhánh ẩn danh.)

văn bản thay thế

Ví dụ: nếu bạn kiểm tra một "chi nhánh từ xa" mà không theo dõi nó trước, bạn có thể kết thúc với một ĐẦU tách rời.

Xem git: chuyển nhánh mà không tách đầu


Với Git 2.23 (tháng 8 năm 2019), bạn không phải sử dụng lệnh khó hiểugit checkout nữa.

git switch cũng có thể kiểm tra một chi nhánh và nhận được một tách rời, ngoại trừ:

  • nó có một --detachtùy chọn rõ ràng

Để kiểm tra cam kết HEAD~3kiểm tra tạm thời hoặc thử nghiệm mà không tạo chi nhánh mới:

git switch --detach HEAD~3
HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
  • nó không thể tách ra do nhầm lẫn một nhánh theo dõi từ xa

Xem:

C:\Users\vonc\arepo>git checkout origin/master
Note: switching to 'origin/master'.

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 switching back to a branch.

Vs sử dụng git switchlệnh mới :

C:\Users\vonc\arepo>git switch origin/master
fatal: a branch is expected, got remote branch 'origin/master'

Nếu bạn muốn tạo một chi nhánh địa phương mới theo dõi một chi nhánh từ xa:

git switch <branch> 

Nếu <branch>không được tìm thấy nhưng có tồn tại một nhánh theo dõi trong chính xác một điều khiển từ xa (gọi nó <remote>) với một tên phù hợp, hãy coi là tương đương với

git switch -c <branch> --track <remote>/<branch>

Không còn sai lầm nữa!
Không còn tách ra không mong muốn ĐẦU!


12
Một cách khác để bạn có thể vào trạng thái đầu tách rời là nếu bạn đang ở giữa một cuộc nổi loạn tương tác và bạn muốn chỉnh sửa một trong các cam kết. Khi Git thả bạn vào cam kết chỉnh sửa, bạn sẽ ở trạng thái đầu tách ra cho đến khi bạn hoàn thành cuộc nổi loạn.

Trong hướng dẫn trực quan này, có lời giải thích này: git commit files creates a new commit containing the contents of the latest commit, plus a snapshot of files taken from the working directory. Additionally, files are copied to the stage."Tập tin được sao chép vào giai đoạn" nghĩa là gì? Tôi nghĩ rằng các tập tin được cam kết, có nghĩa là giai đoạn bị xóa?
tối đa

16
Trên thực tế, bạn sẽ nhận được một ĐẦU tách rời bất cứ khi nào bạn kiểm tra bất kỳ cam kết nào bằng SHA1 của nó, cho dù đó có phải là ở đầu chi nhánh hay không; điều duy nhất bạn có thể kiểm tra mà không bị tách ra là một tên chi nhánh. Ví dụ, mặc dù mastered489trên sơ đồ trên, git checkout ed489sẽ cung cấp cho bạn một ĐẦU tách rời, trong khi git checkout mastersẽ không.
musiphil

8
"You can think of this as an anonymous branch":) Tôi thích sự tương tự
Adrien Be


117

Tôi đã tái tạo điều này ngay bây giờ một cách tình cờ:

  1. liệt kê các chi nhánh từ xa

    git branch -r
          origin/Feature/f1234
          origin/master
    
  2. Tôi muốn kiểm tra một địa phương, vì vậy tôi cắt dán:

    git checkout origin/Feature/f1234
    
  3. Mau! Tách bang

    You are in 'detached HEAD' state. [...])
    

Giải pháp số 1:

Không bao gồm origin/ở phía trước thông số chi nhánh của tôi khi kiểm tra nó:

git checkout Feature/f1234

Giải pháp số 2:

Thêm -btham số tạo chi nhánh cục bộ từ xa

git checkout -b origin/Feature/f1234 hoặc là

git checkout -b Feature/f1234 nó sẽ tự động quay trở lại nguồn gốc


14
Đây gần như là một câu trả lời tuyệt vời, nhưng không giải thích được tại sao bạn rơi vào trạng thái đầu tách ra.
Ngỗng

5
Tôi đồng ý nhưng nó cung cấp giải pháp tôi đang tìm kiếm. Cảm ơn!!
Kilmazed

Tôi thấy trong câu trả lời khác này rằng git checkout -b Feature/f1234<=> git branch Feature/f1234git checkout Feature/f1234.
Armfoot

1
theo mặc định, nó trông có nguồn gốc, vì vậy khi bạn đưa ra origin/branchname, nó sẽ cho origin/origin/branchnamebiết rằng tên đầu tiên là tên từ xa bạn sử dụng -b, nếu bạn không tạo ra một anonymousnhánh tách ra. Tương tự như vậy để kiểm tra từ một điều khiển từ xa khác, bạn sẽ phải đề cập đến -btham số nếu không git không có cách nào để biết nó là từ một điều khiển mới, nó sẽ tìm kiếm origin/remote/branchname.
garg10may

Bạn là một vị thánh!
Harvey Lin

12

thử

git reflog 

điều này cung cấp cho bạn một lịch sử về cách con trỏ và nhánh của bạn di chuyển trong quá khứ.

ví dụ :

88ea06b Head @ {0}: thanh toán: chuyển từ PHÁT TRIỂN sang điều khiển từ xa / nguồn gốc / someNiceFeature e47bf80 Head @ {1}: kéo xuất xứ PHÁT TRIỂN: Chuyển tiếp nhanh

đầu danh sách này là một người có thể gặp phải trạng thái ĐẦU XÁC ĐỊNH ... kiểm tra một nhánh theo dõi từ xa.


7

Nó có thể dễ dàng xảy ra nếu bạn cố gắng hoàn tác các thay đổi bạn đã thực hiện bằng cách kiểm tra lại các tệp và không hoàn toàn hiểu đúng cú pháp.

Bạn có thể nhìn vào đầu ra của git log- bạn có thể dán phần đuôi của nhật ký vào đây kể từ lần cam kết thành công cuối cùng và tất cả chúng ta đều có thể thấy những gì bạn đã làm. Hoặc bạn có thể dán thùng và yêu cầu độc đáo #gittrên IRC freenode.


5

Nó có thể xảy ra nếu bạn có một thẻ có tên giống như một nhánh.

Ví dụ: nếu "phát hành / 0,1" là tên thẻ, thì

git checkout release/0.1

tạo ra tách rời tại "phát hành / 0,1". Nếu bạn mong đợi bản phát hành / 0.1 là tên chi nhánh, thì bạn sẽ bị nhầm lẫn.


1
Đúng. Nhưng làm thế nào để bạn khắc phục điều đó? Làm thế nào để bạn du một kiểm tra của chi nhánh?
Martin

5

Detached HEAD có nghĩa là những gì hiện đang kiểm tra không phải là một chi nhánh địa phương.

Một số tình huống sẽ dẫn đến Detached HEADtrạng thái:

  • Nếu bạn kiểm tra một chi nhánh từ xa , nói origin/master. Đây là một chi nhánh chỉ đọc. Do đó, khi tạo một cam kết từ origin/masternó sẽ được thả nổi tự do , tức là không được kết nối với bất kỳ chi nhánh nào.

  • Nếu bạn kiểm tra một thẻ cụ thể hoặc cam kết . Khi thực hiện một cam kết mới từ đây, nó sẽ lại tự do trôi nổi , tức là không được kết nối với bất kỳ chi nhánh nào. Lưu ý rằng khi một chi nhánh được kiểm tra, các xác nhận mới luôn được đặt tự động ở đầu.

    Khi bạn muốn quay lại và kiểm tra một cam kết hoặc thẻ cụ thể để bắt đầu làm việc từ đó, bạn có thể tạo một nhánh mới có nguồn gốc từ cam kết đó và chuyển sang nó git checkout -b new_branch_name. Điều này sẽ ngăn chặn Detached HEADtrạng thái như bây giờ bạn có một chi nhánh được kiểm tra và không phải là một cam kết.


3

Một cách vô tình đơn giản là làm git checkout headmột lỗi đánh máy HEAD.

Thử cái này:

git init
touch Readme.md
git add Readme.md
git commit
git checkout head

cái nào cho

Note: checking out 'head'.

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.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 9354043... Readme


@VonC: cảm ơn vì liên kết đó. Tôi đang chuẩn bị một khóa đào tạo Git và tôi cũng muốn chỉ ra lý do tại sao đôi khi nó rất khó hiểu. Tôi đã có rất nhiều ví dụ (giống checkout -bnhư thanh toán nhưng thực sự là các chi nhánh) nhưng một danh sách khác chỉ được chào đón.
Thomas Weller

2

Một cách khác để có được trạng thái đầu git tách ra là cố gắng cam kết với một nhánh từ xa. Cái gì đó như:

git fetch
git checkout origin/foo
vi bar
git commit -a -m 'changed bar'

Lưu ý rằng nếu bạn làm điều này, bất kỳ nỗ lực nào khác để kiểm tra nguồn gốc / foo sẽ đưa bạn trở lại trạng thái đầu tách ra!

Giải pháp là tạo chi nhánh foo cục bộ của riêng bạn theo dõi nguồn gốc / foo, sau đó tùy chọn đẩy.

Điều này có lẽ không liên quan gì đến vấn đề ban đầu của bạn, nhưng trang này được đánh giá cao trên google cho "git tách rời" và kịch bản này được ghi chép lại một cách nghiêm túc.


Tình huống này dường như là câu trả lời của Owen ở trên nói về - nơi cắt và dán "origin / foo" khiến git nghĩ về nó như là "origin / origin / foo".
mvanle

1

Khi bạn kiểm tra một cam kết git checkout <commit-hash>hoặc đến một chi nhánh từ xa, ĐẦU của bạn sẽ bị tách ra và cố gắng tạo một cam kết mới trên đó.

Các cam kết không thể truy cập bởi bất kỳ chi nhánh hoặc thẻ nào sẽ là rác được thu thập và xóa khỏi kho sau 30 ngày.

Một cách khác để giải quyết điều này là bằng cách tạo một nhánh mới cho cam kết mới được tạo và kiểm tra nó. git checkout -b <branch-name> <commit-hash>

Bài viết này minh họa cách bạn có thể tách ra trạng thái CHÍNH .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.