fatal: 'origin/main' is not a commit and a branch 'main' cannot be created from it

불타는강정·2022년 1월 1일
6
post-thumbnail

회사 동기에게 깃 도움 요청을 받았다. 브랜치 switch를 못하고 있다고 한다. 궁금해서 다같이 구글밋에 모여서 해결방법을 찾았다.

상황

현재 a브랜치에 있는데 b브랜치로 switch를 하고 싶지만 못하고 있었다.

상황파악

  1. git switch b를 실행해서 에러를 확인해보았다. fatal: invalid reference: step3 브랜치가 로컬에 없는 것 같았다.
  2. 동기들이랑 추측한 결과 깃 클론 받을 때 --single-branch로 받은 게 문제였다. a 브랜치만 받아서 b가 로컬에 없기 때문에 switch를 못하는 것 같다.
  3. 그럼 원격에 있는 b를 받아오면 될 것 같았다.
  4. 원격의 b 브랜치를 확인해보기 위해 git branch -r을 확인해봤다. b 브랜치가 없었다...
  5. 그래도 원격의 b 브랜치를 받기 위해 git checkout -t origin/b를 실행했더니 fatal: 'origin/b' is not a commit and a branch 'b' cannot be created from it 에러가 떴다.
  6. 설마 origin에 b가 없나 싶어 깃허브를 확인했더니 b 브랜치가 있었다.
  7. 분명 원격에 있는데 왜 못 받아오는지 이해가 안 됐다.
  8. 동료가 포기하고 클론을 다시 받자고 했다 -> 말렸다
  9. 에러를 구글링해봤다. 스택오버플로우에 우리랑 같은 문제를 겪었고 해결방법도 있었다.
  10. 아래 명령어를 실행하니 해결됐다.
git  remote  set-branches  --add  'origin'  'newbranch'
git  fetch  'origin'
git  checkout  --track  'origin/newbranch'

내가 잘 몰랐던 것들

바로바로 찾아서 해결은 했지만 내가 부족한 부분은 있었다

  • --single-branch로 받았을 때 왜 원격 브랜치 리스트를 못 봤을까??
  • checkout -t가 어떤 동작을 할까?
  • 해결과정으로 실행한 명령어의 의미

--single-branch

저장소에 하나의 브랜치만 받을 경우 사용하는 옵션이다. 뒤에 브랜치 명을 적어주면 브랜치 하나만 받아온다.

그런데 이렇게 받아오면 왜 원격 브랜치 리스트는 못 보는지 모르겠다. git branch -r은 로컬과 연결된 원격 브랜치의 리스트만 보여줘서 그런가?

찾아보니 -r 옵션은 Option -r causes the remote-tracking branches to be listed remote에 있는 브렌치가 아니라 remote를 트레킹하는 (원격이랑 연결된 로컬 브랜치인듯) 브랜치의 리스트를 보여준다. 지금은 a브랜치만 원격이랑 연결돼서 안 보이는 것 같다.

그럼 origin에 있는 모든 브랜치의 리스트는 못 보는 걸까? - 찾아보니 없는 것 같다..

+하나 이상의 특정한 브랜치를 받아오고 싶을 경우

git clone으로 바로 받아올 수 있는 방법은 없다.
git clone은 여러 과정으로 되어 있는데, 크게 아래 과정으로 이루어진다. (실제로는 6단계)
1. git init
2. git remote add
3. git fetch
4. git checkout
여기서 git remote add로 여러 브랜치를 받아올 수 있다.

또는 --single-branch로 받아온 다음 git remote set-branches origin으로 남은 브랜치를 받아올 수 있다. (우리가 해결한 방법)

git config remote.origin.fetch

--single-branch 를 찾아보다가 이 옵션을 해제하고 다시 전체 브렌치를 받아오고 싶다면 이 명령어를 치고 git config remote.origin.fetch refs/heads/*:refs/remotes/origin/* 다음으로 git fetch를 하라고 한다. git config는 잔디 설정이 안 될 때 이름이랑 이메일 설정하려고 건드린 적 있었는데 remote.origin.fetch 이 복잡한 설정은 무엇인가...! 너무 심연을 본 것 같지만 그래도 가보도록 하자. 이걸 참고해서 알아봤다.

git remote 설정은 Refspec이라 한다. 로컬 깃 저장소를 사용하다가 origin이라는 리모트 저장소를 지정하려면 이렇게 실행한다.
git remote add origin https://github.com/schacon/simplegit-progit

이 명령은 origin이라는 저장소 이름, URL, Fetch할 Refspec을 .git/config 파일에 추가한다. 설정파일을 열어보면 이렇게 저장되어 있다.

[remote "origin"]
    url = https://github.com/schacon/simplegit-progit
    fetch = +refs/heads/*:refs/remotes/origin/*

이제 우리가 봤던 fetch 형식이 나온다. fetch는 +<src>:<dest>로 되어있다. <src>는 리모트 저장소의 Refs 패턴이고 <dest>는 로컬 저장소의 Refs 패턴이다.

--single-branch로 클론받은 레포의 설정파일을 보면 이렇게 되어 있다.

전체 브랜치를 연결시키지 않고 딱 설정한 브랜치만 연결되었다. 이래서 이거 하나만 받아오는구나. 아 복잡하다!

명령어 하나씩 알아보기

git  remote  set-branches  --add  'origin'  'newbranch'
git  fetch  'origin'
git  checkout  --track  'origin/newbranch'

git remote set-branches는 뭔지 아직 못 찾았다. 직접 해보니 Refspec이 바뀌는 건 아니고 config 파일에 [branch] 옵션이 새로 생겼다. 이걸로 브랜치 자체를 추가한 것 같다. (아니 그런데 Ref에는 왜 추가가 안 되지)

그 다음 fetch로 로컬에 없는 데이터 받아오고

git checkout --track origin/serverfix 으로 로컬 브랜치 이름을 자동으로 생성할 수 있다. origin 정보 받아온 다음 origin/브랜치로 바로 원격 브랜치랑 연결되는 로컬 브랜치를 만든 것 같다.

후기

그래도 git HEAD 때서 분리하고 시간도 왔다갔다거리고 많이 알고있다 생각했는데 그래도 모르는 부분이 많다고 느꼈다. 특히 config 관련된 것들... 언젠가 공부해봐야지

profile
대충살자

0개의 댓글