Sửa đầu Git tách ra?


1455

Tôi đang thực hiện một số công việc trong kho lưu trữ của mình và nhận thấy một tệp có các thay đổi cục bộ. Tôi không muốn chúng nữa nên tôi xóa tập tin, nghĩ rằng tôi chỉ có thể kiểm tra một bản sao mới. Tôi muốn làm tương đương với Git

svn up .

Sử dụng git pulldường như không hoạt động. Một số tìm kiếm ngẫu nhiên đã dẫn tôi đến một trang web nơi ai đó khuyên bạn nên làm

git checkout HEAD^ src/

( srclà thư mục chứa tập tin bị xóa).

Bây giờ tôi phát hiện ra tôi có một cái đầu tách ra. Tôi không biết đó là cái gì. Làm thế nào tôi có thể hoàn tác?


69
git checkout mastersẽ đưa bạn trở lại trên nhánh chính. Nếu bạn muốn xóa bất kỳ thay đổi bản sao làm việc, có lẽ bạn muốn làm git reset --hard.
Abe Voelker


nếu bạn không cam kết bạn có thể thực hiệngit checkout -- src/
từ

Hãy thử điều này: liên kết . Tóm lạicreate temp branch - checkout temp branch - checkout master - delete temp branch
fidev

@AbeVoelker Ý của bạn là gì trong các bình luận working copy changes? Bạn có đang đề cập đến những thay đổi bạn đã thực hiện đối với các tệp sau khi kiểm tra một cam kết khác (nghĩa là những thay đổi bạn đã thực hiện khi ở trạng thái đầu tách rời)?
Minh Trần

Câu trả lời:


2148

Đầu tách rời có nghĩa là bạn không còn ở trên một nhánh, bạn đã kiểm tra một cam kết duy nhất trong lịch sử (trong trường hợp này là cam kết trước với ĐẦU, tức là ĐẦU ^).

Nếu bạn muốn xóa các thay đổi của mình liên quan đến ĐẦU tách rời

Bạn chỉ cần kiểm tra chi nhánh bạn đang ở, vd

git checkout master

Lần tới khi bạn đã thay đổi một tệp và muốn khôi phục nó về trạng thái trong chỉ mục, đừng xóa tệp trước, chỉ cần làm

git checkout -- path/to/foo

Điều này sẽ khôi phục tập tin foo về trạng thái trong chỉ mục.

Nếu bạn muốn giữ các thay đổi của mình liên quan đến ĐẦU tách rời

  1. Chạy git branch tmp- điều này sẽ lưu các thay đổi của bạn trong một nhánh mới được gọi là tmp.
  2. Chạy git checkout master
  3. Nếu bạn muốn kết hợp các thay đổi bạn đã thực hiện master, hãy chạy git merge tmptừ masterchi nhánh. Bạn nên ở trên masternhánh sau khi chạy git checkout master.

6
"Điều này sẽ khôi phục tập tin foo về trạng thái trước khi bạn thực hiện bất kỳ thay đổi nào đối với nó." -> nó sẽ khôi phục nó về trạng thái trong chỉ mục - vui lòng chỉnh sửa
Mr_and_Mrs_D 18/07/13

88
Tại sao lỗi này xảy ra ở nơi đầu tiên? Đây là một trong những điều tôi ghét git - hành vi hoàn toàn ngẫu nhiên đôi khi. Chưa bao giờ có vấn đề như vậy với Mercurial.
Hươu cao cổ Violet

97
@VioletGiraffe Đây không phải là lỗi cũng không phải là điều gì đó ngẫu nhiên - nó chỉ đơn giản là trạng thái kho lưu trữ của bạn đi vào khi bạn kiểm tra một cam kết trước đó. "Đầu tách rời" đóng vai trò là một cảnh báo mà bạn cũng có thể muốn tạo hoặc trỏ đến một nhánh nếu bạn có ý định thực hiện bất kỳ công việc nào từ thời điểm đó. Nhưng nếu bạn chỉ muốn xem thẻ hoặc cam kết đó, không có gì sai khi ở trong trạng thái đầu tách rời.
Neil Neyman

22
Đừng làm điều này nếu bạn đã cam kết với cái đầu tách ra, xem các câu trả lời khác. Nếu có, bạn có thể kiểm tra đề cập git trước đó trongPrevious HEAD position was 7426948...
KCD

