질문자 :Ben Zotto
저는 Git의 분기 복잡성을 처음 접했습니다. 저는 항상 단일 지점에서 작업하고 변경 사항을 커밋한 다음 주기적으로 원격 원본으로 푸시합니다.
최근 어딘가에서 커밋 스테이징에서 벗어나기 위해 일부 파일을 재설정했으며 나중에 최근 몇 가지 로컬 커밋을 제거하기 위해 rebase -i
지금은 도저히 이해할 수 없는 상황입니다.
내 작업 영역에서 git log
는 내가 기대했던 것과 정확히 일치하는지 보여줍니다. 나는 가고 싶지 않은 커밋과 새로운 커밋 등으로 올바른 기차를 타고 있습니다.
하지만 방금 원격 리포지토리로 푸시했는데 다른 점이 있습니다. rebase에서 죽인 커밋 몇 개는 푸시되고 로컬에서 커밋된 새 커밋은 거기에 없습니다.
"마스터/원본"이 HEAD에서 분리되어 있다고 생각하지만 이것이 의미하는 바, 명령줄 도구로 시각화하는 방법 및 수정 방법에 대해 100% 명확하지 않습니다.
먼저 HEAD가 무엇이며 분리되었을 때의 의미를 명확히 합시다.
HEAD는 현재 체크아웃된 커밋의 기호 이름입니다. HEAD가 분리되지 않은 경우("정상적인" 1 상황: 분기가 체크아웃됨) HEAD는 실제로 분기의 "ref"를 가리키고 분기는 커밋을 가리킵니다. 따라서 HEAD는 분기에 "연결"됩니다. 새 커밋을 만들면 HEAD가 가리키는 분기가 새 커밋을 가리키도록 업데이트됩니다. HEAD는 분기를 가리키기 때문에 자동으로 따릅니다.
-
git symbolic-ref HEAD
refs/heads/master
"master"라는 브랜치가 체크아웃되었습니다. -
git rev-parse refs/heads/master
yield 17a02998078923f2d62811326d130de991d1a95a
그 커밋은 마스터 브랜치의 현재 팁 또는 "헤드"입니다. -
git rev-parse HEAD
는 또한 17a02998078923f2d62811326d130de991d1a95a
이것이 "상징적 참조"가 의미하는 것입니다. 다른 참조를 통해 개체를 가리킵니다.
(심볼릭 참조는 원래 심볼릭 링크로 구현되었지만 나중에 심볼릭 링크가 없는 플랫폼에서 사용할 수 있도록 추가 해석이 포함된 일반 파일로 변경되었습니다.)
HEAD
→ refs/heads/master
→ 17a02998078923f2d62811326d130de991d1a95a
HEAD가 분리되면 분기를 통해 간접적으로 가리키는 대신 커밋을 직접 가리킵니다. 분리된 HEAD는 명명되지 않은 분기에 있는 것으로 생각할 수 있습니다.
-
git symbolic-ref HEAD
는 치명적으로 실패합니다 fatal: ref HEAD is not a symbolic ref
-
git rev-parse HEAD
17a02998078923f2d62811326d130de991d1a95a
산출합니다.
심볼릭 ref가 아니므로 커밋 자체를 직접 가리켜야 합니다.
우리는 HEAD
→ 17a02998078923f2d62811326d130de991d1a95a
분리된 HEAD로 기억해야 할 중요한 점은 그것이 가리키는 커밋이 달리 참조되지 않는 경우(다른 참조가 도달할 수 없음) 다른 커밋을 체크아웃할 때 "dangling"이 된다는 것입니다. 결국 이러한 댕글링 커밋은 가비지 컬렉션 프로세스를 통해 제거됩니다(기본적으로 최소 2주 동안 보관되며 HEAD의 reflog에서 참조하여 더 오래 보관될 수 있음).
1 분리된 HEAD로 "정상적인" 작업을 수행하는 것은 완벽하게 괜찮습니다. reflog에서 삭제된 기록을 제거하지 않으려면 수행 중인 작업을 추적하기만 하면 됩니다.
대화형 리베이스의 중간 단계는 분리된 HEAD로 수행됩니다(부분적으로 활성 분기의 reflog를 오염시키는 것을 방지하기 위해). 전체 리베이스 작업을 완료하면 리베이스 작업의 누적 결과로 원래 분기를 업데이트하고 HEAD를 원래 분기에 다시 연결합니다. 제 생각에는 리베이스 프로세스를 완전히 완료한 적이 없습니다. 이렇게 하면 rebase 작업에 의해 가장 최근에 처리된 커밋을 가리키는 분리된 HEAD가 남게 됩니다.
상황에서 복구하려면 분리된 HEAD가 현재 가리키는 커밋을 가리키는 분기를 만들어야 합니다.
git branch temp git checkout temp
(이 두 명령은 git checkout -b temp
로 축약될 수 있음)
이렇게 하면 HEAD가 새 temp
분기에 다시 연결됩니다.
다음으로 현재 커밋(및 해당 기록)을 작업할 것으로 예상했던 일반 분기와 비교해야 합니다.
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp git diff master temp git diff origin/master temp
(로그 옵션을 실험해보고 싶을 것입니다: add -p
, --pretty=…
를 생략하여 전체 로그 메시지를 보는 등)
새 temp
분기가 좋아 master
를 업데이트(예:)하여 가리키도록 할 수 있습니다.
git branch -f master temp git checkout master
(이 두 명령은 약어로 git checkout -B master temp
)
그런 다음 임시 분기를 삭제할 수 있습니다.
git branch -d temp
마지막으로 재설정된 기록을 푸시하고 싶을 것입니다.
git push origin master
--force
를 추가해야 할 수 있습니다(즉, 일부 기존 커밋을 삭제하거나 다시 작성했거나, 그렇지 않으면 일부 기록을 다시 작성했습니다). ).
리베이스 작업 중이었다면 아마도 정리해야 할 것입니다. .git/rebase-merge/
디렉토리를 찾아 리베이스가 진행 중인지 확인할 수 있습니다. 해당 디렉토리를 삭제하여 진행 중인 rebase를 수동으로 정리할 수 있습니다(예: 활성 rebase 작업의 목적과 컨텍스트가 더 이상 기억나지 않는 경우). 일반적으로 git rebase --abort
를 사용하지만 피하고 싶은 추가 재설정을 수행합니다(HEAD를 원래 분기로 다시 이동하고 다시 원래 커밋으로 재설정하여 위에서 수행한 작업 중 일부를 취소합니다. ).
Chris Johnsen다음과 같이 하십시오.
git checkout master
또는 유지하려는 변경 사항이 있는 경우 다음을 수행합니다.
git checkout -b temp git checkout -B master temp
Daniel Alexiuc나는이 문제에 부딪쳤고 최고 투표 답변을 읽었을 때 :
HEAD는 현재 체크아웃된 커밋의 기호 이름입니다.
나는 생각했다: 아하! 경우 HEAD
currenlty의 기호 이름 커밋 체크 아웃, 난에 대해 그것을 조정할 수 있습니다 master
에 대해 그것을 리베이스에 의해 master
:
git rebase HEAD master
이 명령:
- 체크 아웃
master
-
HEAD
master
에서 분기된 지점까지 HEAD
의 상위 커밋을 식별합니다. -
master
위에서 해당 커밋을 재생합니다.
그 결과에 있던 모든 커밋이다 HEAD
하지만 master
도 다음입니다 master
. master
는 체크 아웃된 상태로 유지됩니다.
리모컨에 관하여:
rebase에서 내가 죽인 커밋 몇 개는 푸시되었고 로컬에서 커밋된 새 커밋은 거기에 없습니다.
원격 기록은 더 이상 로컬 기록을 사용하여 빨리 감기할 수 없습니다. 원격 기록을 덮어쓰려면 강제로 푸시( git push -f
공동 작업자가 있는 경우 일반적으로 모든 사람이 같은 페이지에 있도록 이를 조정하는 것이 좋습니다.
당신이 밀어 후 master
원격으로 origin
, 원격 추적 브랜치 origin/master
같은 가리 키도록 업데이트로 투입 될 것입니다 master
.
Dmitry Minkovsky분리된 헤드에 대한 기본 설명은 여기를 참조하십시오.
http://git-scm.com/docs/git-checkout
시각화하는 명령줄:
git branch
또는
git branch -a
아래와 같이 출력됩니다.
* (no branch) master branch1
* (no branch)
는 분리된 헤드에 있음을 나타냅니다.
git checkout somecommit
등을 수행하여 이 상태에 도달할 수 있으며 다음과 같이 경고했을 것입니다.
당신은 '분리된 HEAD' 상태에 있습니다. 둘러보고 실험적 변경을 수행하고 커밋할 수 있으며 다른 체크아웃을 수행하여 분기에 영향을 주지 않고 이 상태에서 수행한 커밋을 삭제할 수 있습니다.
생성한 커밋을 유지하기 위해 새 분기를 생성하려는 경우 체크아웃 명령과 함께 -b를 다시 사용하여 (지금 또는 나중에) 그렇게 할 수 있습니다. 예시:
자식 체크 아웃 -b new_branch_name
이제 마스터로 가져 오려면 다음을 수행하십시오.
git reflog
또는 git log
하고 커밋을 기록하십시오. 이제 git checkout master
와 git merge
이 커밋을 병합합니다.
git merge HEAD@{1}
편집하다:
추가하려면 git rebase -i
필요하지 않은 커밋을 삭제/종료할 때뿐만 아니라 편집할 때도 사용합니다. 커밋 목록에서 "편집"을 언급하기만 하면 커밋을 수정할 수 있고 git rebase --continue
를 실행하여 계속 진행할 수 있습니다. 이렇게 하면 분리된 HEAD에 들어오지 않을 것입니다.
manojlds자체 분기에 분리된 커밋 가져오기
git checkout -b mynewbranch
실행하기만 하면 됩니다.
그런 다음 git log
실행하면 커밋이 이제 이 새 분기에서 HEAD
Rose PerroneYou are in 'detached HEAD' state.
검색할 때 이 질문을 찾았습니다.
내가 여기까지 오기 위해 한 일을 과거에 했던 일과 비교하여 분석한 결과, 내가 실수를 저질렀다는 것을 알게 되었습니다.
내 정상적인 흐름은 다음과 같습니다.
git checkout master git fetch git checkout my-cool-branch git pull
이번에는 다음과 같이 했습니다.
git checkout master git fetch git checkout origin/my-cool-branch # You are in 'detached HEAD' state.
문제는 내가 실수로 다음과 같이 했다는 것입니다.
git checkout origin/my-cool-branch
대신:
git checkout my-cool-branch
(내 상황에서) 수정 사항은 단순히 위의 명령을 실행한 다음 흐름을 계속하는 것이었습니다.
git checkout my-cool-branch git pull
user664833현재 분리된 HEAD를 푸시하려면( git log
확인) 다음을 시도하세요.
git push origin HEAD:master
분리된 HEAD를 원점의 마스터 브랜치로 보냅니다. 푸시가 거부되면 git pull origin master
시도하여 원본에서 변경 사항을 가져옵니다. 의도적인 rebase를 수행했고 현재 분리된 분기로 origin/master를 교체하기를 원하기 때문에 원점의 변경 사항에 신경 쓰지 않고 거부된 경우 강제할 수 있습니다( -f
). 이전 커밋에 대한 액세스 권한을 상실한 경우 항상 git reflog
를 실행하여 모든 분기의 기록을 볼 수 있습니다.
변경 사항을 유지하면서 마스터 분기로 돌아가려면 다음 명령을 시도하십시오.
git rebase HEAD master git checkout master
참조: Git: "현재 분기에 없습니다." 변경 사항을 유지하면서 지점으로 쉽게 돌아갈 수 있는 방법이 있습니까?
kenorb마스터 브랜치가 있고 "개발"이나 기능으로 돌아가고 싶다면 다음을 수행하십시오.
git checkout origin/develop
참고: origin/develop 을 확인하세요.
당신은 분리된 HEAD 상태에 있습니다. 둘러보고 실험적인 변경을 수행하고 커밋할 수 있으며 다른 체크아웃을 수행하여 분기에 영향을 미치지 않고 이 상태에서 수행한 커밋을 삭제할 수 있습니다...
그 다음에
git checkout -b develop
효과가있다 :)
amdev다음은 나를 위해 일했습니다 (분기 마스터 만 사용).
git push origin HEAD:master git checkout master git pull
첫 번째는 분리된 HEAD를 원격 원점으로 푸시합니다.
두 번째는 브랜치 마스터로 이동합니다.
세 번째는 브랜치 마스터에 연결된 HEAD를 복구합니다.
푸시가 거부되면 첫 번째 명령에서 문제가 발생할 수 있습니다. 그러나 이것은 더 이상 detached head의 문제가 아니라 detached HEAD가 일부 원격 변경 사항을 인식하지 못한다는 사실에 관한 것입니다.
Daniel Porumbel오늘 방금 이 문제에 부딪쳤고 다음을 수행하여 문제를 해결했다고 확신합니다.
git branch temp git checkout master git merge temp
이 작업을 수행하는 방법을 알아냈을 때 회사 컴퓨터를 사용하고 있었는데 이제 개인용 컴퓨터에서도 동일한 문제가 발생합니다. 그래서 내가 정확히 어떻게 했는지 보기 위해 직장 컴퓨터로 돌아올 때 월요일까지 기다려야 할 것입니다.
adamwineguyHEAD가 양호한 상태라고 완전히 확신하는 경우:
git branch -f master HEAD git checkout master
마스터가 원점에서 분기했기 때문에 원점으로 푸시할 수 없습니다. 다른 사람이 repo를 사용하고 있지 않다고 확신하는 경우 다음과 같이 강제 푸시할 수 있습니다.
git push -f
다른 사람이 사용하지 않는 기능 분기에 있는 경우 가장 유용합니다.
geon'git checkout [branch-name]'만 하면 됩니다. 여기서 [branch-name]은 분리된 헤드 상태가 된 원래 분기의 이름입니다. (asdfasdf에서 분리됨)이 사라집니다.
예를 들어 'dev' 브랜치에서 asdfasd14314 커밋을 체크아웃합니다. ->
'git checkout asdfasd14314'
당신은 지금 분리된 머리 상태에 있습니다
'git branch'는 다음과 같이 나열됩니다. ->
* (detached from asdfasdf) dev prod stage
그러나 분리된 헤드 상태에서 벗어나 dev로 돌아가려면 ->
'git checkout dev'
그러면 'git branch'가 나열됩니다 ->
* dev prod stage
그러나 그것은 물론 분리 된 헤드 상태에서 변경 사항을 유지할 의도가 없지만 변경하려는 의도가 아니라 이전 커밋을보기 위해이 작업을 많이 수행하는 경우입니다.
Adam FreemanChris가 지적한 것처럼 나는 다음과 같은 상황을 겪었습니다.
git symbolic-ref HEAD
는 치명적으로 실패합니다 fatal: ref HEAD is not a symbolic ref
그러나 git rev-parse refs/heads/master
는 내가 복구할 수 있는 좋은 커밋을 가리키고 있었습니다(제 경우에는 마지막 커밋이고 git show [SHA]
그 후로 난잡한 짓을 많이 했지만, 고쳐진 것 같던 것은,
git symbolic-ref HEAD refs/heads/master
그리고 헤드가 다시 부착됩니다!
Varun Garggit checkout origin/master
대신
그냥 git checkout master
그런 다음 git branch
가 분기를 확인합니다.
Goran Ch.나는 같은 문제가 있었고 다음 단계를 통해 해결했습니다.
변경 사항을 유지해야 하는 경우
- 먼저 마스터 브랜치로 돌아가려면
git checkout master
명령을 실행해야 합니다. - 변경 사항을 유지해야 하는 경우
git checkout -b changes
및 git checkout -B master changes
변경 사항이 필요하지 않은 경우
브랜치에서 추적되지 않은 모든 파일을 제거하려면 git clean -df
실행하십시오.
그런 다음 리포지토리 내에서 준비되지 않은 모든 변경 사항을 지워야 합니다. git checkout --
을 실행해야 합니다.
git checkout master
명령을 사용하여 분기를 마스터 분기에 다시 넣어야 합니다.
Aravinda Meewalaarachchi푸시하고 싶은 로컬 커밋이 없었기 때문에 로컬 브랜치를 다시 삭제하는 것만큼 쉬웠습니다.
그래서 나는 했다:
git branch -d branchname
그런 다음 분기를 다시 확인합니다.
git checkout branchname
Klaus당신은 마스터의 상단에 약간의 커밋을했고, "뒤로 병합"에 불과합니다 master
(즉, 당신이 원하는이 master
를 차례로 HEAD
)의 한 줄은 다음과 같습니다
git checkout -B master HEAD
- 이미 존재하더라도
master
라는 새 분기를 만듭니다 master
움직이는 것과 같으며 이것이 우리가 원하는 것입니다). - 새로 생성된 분기는 현재 있는
HEAD
를 가리키도록 설정됩니다. - 새 분기가 체크 아웃되었으므로
master
에 있습니다.
나는 이것이 종종 분리된 상태에 있는 하위 리포지토리의 경우에 특히 유용하다는 것을 알았습니다.
quazgar오늘이 문제가 발생했습니다. 여기에서 하위 모듈을 업데이트했지만 어떤 지점에도 없었습니다. 나는 이미 커밋했기 때문에 stash, checkout, unstashing이 작동하지 않습니다. 나는 분리 된 헤드의 커밋을 체리 피킹했습니다. 그래서 커밋 직후(푸시가 실패했을 때) 다음을 수행했습니다.
git checkout master git cherry-pick 99fe23ab
내 생각은 갔다 : 나는 머리가 분리되어 있지만 마스터가되고 싶습니다. 내 detached 상태가 마스터와 크게 다르지 않다고 가정하고 내 커밋을 마스터에 적용할 수 있다면 설정하겠습니다. 이것이 바로 체리픽이 하는 일입니다.
prewettmaster
아닌 상태에서 일부 변경을 수행한 것으로 판명된 상황에서 개인적으로 자신을 발견할 때(즉, HEAD
master
바로 위에 분리되어 있고 그 사이에 커밋이 없음) 숨김이 도움이 될 수 있습니다.
git stash # HEAD has same content as master, but we are still not in master git checkout master # switch to master, okay because no changes and master git stash apply # apply changes we had between HEAD and master in the first place
Ben Usman간단히 말해서, 분리된 HEAD 상태는 분기의 HEAD(또는 팁)로 체크아웃되지 않았음을 의미합니다.
예를 들어 이해
대부분의 경우 분기는 다음과 같은 여러 커밋의 시퀀스입니다.
커밋 1: master-->branch_HEAD(123be6a76168aca712aea16076e971c23835f8ca)
커밋 2: master-->123be6a76168aca712aea16076e971c23835f8ca-->branch_HEAD(100644a76168aca712aea16076e971c23835f8ca)
커밋 시퀀스의 경우 위에서 볼 수 있듯이 분기는 최신 커밋을 가리킵니다. 그래서 당신은 123be6a76168aca712aea16076e971c23835f8ca 를 커밋하기 위해 체크 아웃하면 분기의 HEAD가 100644a76168aca712aea16076e971c238 을 가리키고 기술적으로 체크 아웃되기 때문에 분리 된 헤드 상태가됩니다. 따라서, 당신은 분리된 HEAD 상태에 있습니다.
이론적 설명
이 블로그에서는 Git 리포지토리가 커밋 트리이며 각 커밋 포인터가 업데이트되고 각 브랜치에 대한 이러한 포인터가 .git/refs 하위 디렉토리에 저장되어 있는 조상을 가리키는 각 커밋이 있음을 분명히 밝혔습니다. 태그는 .git/refs/tags에 저장되고 분기는 .git/refs/heads에 저장됩니다. 파일 중 하나를 보면 각 태그가 40자 커밋 해시가 있는 단일 파일에 해당하고 위에서 @Chris Johnsen과 @Yaroslav Nikitenko가 설명한 대로 이러한 참조를 확인할 수 있습니다.
Keshav나는 정말 어리석은 상태에 빠졌습니다. 다른 사람이 이것을 유용하게 사용할지 의심 스럽습니다. 그러나 만일을 대비하여
git ls-remote origin 0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b HEAD 6f96ad0f97ee832ee16007d865aac9af847c1ef6 refs/heads/HEAD 0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b refs/heads/master
내가 결국 고친
git push origin :HEAD
KCD이것은 나를 위해 완벽하게 작동했습니다.
1. git stash
를 사용하여 로컬 수정 사항 저장
변경 사항을 취소하려면
git clean -df
git checkout -- .
git clean은 추적되지 않은 모든 파일을 제거하고(경고: .gitignore에 직접 언급된 무시된 파일은 삭제하지 않지만 폴더에 있는 무시된 파일은 삭제할 수 있음) git checkout은 준비되지 않은 모든 변경 사항을 지웁니다.
2. git checkout master
메인 브랜치로 전환 (마스터를 사용한다고 가정)
3. 마스터 브랜치에서 마지막 커밋을 가져 git pull
4. 모든 것이 잘 보이는지 확인하기 위한 git status
On branch master Your branch is up-to-date with 'origin/master'.
jmojico제 경우에는 git status
실행했는데 작업 디렉토리에 추적되지 않은 파일이 몇 개 있다는 것을 알았습니다.
rebase가 작동하도록 하려면 청소해야 했습니다(필요하지 않았기 때문에).
falsarellaEclipse에서 EGit 을 사용하는 경우: 마스터가 주요 개발 분기라고 가정합니다.
- 일반적으로 새 분기에 대한 변경 사항을 커밋합니다.
- 그런 다음 원격에서 당겨
- 그런 다음 프로젝트 노드를 마우스 오른쪽 버튼으로 클릭하고 팀을 선택한 다음 기록 표시를 선택합니다.
- 그런 다음 마스터를 마우스 오른쪽 버튼으로 클릭하고 체크 아웃을 선택하십시오.
- Eclipse가 알려주면 두 개의 마스터가 하나는 로컬 하나는 원격이고 원격을 선택하십시오.
그런 다음 원본 마스터에 다시 연결할 수 있어야 합니다.
Junchen Liu나는 같은 문제가 있었다. git stash
변경 사항을 숨기고 로컬의 분기를 이전 커밋으로 하드 재설정한 다음(이로 인해 발생한 것으로 생각했습니다) git pull
을 수행했는데 지금은 해당 헤드가 분리되지 않습니다. 변경 사항을 다시 git stash apply
잊지 마십시오.
SamLgit checkout checksum # You could use this to peek previous checkpoints git status # You will see HEAD detached at checksum git checkout master # This moves HEAD to master branch
David Yang출처 : http:www.stackoverflow.com/questions/5772192/how-can-i-reconcile-detached-head-with-master-origin