HEAD를 이전 위치로 다시 옮기려면 어떻게해야합니까? (분리 된 머리) & 커밋 취소


179

Git에서는 squash commit다른 지점에서 병합 한 다음 다음 HEAD을 통해 이전 장소 로 재설정 하여 a 를 하려고했습니다 .

git reset origin/master

그러나 나는 이것을 벗어나야합니다. HEAD를 이전 위치로 다시 옮길 수 있습니까?

23b6772이동해야 할 커밋 의 SHA-1 조각 ( )이 있습니다. 이 커밋으로 돌아가려면 어떻게해야합니까?


12
HEAD는 현재 위치에 대한 포인터 일뿐입니다. git checkout 23b6772해야 할 것.
Yaroslav 관리자


1
아니 @YaroslavAdmin 그것은해야 하지 . A는 직접 커밋을 체크 아웃하는 것입니다 강령술 미안, (원격 추적 브랜치 스스로 체크 아웃 자동으로 연기 (가) 영업 이익이 그랬던 것처럼 그들은 당신이 그렇게 할 때를 가리 저지 할 수 없기 때문에) 또한 이유 분리 HEAD 상태가 발생 코멘트 :-) 나는 초기 문제가 이미 해결 되기를 바랍니다 ...
RomainValeri

답변:


397

대답하기 전에 배경을 추가하여 이것이 무엇인지 설명해 봅시다 HEAD.

First of all what is HEAD?

HEAD단순히 현재 분기의 현재 커밋 (최신)에 대한 참조입니다. 주어진 시간에
하나만있을 수 있습니다 HEAD(제외 git worktree).

내용은 HEAD내부에 저장 .git/HEAD되며 현재 커밋의 40 바이트 SHA-1을 포함합니다.


detached HEAD

HEAD히스토리에서 이전 커밋을 가리키는 최신 커밋-의미가 아닌 경우 호출 detached HEAD됩니다.

여기에 이미지 설명을 입력하십시오

명령 행에서 분기 이름 대신 SHA-1은 다음과 같습니다 HEAD. 현재 분기의 끝을 가리 키지 않기 때문 입니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


분리 된 HEAD에서 복구하는 방법에 대한 몇 가지 옵션 :


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

원하는 커밋을 가리키는 새 분기를 체크 아웃합니다.
이 명령은 주어진 커밋을 체크 아웃합니다.
이 시점에서 지점을 만들고이 시점부터 작업을 시작할 수 있습니다.

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

당신은 항상 사용할 수 있습니다 reflog.
git reflog 변경 사항을 표시 HEAD하고 원하는 참조 로그 항목을 체크 아웃하면 HEAD이 커밋으로 돌아갑니다.

HEAD가 수정 될 때마다 reflog

git reflog
git checkout HEAD@{...}

원하는 커밋으로 돌아갑니다.

여기에 이미지 설명을 입력하십시오


git reset --hard <commit_id>

HEAD를 원하는 커밋으로 "이동"하십시오.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • 참고 : ( Git 2.7 이후 )도 사용할 수 있습니다 git rebase --no-autostash.

git revert <sha-1>

지정된 커밋 또는 커밋 범위를 "실행 취소"합니다.
reset 명령은 지정된 커밋에서 변경 한 내용을 "실행 취소"합니다.
실행 취소 패치가 포함 된 새 커밋이 커밋되고 원래 커밋도 기록에 남아 있습니다.

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

이 스키마는 어떤 명령이 무엇을 수행하는지 보여줍니다.
보시 reset && checkout다시피을 수정하십시오 HEAD.

여기에 이미지 설명을 입력하십시오


최신 커밋에 있지 않은 경우-히스토리의 이전 커밋이 다른 분기의 팁이 아닌 한 HEAD가 히스토리에서 이전 커밋을 가리키고 있음을 의미합니다 . 내 경험상 HEAD가 어떤 지점에서 가리키는 커밋을 가리 키지 않으면 분리되었다고 말할 수 있습니다. 태그에는 적용되지 않습니다.
Tim