9
@VioletGiraffe: bạn có một mô hình tinh thần về những gì đang xảy ra dựa trên Mercurial, nhưng bạn đang sử dụng Git. Nếu bạn không muốn điều chỉnh mô hình tinh thần của mình để phù hợp với mô hình của Git, thì mọi thứ sẽ tiếp tục xuất hiện ngẫu nhiên. Giống như bạn đang đi dạo bên ngoài với kính VR và bạn nghĩ rằng bạn đang lái máy bay nhưng bạn thực sự băng qua đường. Bạn sẽ bị ô tô đâm.
iconoclast

477

Nếu bạn đã thay đổi các tập tin mà bạn không muốn mất, bạn có thể đẩy chúng. Tôi đã cam kết chúng ở chế độ tách rời và sau đó bạn có thể chuyển sang một nhánh tạm thời để tích hợp sau này trong chủ.

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

Trích từ:

Phải làm gì với cam kết được thực hiện trong một cái đầu tách ra


27
Tôi thấy đây là giải pháp ưa thích - đặc biệt nếu bạn muốn giữ những thay đổi bạn đã thực hiện khi kiểm tra phiên bản riêng lẻ.
quảng cáo

10
@adswebwork: Tôi đồng ý. Tất cả các câu trả lời khác đề nghị quay trở lại trạng thái trước đó và mất các thay đổi được thực hiện cục bộ ở trạng thái đầu tách ra.
Sk8erPeter

6
tại sao không git stash? Vì đó là điều đầu tiên tôi nghĩ đến. tạo ra một nhánh mới sẽ là một quá mức cần thiết.
thesummersign

2
bạn cũng có thể git rebase my-temporary-workvà sau đó xóa chi nhánh git branch -d my-temporary-workđể nó xuất hiện như thể bạn đã cam kết với chi nhánh bên phải ở vị trí đầu tiên.
Zoltán

@geekay git stashcó vẻ như là công cụ hoàn hảo cho trường hợp này. Bạn có thể vui lòng viết một câu trả lời với các bước được đề xuất để đạt được điều đó?
Zoltán

157

Một giải pháp mà không tạo ra một nhánh tạm thời.

Cách thoát (khắc phục lỗi) đã tách trạng thái CHÍNH khi bạn đã thay đổi một cái gì đó trong chế độ này và, tùy ý, muốn lưu các thay đổi của bạn:

  1. Cam kết thay đổi bạn muốn giữ. Nếu bạn muốn tiếp nhận bất kỳ thay đổi nào bạn đã thực hiện ở trạng thái CHÍNH tách rời, hãy cam kết chúng. Giống:

    git commit -a -m "your commit message"
    
  2. Hủy bỏ những thay đổi bạn không muốn giữ. Cài đặt lại cứng sẽ loại bỏ mọi thay đổi không được cam kết mà bạn đã thực hiện ở trạng thái CHÍNH tách rời:

    git reset --hard
    

    (Nếu không có điều này, bước 3 sẽ thất bại, phàn nàn về các tệp không được cam kết đã sửa đổi trong phần ĐẦU tách rời.)

  3. Kiểm tra chi nhánh của bạn. Thoát trạng thái CHÍNH tách ra bằng cách kiểm tra chi nhánh bạn đã làm việc trước đó, ví dụ:

    git checkout master
    
  4. Nhận các cam kết của bạn. Bây giờ bạn có thể đảm nhận các cam kết bạn đã thực hiện ở trạng thái CHÍNH tách ra bằng cách chọn anh đào, như thể hiện trong câu trả lời của tôi cho một câu hỏi khác .

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    

Chính git reset --hardxác là tôi cần, bởi vì tôi muốn thượng nguồn là nguồn và những thay đổi cục bộ nên được loại bỏ.
Markus Zeller

Câu trả lời tuyệt vời, điều này làm việc cho tôi
MGLondon

130

Đầu tách có nghĩa là:

  1. Bạn không còn ở trên một chi nhánh,
  2. Bạn đã kiểm tra một cam kết duy nhất trong lịch sử

Nếu bạn không có thay đổi: bạn có thể chuyển sang chủ bằng cách áp dụng lệnh sau

  git checkout master

Nếu bạn có những thay đổi mà bạn muốn giữ:

Trong trường hợp một ĐẦU tách rời, cam kết hoạt động như bình thường, ngoại trừ không có chi nhánh có tên nào được cập nhật. Để nhận được nhánh chính được cập nhật với các thay đổi đã cam kết của bạn, hãy tạo một nhánh tạm thời ở đó (theo cách này, nhánh tạm thời sẽ có tất cả các thay đổi đã cam kết bạn đã thực hiện trong ĐẦU tách rời), sau đó chuyển sang nhánh chính và hợp nhất nhánh tạm thời với sư phụ.

