git - 설치 - 분리 된 HEAD를 마스터/원산지와 어떻게 조화시킬 수 있습니까?




git이란 (17)

나는 힘내 자의 분기 복잡성에 새로운 사람이다. 저는 항상 하나의 브랜치에서 작업하고 변경 사항을 커밋 한 다음 주기적으로 원격 원점으로 푸시합니다.

최근에 어딘가에 커밋 스테이징에서 벗어나기 위해 일부 파일을 리셋했고 나중에 최근 로컬 커밋 몇 개를 제거하기 위해 rebase -i 를 수행했습니다. 이제 나는 이해가 안되는 상태에 있습니다.

내 작업 영역에서 git log 는 내가 기대하는 바를 정확하게 보여줍니다. 나는 가고 싶지 않은 커밋과 새로운 커밋이있는 올바른 열차에 있습니다.

하지만 방금 원격 저장소로 밀어 넣었습니다. 다른 점이 있습니다. 리베이스에서 죽인 커밋 중 두 가지가 밀려 났고, 로컬로 커밋 된 새로운 커밋이 없습니다.

나는 "마스터 / 원점"이 HEAD에서 분리되었다고 생각하지만, 그게 무슨 뜻인지, 명령 행 도구로 시각화하는 방법, 그리고 그것을 고치는 방법에 대해서는 100 % 명확하지 않습니다.


자체 분기에 대한 분리 된 커밋을 얻으십시오.

단순히 git checkout -b mynewbranch 실행 git checkout -b mynewbranch .

그런 다음 git log 실행하면 커밋이 이제이 새 분기에서 HEAD 라는 것을 알 수 있습니다.


'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

그러나 그것은 분리 된 헤드 상태에서 어떤 변화를 유지하려고 의도하지 않는다면 당연히 그렇지만 나는 변화를 의도하지 않고 많은 커밋을하고 있지만 이전의 커밋을보기 만한다.


간단히 말해서 분리 된 HEAD 상태 는 어떤 지점의 HEAD (또는 팁)에 체크 아웃되지 않았 음을 의미 합니다 .

예제로 이해하기

대부분의 경우의 브랜치는 다음과 같은 다중 커밋의 시퀀스입니다.

커밋 1 : master -> branch_HEAD (123be6a76168aca712aea16076e971c23835f8ca)

Commit 2 : master -> 123be6a76168aca712aea16076e971c23835f8ca -> branch_HEAD (100644a76168aca712aea16076e971c23835f8ca)

위의 커밋 시퀀스에서 볼 수 있듯이, 여러분의 지사는 가장 최근 커밋을 가리 킵니다. 따라서 그 경우 123be6a76168aca712aea16076e971c23835f8ca 를 커밋 하기 로 계산하면 지점의 HEAD가 100644a76168aca712aea16076e971c23835f8ca가리키고 머리말 이없는 지점에서 기술적으로 체크 아웃 된 것이므로 분리 된 머리 상태가됩니다. 따라서 분리 된 HEAD 상태에 있습니다.

이론적 설명

이 블로그에서는 Git 저장소가 커밋 트리임을 명시하고 있습니다. 커밋 포인터가있는 조상을 가리키는 각 커밋이 업데이트되고 각 분기에 대한 포인터는 .git / refs 하위 디렉토리에 저장됩니다. 태그는 .git / refs / tags에 저장되고 브랜치는 .git / refs / heads에 저장됩니다. 파일 중 하나를 보면 각 태그가 40 자의 커밋 해시가있는 단일 파일에 해당하며 @Chris Johnsen 및 @Yaroslav Nikitenko가 위에서 설명한대로 이러한 참조를 확인할 수 있습니다.


개인적으로 내가 상황에 빠졌을 때 내가 master 있지 않을 때 (즉, HEADmaster 바로 위에서 분리되어 있고 그 사이에 커밋이없는 경우) 약간의 변경을 한 경우 stashing이 도움이 될 수 있습니다.

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

나는 단지 오늘이 문제에 부딪쳤다. 그리고 내가 그것을해서 해결했다고 꽤 확신한다 :

git branch temp
git checkout master
git merge temp

나는이 작업을 수행하는 방법을 알았을 때 작업 컴퓨터에 있었고 이제는 개인용 컴퓨터에서 같은 문제를 겪고 있습니다. 월요일에 내가 작업 컴퓨터로 돌아와서 내가 어떻게하는지 정확히 알기 위해 기다려야 할 것이다.


나는 똑같은 문제가 있었다. git stash 하여 변경 사항을 git stash 이전 커밋에 대한 로컬 지점을 하드 리셋 (나는 그 원인이 있다고 생각했다) 한 다음 git pull 했고 지금 그 헤드를 분리하지 않습니다. 변경 사항을 다시 git stash apply 하려면 git stash apply 을 잊지 마십시오.