분리 된 HEAD에있을 수 있으며 동시에이 분기의 HEAD와 동일한 커미트가있는 분기가 있습니다. 난 당신의 의견을 이해하지 못합니다
CodeWizard

3
제목에 인라인 코드 마크 업을 사용하는 데 문제가 있습니다. :)
jub0bs

그것을 강조하는 더 좋은 방법을 찾지 못했습니다. 자유롭게 편집하십시오. 당신은 환영 이상입니다
CodeWizard

22

하다

git reset 23b6772

올바른 위치에 있는지 확인하려면

git status

당신은 뭔가를 볼 수 있습니다

지점 마스터 지점은 17 개의 커밋으로 '원점 / 마스터'뒤에 있으며 빨리 감을 수 있습니다.

그런 다음 리모컨의 기록을 다시 작성하여 변경 사항을 반영하십시오.

git push --force-with-lease // a useful command @oktober mentions in comments

1
을 (를) 초과하여 조심하십시오 git push --force. 많은 상황에서 그것은 당신을 잠시 동안 팀에서 가장 인기있는 사람으로 만들 것입니다 ....
Kay V

위의 메모에 추가하기 위해 about.gitlab.com/blog/2014/11/26/keeping-your-code-protected 에서이 인용문을 보았습니다 . "단일 git push --force 명령 "186 Jenkins] 리포지토리는 브랜치 헤드가 이전 커밋을 가리 키도록 되 감았으며 실제로 새로운 커밋은 잘못된 git-push 후에 잘못 배치되었습니다." -매우 인기없는 개발자 ....
Kay V

2
한 번 봐 걸릴 @KayV git push --force-with-lease(Thoughtbot 기사 : thoughtbot.com/blog/git-push-force-with-lease를 )
옥토 페스트

1
유용한 플래그, @oktober 및 좋은 기사. 여기에 추가하고 그것에 대해 핑을 보내 주셔서 감사합니다.
Kay V

1
감사합니다! 이것은 내가 나쁜 병합을 취소하는 데 도움이되었습니다. 병합은 revert커밋 과 같은 방식으로 반응하지 않기 때문에 엄청나게 어려운 상황에 처했습니다. force-with-lease다른 사람들의 작업에 영향을 미치지 않고 지점의 git history를 다시 쓸 수 있다고 확신했습니다. 브라보!
anon58192932

11

가장 빠른 솔루션 (단 1 단계)

사용하다 git checkout -

당신은 볼 수 있습니다 Switched to branch <branch_name>. 원하는 지점인지 확인하십시오.


간단한 설명 :이 명령은 HEAD를 마지막 위치로 다시 이동시킵니다. 이 답변 끝에있는 결과 에 대한 참고 사항을 참조하십시오 .


니모닉 :이 방법은 cd -이전에 방문한 디렉토리로 돌아 오는 데 사용 하는 것과 매우 유사 합니다. 구문과 적용 가능한 경우는 매우 일치합니다 (예 : 실제로 HEAD가 원래 위치로 돌아 가기를 원할 때 유용합니다).


보다 체계적인 솔루션 (2 단계, 기억에 남는)

빠른 접근 방식은 OP의 문제를 해결합니다. 그러나 상황이 약간 다른 경우 어떻게해야합니까? Bash를 다시 시작한 다음 HEAD를 분리 한 상태에서 자신을 찾았습니다. 이 경우 간단하고 쉽게 기억할 수있는 2 가지 단계가 있습니다.

1. 필요한 지점을 선택하십시오

사용하다 git branch -v

기존 로컬 지점 목록이 표시됩니다. 필요에 맞는 지사 이름을 얻으십시오.

2. HEAD를 이동

사용하다 git checkout <branch_name>