git branch  temp
git checkout master
git merge temp

2
hoàn hảo, sau đó loại bỏ temp chi nhánh
Davi Menezes

64

Đây là những gì tôi vừa làm sau khi nhận ra mình đang ở trên một cái đầu tách ra và đã thực hiện một số thay đổi.

Tôi đã cam kết những thay đổi.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

Tôi nhớ hàm băm (1fe56ad) của cam kết. Sau đó tôi kiểm tra chi nhánh mà tôi nên có.

$ git checkout master
Switched to branch 'master'

Cuối cùng tôi đã áp dụng những thay đổi của cam kết cho chi nhánh.

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

Tôi nghĩ rằng điều này là một chút dễ dàng hơn so với việc tạo ra một chi nhánh tạm thời.


2
Đây nên là câu trả lời. Nó nhận lại các tập tin nuked của bạn.
BlindWanderer

2
Vâng, đây thực sự là điều đơn giản nhất để làm - đủ đơn giản để nhớ mà không cần tìm kiếm trên web vào lần tiếp theo. Cam kết, ghi chú băm, trở lại chi nhánh mà bạn muốn cam kết và git cherry-pick <hash>.
Mason

Cảm ơn giải pháp. Điều này đã giúp. Tôi cũng có thể nói thêm rằng tôi phải thực hiện một "git đẩy gốc master" để chủ và gốc / chủ của tôi chỉ vào cùng một cam kết.
củ cải424

1
Đây thực chất là câu trả lời của tanius (được đăng hơn một năm trước).
Peter Mortensen

Cảm ơn sự lựa chọn sảng khoái này hoàn nguyên những thay đổi đầu tách cuối cùng
Omega Cube

55

Nếu bạn đã thực hiện một số thay đổi và sau đó nhận ra rằng bạn đang ở trên một đầu tách ra, có một giải pháp đơn giản cho việc đó: stash -> checkout master -> stash pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

Bạn sẽ có những thay đổi không được cam kết và ĐẦU "đính kèm" bình thường, như không có gì xảy ra.


2
Đã đánh dấu cậu bé xấu này - tiết kiệm làm một nhánh tạm thời. Làm việc một điều trị.
Tim Tyler

1
Tôi thường kết thúc ở trạng thái CHÍNH tách ra sau khi kiểm tra một mô hình con git, sau đó thực hiện các thay đổi cho nó. Tôi thấy rằng đây là giải pháp tốt nhất và dễ nhất để sửa chữa mọi thứ để tôi có thể bảo vệ các thay đổi của mình.
dùng5359531

1
Điều này không hoạt động nếu bạn đã cam kết thay đổi trong trạng thái tách rời?
Danijel

40

Khi bạn kiểm tra một cam kết cụ thể git, bạn sẽ ở trạng thái đầu tách ra ... đó là bản sao làm việc của bạn không còn phản ánh trạng thái của một tham chiếu có tên (như "chính chủ"). Điều này hữu ích để kiểm tra trạng thái trong quá khứ của kho lưu trữ, nhưng không phải là điều bạn muốn nếu bạn thực sự đang cố gắng hoàn nguyên các thay đổi.

Nếu bạn đã thực hiện thay đổi đối với một tệp cụ thể và bạn chỉ muốn loại bỏ chúng, bạn có thể sử dụng checkoutlệnh như thế này:

git checkout myfile

Điều này sẽ loại bỏ mọi thay đổi không được cam kết và hoàn nguyên tệp về bất kỳ trạng thái nào nó có trong phần đầu của chi nhánh hiện tại của bạn. Nếu bạn muốn loại bỏ các thay đổi mà bạn đã cam kết, bạn có thể muốn sử dụng resetlệnh. Ví dụ: điều này sẽ đặt lại kho lưu trữ về trạng thái của cam kết trước đó, loại bỏ mọi thay đổi tiếp theo:

git reset --hard HEAD^

Tuy nhiên, nếu bạn đang chia sẻ kho lưu trữ với người khác, thì git resetcó thể gây gián đoạn (vì nó xóa một phần lịch sử kho lưu trữ). Nếu bạn đã chia sẻ các thay đổi với người khác, bạn thường muốn xem xét git revertthay vào đó, điều này tạo ra một "phản đối" - nghĩa là, nó tạo ra một cam kết mới "hoàn tác" các thay đổi trong câu hỏi.

