오래된 커밋을 확인하고 마스터 브랜치에서 헤드를 유지하고 있습니까?


85

현재 다른 git 커밋으로 전환하기 위해 (동일한 브랜치에서 ... 실제로는 마스터 브랜치에서!) 명령을 실행하고 있습니다.

git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

자, 내가 할 때마다 git은 내가 이제 분리 된 머리를 가지고 있다고 말합니다. 이전 커밋으로 이동하고 동일한 브랜치에서 헤드를 유지하려면 어떻게해야합니까?


1
해당 명령을 실행하면 HEAD 참조가 해당 커밋으로 변경됩니다 . HEAD가 다른 곳을 가리키는 것도 의미가 없습니다.
Greg Hewgill 2011

내가 git의 메시지에서 이해하는 바에 따르면 nowhere를 가리키고 있으며 이는 바람직하지 않습니다.
삼켜 진 elysium

1
Git 메시지는 "HEAD is now at ea3d5ed ..."와 같은 특정 커밋을 확인할 때 표시되며 HEAD 어딘가를 가리키고 있음을 알려줍니다 . HEAD를 제외한 다른 이름이없는 어딘가를 가리키고 있습니다 (현재는 git checkout다른 커밋 또는 브랜치 이름으로 HEAD가 새 위치로 이동하기 때문에).
Greg Hewgill 2011

주어진 대답이 이것을 적절하게 설명합니까, 아니면 우리가 더 명확하게 할 수있는 것이 있습니까? 귀하의 질문에 대한 답변이없는 경우 제 답변을 명확히 해 드리겠습니다.
Brian Campbell

HEAD를 완전히 변경하지 않고 다른 커밋을 확인하는 방법을 찾고있는 경우 (예 : 이전 커밋으로 되돌리려면) 다음 git revert --no-commit 0766c053..HEAD을 수행합니다 0766c053. 확인하려는 커밋은 어디에 있습니까 ? 이것은 stackoverflow.com/a/21718540/525872 에서 가져온 것 입니다.
Jo Liss

답변:


193

이 작업을 수행하는 대부분의 경우 임시 브랜치로 체크 아웃합니다.

git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

그런 다음 완료되면 지점을 삭제합니다.


80

해당 커밋을 체크 아웃 할 때 수행하려는 작업에 따라 다릅니다. 당신이하고있는 모든 것이 그 개정판을 빌드하거나 테스트 할 수 있도록 그것을 체크 아웃하는 것이라면, 분리 된 머리로 작업하는 것은 잘못된 것이 아닙니다. 커밋 ( git checkout master예 :)을 만들기 전에 실제 브랜치를 확인하여 브랜치에 포함되지 않은 커밋을 생성하지 않도록하십시오.

그러나 그 시점부터 더 많은 커밋을하려면 브랜치를 만들어야합니다. 브랜치에서 참조하지 않는 커밋을 만들면 쉽게 잃어 버릴 수 있으며 결국에는 아무것도 언급하지 않으므로 git의 가비지 수집기에 의해 정리됩니다. 다음을 실행하여 새 분기를 만들 수 있습니다.

git checkout -b newbranch ea3d5ed

시각화를 돕기 위해 분리 된 머리에서 작업하는 것과 가지에서 작업하는 것이 어떻게 다른지 보여주는 몇 가지 다이어그램이 있습니다.

master, A, B, C master에 대한 3 개의 커밋으로 시작하겠습니다 . 현재 분기이므로를 HEAD가리키고 masterC를 커밋합니다.

알파벳
*-*-* <-마스터 <-HEAD

이제 커밋하면 git은 부모로 C가있는 커밋을 만들고 (이는 현재 커밋이고 HEADvia 에서 가리키는 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 일 동안 리플 로그에 보관됩니다.


왜 당신이 오래된 커밋을 체크 아웃 할 때 머리가 분리 되는지는 나에게 완전히 명확하지 않습니다 . 머리 가 분리 되었다는 것이 문제 일까요? 반면에 머리가 분리 된 오래된 커밋을 체크 아웃하면 잃어 버릴 뿐인데, 왜 그렇게할까요? 그냥 어지럽히고 시도하기 위해? git이 처음에 그것을 허용하는 이유는 무엇입니까?
삼켜 진 elysium

5
@devoured elysium "분리 된 헤드" HEAD는 커밋을 가리키는 브랜치를 가리키는 대신 커밋의 SHA-1을 직접 가리키는 참조 가 있음을 의미합니다 . 머리가 브랜치를 참조하지 않기 때문에 Git은 새 커밋을 추가 할 때 업데이트 할 브랜치를 알지 못합니다. 내 답변의 시작 부분에서 설명했듯이 코드를 빌드하거나 테스트하기 위해 이전 버전으로 돌아가는 경우 머리가 분리되어 있어도 완벽합니다. git checkout master또는 이와 유사한 지점으로 언제든지 돌아갈 수 있습니다 . 머리가 분리 된 상태에서 저지르면 문제가됩니다.
Brian Campbell

@BrianCampbell-브랜치 (현재 머리가있는 곳)에서 커밋을 한 후 브랜치를 B에 병합하고 B를 마스터에 병합합니까? 다음에는 무엇을해야합니까?
amey1908

당신의 설명은 나를 위해 다른 많은 것들을 '클릭'하게 만들었습니다. 감사합니다. 이제 마지막으로 ... 자식을 이해 수

8

변경하지 않고 이전 커밋으로 돌아가서 재생하려면 다음을 수행하십시오.

git co <previous-commit-id>

이 명령 다음에 "(분기 없음)"이라는 분기에있게됩니다.

이를 확인하십시오.

git br

이 이전에 커밋 된 코드로 플레이 한 후에는 사용하던 브랜치로 전환 할 수 있습니다.

git co <the-branch-you-were-on>

"(분기 없음)"은 자동으로 삭제됩니다. 이렇게하면 임시 브랜치를 만들 필요가 없습니다.


5

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 탈선이 계속해서 짜증을 낸다면 커밋 기록을 찾아 볼 수 있습니다.)


1

질문은 약간 모호하지만 작업 트리의 파일 만 변경하려면 다음과 같이하면됩니다.

git checkout [commit|branch] -- .

그런 다음 변경 사항을 준비하고 원하는 경우 새 커밋을 만들 수 있습니다. 이것은 때때로 매우 유용합니다.


0

나는 당신의 질문을 이해한다고 생각합니다. 내가 그것을 해결하기 위해 찾은 것입니다. 그리고 그것의 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>

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