당신은 볼 수 있습니다 Switched to branch <branch_name>. 성공!


결과

두 방법 중 하나를 사용하면 이전과 같이 계속해서 작업을 추가하고 커밋 할 수 있습니다. 다음 변경 사항은에 추적됩니다 <branch_name>.

모두 참고 git checkout -하고 git checkout <branch_name>머리가 분리 된 상태에서 커밋 변경이있는 경우 추가 지침을 제공 할 것입니다.


이것은 내가 할 경우 (8acc968은 HEAD ~ 2 인 가정) 때문에 작동하지 않습니다 git checkout 8acc968다음 git branch -vMyBranch아래 ... 목록에하지만 git checkout MyBranch내 의견을 삭제합니다.
amuliar

안녕하세요 @ amuliar- git checkout 8acc968분기가 아닌 커밋을 확인합니다. MyBranch원하는 커밋이 있으면 시도하십시오 git checkout MyBranch. 커밋 8acc968의 변경 사항이 포함되어 있지 않으면 지점을 체크 아웃 한 후 해당 변경 사항을 병합해야합니다.
Kay V

답변 해주셔서 감사합니다! 내가 그랬어 git checkout이전 커밋보고 다시 최신 커밋을 얻고 싶었다. 그러나 최신 커밋 해시가 없으면 거의 잃어 버렸습니다. 이 솔루션은 내 상황에 완벽합니다!
zyy

4

질문은 다음과 같이 읽을 수 있습니다.

HEADat 23b6772와 분리 상태 에 있었고 입력했습니다 git reset origin/master(스쿼시하고 싶었 기 때문에). 지금은 어떻게 돌아가 않는다, 내 마음을 변경했습니다 HEAD에있는 23b6772?

직접적인 대답은 다음과 같습니다. git reset 23b6772

그러나 이전 질문을 참조 할 때마다 입력 (복사 및 붙여 넣기) 커밋 해시 또는 약어가 아프기 때문에이 질문에 부딪 쳤 HEAD으며 인터넷 검색에서 일종의 속기가 있는지 확인했습니다.

거기있다!

git reset -(또는 내 경우 git cherry-pick -)

우연히 * nix cd -의 이전 현재 디렉토리 로 돌아가는 것과 같습니다 ! hurrah, 나는 하나의 돌로 두 가지를 배웠다.


0

명령 git checkout commit_id을 실행하면 HEAD 분리 13ca5593d(say commit-id)및 분기를 더 이상 사용할 수있게됩니다.

명령을 단계별로 실행하여 이전 위치로 다시 이동-

  1. git pull origin branch_name (선생님)
  2. git checkout branch_name
  3. git pull origin branch_name

원격 저장소에서 업데이트 된 커밋으로 이전 위치로 돌아갑니다.


0

오늘은 실수로 커밋을 체크 아웃하고 작업을 시작하여 HEAD 분리 상태에 대한 커밋을했습니다. 그런 다음 다음 명령을 사용하여 원격 지점으로 푸시했습니다.

git push origin HEAD: <My-remote-branch>

그때

git checkout <My-remote-branch>

그때

git pull

나는 분리 HEAD에서 내 지점의 모든 변경 사항을 마침내 얻었습니다.


0

이것은 기술적 인 해결책은 아니지만 효과가 있습니다. (팀원 중 누구라도 현지에서 동일한 지점을 보유한 경우)

브랜치 이름을 branch-xxx 라고 가정 해 봅시다 .

해결 단계 :

  • 업데이트하거나 당기지 마십시오.
  • 컴퓨터의 branch-xxx 에서 새 분기 ( branch-yyy )를 만드십시오.
  • 그게 전부입니다. 기존의 모든 변경 사항은이 새로운 지점 ( branch-yyy )에 있습니다. 이 지점으로 작업을 계속할 수 있습니다.

참고 :이 역시 기술적 인 해결책은 아니지만 확실히 도움이 될 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.