Sách Git có nhiều chi tiết hơn.


1
Như tôi đã nói trong câu trả lời của @ ralphtheninja, git checkout path/to/foocó thể xung đột với git checkout some-branch, vì vậy sẽ tốt hơn nếu sử dụng git checkout -- path/to/foođể tránh những xung đột này.
Diego Lago

30

Đầu nằm trong một con trỏ và kết quả là nó trỏ - trực tiếp hoặc gián tiếp - vào một cam kết cụ thể:

  ĐẦU đính kèm có nghĩa là nó được gắn vào một số nhánh (tức là nó trỏ đến một nhánh).
Tách rời có nghĩa là nó không được gắn vào bất kỳ nhánh nào, tức là nó trỏ trực tiếp đến một số cam kết.

nhập mô tả hình ảnh ở đây

Nói cách khác:

  • Nếu nó trỏ đến một cam kết trực tiếp , thì ĐẦU bị tách ra .
  • Nếu nó trỏ đến một cam kết một cách gián tiếp , (nghĩa là nó trỏ đến một nhánh, đến lượt nó trỏ đến một cam kết), thì ĐẦU được đính kèm .

Để hiểu rõ hơn các tình huống với ĐẦU được đính kèm / tách rời, hãy hiển thị các bước dẫn đến bộ tứ ảnh ở trên.

Chúng tôi bắt đầu với cùng một trạng thái của kho lưu trữ (hình ảnh trong tất cả các góc phần tư là như nhau):

nhập mô tả hình ảnh ở đây


Bây giờ chúng tôi muốn thực hiện git checkout- với mục tiêu khác nhau trong những hình ảnh cá nhân (lệnh trên đầu trang của họ đang mờ để nhấn mạnh rằng chúng tôi chỉ sẽ áp dụng những lệnh):

nhập mô tả hình ảnh ở đây


Đây là tình huống sau khi thực hiện các lệnh đó:

nhập mô tả hình ảnh ở đây

Như bạn có thể thấy, HEAD chỉ đến mục tiêu của git checkoutlệnh - tới một nhánh (3 hình ảnh đầu tiên của bộ tứ) hoặc (trực tiếp) đến một cam kết (hình ảnh cuối cùng của bộ tứ).

Nội dung của thư mục làm việc cũng được thay đổi, phù hợp với cam kết thích hợp (ảnh chụp nhanh), tức là với cam kết được chỉ ra (trực tiếp hoặc gián tiếp) bởi CHÍNH.


Vì vậy, bây giờ chúng ta đang ở trong tình huống tương tự như khi bắt đầu câu trả lời này:

nhập mô tả hình ảnh ở đây


6
Không đọc nó, nhưng đã bình chọn cho những bức ảnh đẹp mà bạn thực hiện;).
Carlo Wood

@Carlo, cảm ơn!
MaryD

22

Vì "trạng thái đầu tách rời" có bạn trên một nhánh tạm thời, chỉ cần sử dụng git checkout -nó sẽ đưa bạn vào nhánh cuối cùng mà bạn đang ở.


1
hãy cẩn thận, bạn sẽ mất bất kỳ cam kết nào bạn đã thực hiện khi bạn ở trạng thái đầu tách ra.
Ajak6

@ Ajak6 Bạn không thực sự mất những cam kết đó. Chúng vẫn có sẵn thông qua git reflogvà có thể được đưa vào một chi nhánh mới hoặc thông qua git cherry-pickmột chi nhánh hiện có. Xem câu hỏi này .
tanius

7

Để làm rõ hơn câu trả lời của @Philippe Gerber, đây là:

git cherry-pick

Trước đây cherry-pick, a git checkout masterlà cần thiết trong trường hợp này. Hơn nữa, nó chỉ cần thiết với một committrong detached head.


6

Phụ lục

Nếu chi nhánh mà bạn muốn trả lại là lần thanh toán cuối cùng mà bạn đã thực hiện, bạn chỉ cần sử dụng checkout @{-1}. Điều này sẽ đưa bạn trở lại kiểm tra trước đây của bạn.

Hơn nữa, bạn có thể đặt bí danh cho lệnh này, ví dụ, git global --config alias.prevđể bạn chỉ cần gõ git prevđể chuyển trở lại kiểm tra trước đó.


4