나는 정말로 어리석은 상태에 빠졌습니다. 다른 누구도이 유용함을 알지 못할 것입니다.

git ls-remote origin
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        HEAD
6f96ad0f97ee832ee16007d865aac9af847c1ef6        refs/heads/HEAD
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        refs/heads/master

결국 나는

git push origin :HEAD

나는이 문제에 부딪쳤다. 그리고 내가 가장 많이 투표 한 대답을 읽을 때 :

HEAD는 현재 체크 아웃 된 커밋의 상징적 인 이름입니다.

나는 생각했다 : Ah-ha! HEAD 가 currenlty checkout 커밋의 상징적 인 이름이라면 master 에 대해 리베이스함으로써 master 와 대조 할 수 있습니다 :

git rebase HEAD master

이 명령은 다음과 같습니다.

  1. master 체크 아웃
  2. HEAD 의 부모 커밋을 master 에서 분기 된 HEAD 지점으로 식별합니다.
  3. master 위의 커밋을 재생합니다.

최종 결과는 HEAD 있지만 master 가 아닌 모든 커밋이 master 입니다. master 는 체크 아웃 상태로 유지됩니다.

원격 :

rebase에서 죽인 커밋 몇 개가 밀려 났고, 지역에서 저지른 새로운 커밋은 거기에 없었습니다.

원격 기록은 더 이상 로컬 기록을 사용하여 빨리 감기 할 수 없습니다. 원격 히스토리를 덮어 git push -f 려면 강제 실행 ( git push -f )해야합니다. 공동 작업자가있는 경우 일반적으로 공동 작업자와 조정하여 모두가 같은 페이지에 있도록하는 것이 좋습니다.

master 를 원격 origin 밀어 넣으면 원격 추적 분기 origin/masterorigin/master 와 동일한 커밋을 가리 키도록 업데이트됩니다.


다음은 저에게 도움이되었습니다 (분기 마스터 만 사용).

git push origin HEAD:master
git checkout master        
git pull

첫 번째는 분리 된 HEAD를 원격 원점으로 푸시합니다.

두 번째는 지점 마스터로 이동합니다.

세 번째는 분기 마스터에 연결된 HEAD를 복구합니다.

푸시가 거부되면 첫 번째 명령에서 문제가 발생할 수 있습니다. 그러나 이것은 더 이상 분리 된 헤드의 문제가 아니지만 분리 된 헤드가 일부 원격 변경을 인식하지 못한다는 사실에 관한 것입니다.


만약 당신이 master 브랜치를 가지고 있고 "development"또는 feature로 돌아가고 싶다면 :

git checkout origin/develop

참고 : 원산지 확인 / 개발

분리 된 HEAD 상태입니다. 둘러보고 둘러보고 실험을 변경하고 커밋 할 수 있으며 또 다른 체크 아웃을 수행하여 분기에 영향을주지 않고이 상태에서 커밋을 삭제할 수 있습니다.

그때

git checkout -b develop

그것은 작동합니다 :)


먼저, HEAD가 무엇인지, 분리되었을 때 HEAD가 무엇을 의미하는지 명확히 설명 합니다 .

HEAD는 현재 체크 아웃 된 커밋의 상징적 인 이름입니다. HEAD가 분리되지 않은 경우 ( "정상"상태 : 분기를 체크 아웃 한 경우), 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 를 산출 17a02998078923f2d62811326d130de991d1a95a
    이것은 "상징적 심판"을 의미합니다. 다른 참조를 통해 객체를 가리 킵니다.
    (심볼릭 심판은 원래 심볼릭 링크로 구현되었지만 심볼릭 링크가없는 플랫폼에서 사용할 수 있도록 추가 해석을 통해 일반 파일로 변경되었습니다.)

HEADrefs/heads/master17a02998078923f2d62811326d130de991d1a95a

HEAD가 분리되면 지점을 통해 간접적으로 가리키는 대신 직접 커밋을 가리 킵니다. 분리 된 HEAD는 이름없는 지점에 있다고 생각할 수 있습니다.

  • git symbolic-ref HEADfatal: ref HEAD is not a symbolic ref 실패합니다 fatal: ref HEAD is not a symbolic ref
  • git rev-parse HEAD 17a02998078923f2d62811326d130de991d1a95a
    심볼릭 심판이 아니기 때문에 커밋 자체를 직접 가리켜 야합니다.

우리는 HEAD17a02998078923f2d62811326d130de991d1a95a

분리 된 HEAD로 기억해야 할 중요한 점은 그것이 참조하는 커밋이 참조되지 않으면 (다른 참조가 도달 할 수없는 경우), 다른 커밋을 체크 아웃 할 때 "dangling"이됩니다. 결과적으로 이러한 매달린 커밋은 가비지 수집 프로세스를 통해 정리됩니다 (기본적으로 적어도 2 주 동안 유지되며 HEAD의 reflog에서 참조하여 더 오래 보관할 수 있습니다).

