현재 다른 git 커밋으로 전환하기 위해 (동일한 브랜치에서 ... 실제로는 마스터 브랜치에서!) 명령을 실행하고 있습니다.
git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
자, 내가 할 때마다 git은 내가 이제 분리 된 머리를 가지고 있다고 말합니다. 이전 커밋으로 이동하고 동일한 브랜치에서 헤드를 유지하려면 어떻게해야합니까?
현재 다른 git 커밋으로 전환하기 위해 (동일한 브랜치에서 ... 실제로는 마스터 브랜치에서!) 명령을 실행하고 있습니다.
git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
자, 내가 할 때마다 git은 내가 이제 분리 된 머리를 가지고 있다고 말합니다. 이전 커밋으로 이동하고 동일한 브랜치에서 헤드를 유지하려면 어떻게해야합니까?
git checkout
다른 커밋 또는 브랜치 이름으로 HEAD가 새 위치로 이동하기 때문에).
git revert --no-commit 0766c053..HEAD
을 수행합니다 0766c053
. 확인하려는 커밋은 어디에 있습니까 ? 이것은 stackoverflow.com/a/21718540/525872 에서 가져온 것 입니다.
답변:
해당 커밋을 체크 아웃 할 때 수행하려는 작업에 따라 다릅니다. 당신이하고있는 모든 것이 그 개정판을 빌드하거나 테스트 할 수 있도록 그것을 체크 아웃하는 것이라면, 분리 된 머리로 작업하는 것은 잘못된 것이 아닙니다. 커밋 ( git checkout master
예 :)을 만들기 전에 실제 브랜치를 확인하여 브랜치에 포함되지 않은 커밋을 생성하지 않도록하십시오.
그러나 그 시점부터 더 많은 커밋을하려면 브랜치를 만들어야합니다. 브랜치에서 참조하지 않는 커밋을 만들면 쉽게 잃어 버릴 수 있으며 결국에는 아무것도 언급하지 않으므로 git의 가비지 수집기에 의해 정리됩니다. 다음을 실행하여 새 분기를 만들 수 있습니다.
git checkout -b newbranch ea3d5ed
시각화를 돕기 위해 분리 된 머리에서 작업하는 것과 가지에서 작업하는 것이 어떻게 다른지 보여주는 몇 가지 다이어그램이 있습니다.
master
, A, B, C master
에 대한 3 개의 커밋으로 시작하겠습니다 . 현재 분기이므로를 HEAD
가리키고 master
C를 커밋합니다.
알파벳 *-*-* <-마스터 <-HEAD
이제 커밋하면 git은 부모로 C가있는 커밋을 만들고 (이는 현재 커밋이고 HEAD
via 에서 가리키는 master
) master
새 커밋을 가리 키도록 업데이트 합니다. 모든 커밋은 이제에 master
있으며 HEAD
를 통해 새 커밋을 가리 킵니다 master
.
ABCD *-*-*-* <-마스터 <-HEAD
이제 B를 확인하여 분리 된 HEAD
.
ABCD *-*-*-* <-마스터 ^ \-머리
여기서는 모든 것이 잘 작동합니다. 모든 파일을보고, 프로그램을 빌드하고, 테스트하는 등의 작업을 할 수 있습니다. 새 커밋을 만들 수도 있습니다. 하지만 그렇게하면 우리가있는 브랜치가 없기 때문에 그 새로운 커밋에서 브랜치를 가리킬 수 없습니다. 그것을 가리키는 유일한 것은 HEAD
:
ABCD *-*-*-* <-마스터 \ * <-머리 이자형
나중에 master
다시 체크 아웃하기로 결정 하면 E를 언급하는 것이 없습니다.
ABCD *-*-*-* <-마스터 <-HEAD \ * 이자형
참조하는 것이 없기 때문에 찾기가 어려울 수 있으며 git은 참조가없는 커밋을 버려야한다고 생각합니다 (리베이스, 패치를 스쿼시하거나 다른 재미있는 기록 조작을 수행하는 경우 매우 일반적으로 발생합니다. 일반적으로 버려진 패치를 나타냅니다. 더 이상 신경 쓰지 않는 것). 일정 시간이 지나면 git은 다음 번에 가비지 수집이 실행될 때 폐기되도록 가비지로 간주합니다.
따라서 베어 개정판을 확인하고 머리를 분리하는 대신 더 많은 커밋을 할 것 같으면 git checkout -b branch B
브랜치를 만들고 확인하는 데 사용해야 합니다. 이제 커밋은 쉽게 참조하고 나중에 병합 할 수있는 브랜치에 포함될 것이므로 손실되지 않습니다.
ABCD *-*-*-* <-마스터 ^ \-분기 <-HEAD
이 작업을 잊고 브랜치에서 커밋을 생성하더라도 걱정할 필요가 없습니다. 를 사용하여 헤드 개정을 참조하는 분기를 만들 수 있습니다 git checkout -b branch
. 이미 master
브랜치 로 다시 전환 했고 길잃은 커밋을 잊었다는 것을 깨달은 경우를 사용하여 찾을 수 있습니다 . 이는 지난 며칠 동안 git reflog
커밋 HEAD
이 지적한 내역을 보여줍니다 . 여전히 리플 로그에있는 것은 가비지 수집되지 않으며 일반적으로 레퍼런스는 적어도 30 일 동안 리플 로그에 보관됩니다.
HEAD
는 커밋을 가리키는 브랜치를 가리키는 대신 커밋의 SHA-1을 직접 가리키는 참조 가 있음을 의미합니다 . 머리가 브랜치를 참조하지 않기 때문에 Git은 새 커밋을 추가 할 때 업데이트 할 브랜치를 알지 못합니다. 내 답변의 시작 부분에서 설명했듯이 코드를 빌드하거나 테스트하기 위해 이전 버전으로 돌아가는 경우 머리가 분리되어 있어도 완벽합니다. git checkout master
또는 이와 유사한 지점으로 언제든지 돌아갈 수 있습니다 . 머리가 분리 된 상태에서 저지르면 문제가됩니다.
Git의 HEAD는 작업 디렉토리에있는 내용을 나타내는 포인터입니다. 브랜치의 헤드가 아닌 커밋을 확인하려면 해당 커밋을 가리 키도록 HEAD를 리디렉션하면됩니다. 주위에 방법이 없습니다. 해당 커밋에서 임시 브랜치를 만들 수 있지만 그럼에도 불구하고 HEAD는 마스터에서 멀어집니다.
그것은 짧은 설명입니다. 아래의 자세한 내용은 HEAD와 마스터가 어떻게 다른지 이해하는 데 도움이되기를 바랍니다.
일반적으로 상황은 다음과 같습니다.
C ← refs/heads/master ← HEAD
↓
B
↓
A
즉,“C의 부모는 B이고 B의 부모는 A입니다. 브랜치 마스터는 C를 가리키고 있으며 현재 마스터의 내용을 확인했습니다. 또한 내가 커밋하면 마스터가 업데이트 될 것이다.”
커밋 그래프를 완전히 이해하는 데 필요한 몇 가지 가정이 내재되어 있습니다. 즉, 커밋은 부모 만 참조하고 브랜치의 내용은 부모 링크를 따라 도달 할 수있는 커밋 (및 커밋 만)입니다. 작업 트리 및 인덱스의 (수정되지 않은) 내용은 간접적으로 ( "기호") 또는 직접 ( "분리") HEAD에 의해 명명 된 커밋과 일치해야합니다.
따라서 이전 커밋을 확인하려면 원하는 커밋을 가리 키도록 HEAD를 업데이트해야합니다. git-checkout
다음과 같이합니다.
C ← refs/heads/master
↓
B ← HEAD
↓
A
이제, 당신은 오래된 것을보고 있기 때문에 당신의 지부를 당신 뒤에두고 왔습니다. "분리 된 머리"의 조언이 차분하게 말해 주듯이 (내 강조).
주위를 둘러보고 실험적인 변경을하고 커밋 할 수 있으며, 다른 체크 아웃을 수행하여 분기 에 영향을주지 않고이 상태에서 수행 한 커밋을 삭제할 수 있습니다 .
반면에 브랜치를 재설정하면 필요한 위치에 HEAD가 생기지 만 매우 다른 효과가 있습니다!
C
↓
B ← refs/heads/master ← HEAD
↓
A
커밋 C는 더 이상 마스터 브랜치의 일부가되는 것을 원하지 않는다고 선언했기 때문에 쓰레기가됩니다.
즉, 당신이 할 일은 "HEAD"에 의해 수단을 이눔 이해 - 그것은 어디 당신이 있습니다, 어떤 주어진 지점이없는 곳. 그리고 당신 이있는 곳이 브랜치가있는 곳과 같지 않다면 분리 된 HEAD를 사용할 수밖에 없습니다.
(아마도 GitHub, gitk 또는 gitweb을 살펴보고 HEAD 탈선이 계속해서 짜증을 낸다면 커밋 기록을 찾아 볼 수 있습니다.)
나는 당신의 질문을 이해한다고 생각합니다. 내가 그것을 해결하기 위해 찾은 것입니다. 그리고 그것의 GUI 솔루션이 없으며, 당신은 그것을 해결하기 위해 단지 명령을 사용할 수 있으며, 정말 간단합니다.
1 단계 : 돌아 가려는 이전 커밋의 태그를 만듭니다.
태그 v2.0처럼
2 단계 : git checkout v2.0
이제 HEAD가 'v2.0'커밋을 가리키고 있지만 마스터는 여전히 마지막 커밋을 가리키고 있습니다.
C:\Program Files\Git\doc\git\html\git-checkout.html
이 문서는 당신을 도울 수 있습니다
또는 입력 git help <checkout>