Ở trong "đầu tách rời" có nghĩa là ĐẦU đề cập đến một cam kết không tên cụ thể (ngược lại với một nhánh được đặt tên) (cf: https://git-scm.com/docs/git-checkout phần Đầu tách rời )

Để khắc phục sự cố, bạn chỉ cần chọn nhánh được chọn trước đó bởi

git checkout @{-1}


2

Khi bạn ở trong tình huống tách rời và tạo các tệp mới, trước tiên hãy đảm bảo rằng các tệp mới này được thêm vào chỉ mục, ví dụ như:

git add .

Nhưng nếu bạn chỉ thay đổi hoặc xóa các tệp hiện có, bạn có thể thêm (-a) và cam kết với một tin nhắn (-m) cùng một lúc thông qua:

git commit -a -m "my adjustment message"

Sau đó, bạn có thể chỉ cần tạo một nhánh mới với trạng thái hiện tại của bạn với:

git checkout -b new_branch_name

Bạn sẽ có một chi nhánh mới và tất cả các điều chỉnh của bạn sẽ ở đó trong chi nhánh mới đó. Sau đó, bạn có thể tiếp tục đẩy đến điều khiển từ xa và / hoặc thanh toán / kéo / hợp nhất nếu muốn.


1

Git nói với tôi làm thế nào để làm điều đó.

nếu bạn gõ:

git checkout <some-commit_number>

Lưu trạng thái

git add .
git commit -m "some message"

Sau đó:

 git push origin HEAD:<name-of-remote-branch>

1

Tôi muốn giữ những thay đổi của mình vì vậy, tôi chỉ sửa lỗi này ...

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

công việc đó cho tôi


1

Thông thường HEADchỉ vào một nhánh. Khi nó không trỏ đến một nhánh thay vào đó khi nó trỏ đến một hàm băm cam kết giống như 69e51nó có nghĩa là bạn có một ĐẦU tách rời. Bạn cần chỉ cho nó hai nhánh để khắc phục sự cố. Bạn có thể làm hai điều để sửa nó.

  1. git checkout other_branch // Không thể khi bạn cần mã trong cam kết đó hash
  2. tạo một nhánh mới và trỏ băm xác nhận vào nhánh vừa tạo.

Đầu phải chỉ vào một nhánh, không băm cam kết là quy tắc vàng.


đây là lý do tại sao tôi có lỗi này Tôi đã kiểm tra bản sửa đổi và sau đó kiểm tra lại bản sửa đổi hiện tại / mới nhất thay vì kiểm tra chi nhánh, cái mà sẽ gắn cái đầu đúng cách. Cảm ơn đã giúp đỡ.
Rahul Thakur

1

Đầu tách ra có nghĩa là bạn chưa kiểm tra chi nhánh của mình đúng cách hoặc bạn vừa kiểm tra một cam kết duy nhất.

Nếu bạn gặp phải một vấn đề như vậy thì trước tiên stash thay đổi địa phương của bạn để bạn sẽ không bị mất những thay đổi của bạn.

Sau đó ... kiểm tra chi nhánh bạn muốn bằng lệnh:

Giả sử bạn muốn chi nhánh MyOrigenBranch:

kiểm tra git -b someName origin / MyOrigenBranch


1

bạn có thể đã làm git reset --hard origin/your-branch.

Cố gắng chỉ git checkout your-branch


0
git pull origin master

đã làm cho tôi. Nó chỉ là về việc đưa ra tên từ xa và chi nhánh rõ ràng.


0

Trong trường hợp của tôi, tôi chạy git statusvà tôi thấy rằng tôi có một vài tệp không bị theo dõi trong thư mục làm việc của tôi.

Tôi chỉ cần làm sạch chúng (vì tôi không cần chúng) để chạy rebase mà tôi muốn thực hiện.


0

Điều này làm việc cho tôi, Nó sẽ chỉ định một chi nhánh mới cho đầu tách ra:

kiểm tra git new_branch_name detached_head_garbage_name


0

Đầu tách rời có nghĩa là bạn hiện không ở bất kỳ chi nhánh nào. Nếu bạn muốn GIỮ những thay đổi hiện tại của mình và chỉ cần tạo một chi nhánh mới, đây là những gì bạn làm:

git commit -m "your commit message"
git checkout -b new_branch

Sau đó, bạn có khả năng muốn hợp nhất chi nhánh mới này với các chi nhánh khác. Luôn luôn hữu ích là lệnh git "a dog" :

git log --all --decorate --oneline --graph
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.