1 분리 된 HEAD로 "정상"작업을 수행하는 것은 완벽하게 훌륭합니다. reflog에서 기록을 삭제하는 것을 피하기 위해 무엇을하고 있는지 추적해야합니다.

대화 형 rebase의 중간 단계는 분리 된 HEAD로 수행됩니다 (부분적으로 활성 분기의 reflog를 오염시키지 않음). 전체 rebase 작업을 완료하면 원래 분기를 rebase 작업의 누적 결과로 업데이트하고 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 를 추가해야 할 수도 있습니다 ).

rebase 작업을하는 중일 때는 정리해야합니다. .git/rebase-merge/ 디렉토리를 찾아 rebase가 진행 중인지 여부를 확인할 수 있습니다. 해당 디렉토리를 삭제하여 진행중인 rebase를 수동으로 정리할 수 있습니다 (예 : 활성 rebase 작업의 목적과 컨텍스트를 더 이상 기억하지 않는 경우). 일반적으로 git rebase --abort 사용 git rebase --abort , 이는 여러분이 아마 피해야 할 여분의 재설정을 수행합니다 (HEAD를 원래의 지점으로 옮기고 원래의 커밋으로 되돌려 놓습니다. 이것은 원래 위의 작업 중 일부를 취소합니다). ).


분리 된 머리의 기본 설명을 보려면 여기를보십시오.

http://git-scm.com/docs/git-checkout

그것을 시각화하는 커맨드 라인 :

git branch

또는

git branch -a

당신은 다음과 같은 출력을 얻을 것이다 :

* (no branch)
master
branch1

* (no branch) 는 분리 된 머리에 * (no branch) 보여줍니다.

git checkout somecommit 등을 수행하여이 상태로 올 수 있었으며 다음과 같이 경고했을 것입니다.

당신은 'HEAD'상태에 있습니다. 주변을 둘러보고 실험적으로 변경하고 커밋 할 수 있으며, 다른 체크 아웃을 수행하여 분기에 영향을주지 않고이 상태에서 커밋을 삭제할 수 있습니다.

작성한 커 L 트를 보유 할 새 브랜치를 작성하려는 경우, checkout 명령으로 -b를 다시 사용하여 (지금 또는 나중에) 수행 할 수 있습니다. 예:

자식 체크 아웃 -b new_branch_name

자, 그들을 마스터로 데려 가기 위해서 :

git reflog 또는 심지어 git log 하고 커밋을 기록하십시오. 이제 git checkout mastergit merge 이 커밋을 git merge 합니다.

git merge [email protected]{1}

편집하다:

추가하려면 git rebase -i 사용하여 불필요한 커밋을 삭제 / 제거 할뿐만 아니라 커밋을 편집 할 수도 있습니다. 커밋 목록에서 "편집"을 언급하면 ​​커밋을 수정 한 다음 git rebase --continue 를 실행할 수 있습니다. 계속 진행하십시오. 이것은 당신이 분리 된 머리에 결코 들어오지 않았 음을 확신했을 것입니다.


이것은 나를 위해 완벽하게 작동했습니다.

1. git stash 를 사용하여 로컬 수정 사항 저장하기

변경 사항을 취소하려는 경우
git clean -df
git checkout -- .
git clean은 모든 untrack되지 않은 파일을 제거합니다 (경고 : .gitignore에서 직접 언급 한 무시 된 파일은 삭제하지 않지만 폴더에있는 무시 된 파일은 삭제할 수 있음). git checkout은 모든 unstaged 변경 사항을 지 웁니다.

2. git checkout master 가 메인 브랜치 (master를 사용하기를 원한다고 가정)로 바꾼다.
3. git pull 을 사용하여 master 브랜치에서 마지막 커밋을 가져옵니다.
4. 모든 것을 확인하기 위해 git status 가 멋지게 보인다.

On branch master
Your branch is up-to-date with 'origin/master'.

크리스가 지적한대로, 나는 상황을 따라 갔다.

git symbolic-ref HEADfatal: ref HEAD is not a symbolic ref 실패합니다 fatal: ref HEAD is not a symbolic ref

그러나 git rev-parse refs/heads/master 는 내가 복구 할 수있는 곳에서 좋은 커밋을 가리키고있다. (내 경우에는 마지막 커밋이고 git show [SHA] 사용하여 커밋을 볼 수있다 git show [SHA]

그 후 많은 일들을했는데, 고정되어있는 것처럼 보이는 것은 단지,

git symbolic-ref HEAD refs/heads/master

머리가 붙어 있습니다!


현재 분리 된 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 checkout origin/master 를 수행하는 대신

그냥 git checkout master

그러면 git branch 가 여러분의 git branch 를 확인합니다.


git 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




git