꺼내먹는지식 준

GITHUB 협업 1.5, local remote branch 본문

CS/깃헙

GITHUB 협업 1.5, local remote branch

알 수 없는 사용자 2022. 4. 9. 17:46

Github 협업을 위한 글들을 숙지하고, 약간의 실험을 한 후 임에도 불구하고 막상 직접 깃헙을 사용하다보니 여러 문제가 발생했다. 이에 더하여, vscode에서 git graph를 보고 마우스로 간단하게 git flow 를 조작하다가 실제로 CLI 를 사용하여 github 을 조작해보니 예상치 못한 문제들이 발생했다. 대표적으로는, 마우스로 조작할 때와 다르게 내가 의도한 명령어의 실제 작동이 예상과 다를 때 이다. 또한 graph를 실시간으로 보면서 상호작용하는 것이 아니다 보니까 머리 속에 흐름이 잘 그려지지 않기도 했다. 이에 따라 최종적으로 연습 repository를 만들어 과업 속에서 얻는 인사이트들을 실험해보고자 하였다. 

 

스스로 실험하면서 발생하는 모든 시나리오를 작성할 예정이다. 


해당 글에서 다음과 같이 구간이 분리된 글들은 읽지 않고 넘어가도 좋다. 본 글의 맥락과는 크게 관련 없는 추가 정보이다. 


github 홈페이지에서 Repository를 생성한 후, 처음으로 연결을 한다. 

(base) hajunkim@hajunuicBookPro github_practice_final % git clone https://github.com/organization_name/test.git
'test'에 복제합니다...
warning: 빈 저장소를 복제한 것처럼 보입니다.

곧바로 연결을 하니 warning이 나온다. 

문제가 있을까? 

(base) hajunkim@hajunuicBookPro test % git remote -v
origin	https://github.com/organization_name/test.git (fetch)
origin	https://github.com/organization_name/test.git (push)

우선 remote repository에 잘 연결된건 확인 하였다. 

(base) hajunkim@hajunuicBookPro test % git status
현재 브랜치 main

아직 커밋이 없습니다

커밋할 사항 없음 (파일을 만들거나 복사하고 "git add"를 사용하면 추적합니다)

local repository를 생성한적이 없지만, remote repository를 clone했다는 것만으로도 바로 local repositroy "test"가 생성된 것을 알 수 있다. 

본 블로그의 github 협업 글들을 참고하면, pre-commit commit template, issue template, 등등 협업을 위한 필수 과정들이 있다는 것을 알 수 있다. 해당 template 들을 담은 .github 폴더를 먼저 remote repository에 등록해보자. 


먼저 local repository인 test로 .github 폴더를 옮겨보자. 

(base) hajunkim@hajunuicBookPro github_practice_final % ls -a 
.		..		.DS_Store	.github		test

test 상위폴더에 .github 폴더를 넣어놨다. local repository가 생성되었으니 폴더를 옮겨야 한다. 

mv [파일명] [폴더명/파일명] : 파일을 입력한 폴더로 이동

(base) hajunkim@hajunuicBookPro github_practice_final % ls -a 
.		..		.DS_Store	.github		test

(base) hajunkim@hajunuicBookPro github_practice_final % mv .github test

(base) hajunkim@hajunuicBookPro github_practice_final % cd test

(base) hajunkim@hajunuicBookPro test % ls -a
.	..	.git	.github

test 폴더로 .github 파일을 옮겼다. 


git status 로 확인하자 .github 파일이 추적되지 않는 것을 확인할 수 있다. git add를 통해 추적하자. 

(base) hajunkim@hajunuicBookPro test % git status
현재 브랜치 main

아직 커밋이 없습니다

추적하지 않는 파일:
  (커밋할 사항에 포함하려면 "git add <파일>..."을 사용하십시오)
	.github/

커밋할 사항을 추가하지 않았지만 추적하지 않는 파일이 있습니다 (추적하려면 "git
add"를 사용하십시오)
(base) hajunkim@hajunuicBookPro test % git add .
(base) hajunkim@hajunuicBookPro test % git status
현재 브랜치 main

아직 커밋이 없습니다

커밋할 변경 사항:
  (스테이지 해제하려면 "git rm --cached <파일>..."을 사용하십시오)
	새 파일:       .github/.DS_Store
	새 파일:       .github/.gitmessage.txt
	새 파일:       .github/.pre-commit-config.yaml
	새 파일:       .github/ISSUE_TEMPLATE/README.md
	새 파일:       .github/ISSUE_TEMPLATE/bug-report.md
	새 파일:       .github/ISSUE_TEMPLATE/extra.md
	새 파일:       .github/ISSUE_TEMPLATE/feature-development.md
	새 파일:       .github/ISSUE_TEMPLATE/feature-request.md
	새 파일:       .github/commit_template_manual.md
	새 파일:       .github/pull_request_template.md

추적은 되었고, 

git commit -m "[DOCS]: Add basic git commit files"
[main (최상위-커밋) e9edaa8] [DOCS]: Add basic git commit files
 10 files changed, 203 insertions(+)
 create mode 100644 .github/.DS_Store
 create mode 100755 .github/.gitmessage.txt
 create mode 100755 .github/.pre-commit-config.yaml
 create mode 100755 .github/ISSUE_TEMPLATE/README.md
 create mode 100755 .github/ISSUE_TEMPLATE/bug-report.md
 create mode 100755 .github/ISSUE_TEMPLATE/extra.md
 create mode 100755 .github/ISSUE_TEMPLATE/feature-development.md
 create mode 100755 .github/ISSUE_TEMPLATE/feature-request.md
 create mode 100755 .github/commit_template_manual.md
 create mode 100755 .github/pull_request_template.md

commit을 통해 등록도 완료하였다. 

 


※해당 부분은 읽지 마시오. 

(base) hajunkim@hajunuicBookPro test % git status
현재 브랜치 main
현재 브랜치가 'origin/main' 기반이지만, 업스트림이 없어졌습니다.
  (바로잡으려면 "git branch --unset-upstream"을 사용하십시오)

커밋할 사항 없음, 작업 폴더 깨끗함

다시 한번 상태를 확인해보니 orgin/main 과 local 의 main이 연결되지 않은 것으로 보인다. 

 

해당 문제에 대해 stack overflow는 다음과 같이 설명한다. 

remote-tracking branch origin/master used to exist, but does not now, so local branch source is tracking something that does not exist, which is suspicious at best

 

 

한마디로 local과 remote 가 연결되지 않았다는 것인데, git init 을 한 후 연결하지 않고 바로 clone해서 그런가? 싶긴하다.

그래도 한번 먼저 push 를 해보도록 한다. 

(base) hajunkim@hajunuicBookPro test % git push orgin main
fatal: 'orgin' does not appear to be a git repository
fatal: 리모트 저장소에서 읽을 수 없습니다

올바른 접근 권한이 있는지, 그리고 저장소가 있는지
확인하십시오.
(base) hajunkim@hajunuicBookPro test % git remote -v
origin	https://github.com/organization_name/test.git (fetch)
origin	https://github.com/organization_name/test.git (push)

remote -v 명령어로 확인해보면 연결은 되어 있지만 origin/main과 local main이 연결되지는 않았다. 

해당 github에 들어가보면 main branch가 없다는 것을 확인할 수 있다. 

 

※사전 경험에 의하면 remote branch 가 있으면 local branch도 자동으로 생성되고 반대의 경우도 동일한 것으로 알고 있었다. 다만 지금은 branch가 아예 없는 경우라 그런것 아닌가 싶기는하다. 

 

https://trustyoo86.github.io/git/2017/11/28/git-remote-branch-create.html

 

다음의 블로그의 글을 참고해봐도 사전 경험 이해가 맞다. 

아래는 해당 블로그 글 부분 발췌이다. 

처음 remote branch를 생성할 때는 아래의 방법을 따라야 한다고 한다. 

 

초기화하지 않고 저장소를 생성할 때의 커맨드라인 안내 메시지도 main으로 초기화하도록 변경되었다. 이전에는 git이 알아서 기본으로 master를 기본으로 사용하였지만 main은 그렇지 않기 때문에 명시적으로 git branch -M main으로 브랜치를 생성하는 명령어가 추가되었다.


위 부분은 시행착오이나, 기록을 위해 남겨둔다. 
정리하자면 originorgin 로 오타를 내서 생성이 안된거다. 
clone 을 하자마자 local에 main branch는 자동으로 생성되었다. 
그리고 local의 main branch에 .git 폴더를 올린 후, remote 로 push 하자 remote에도 branch가 생성되었다. 
(base) hajunkim@hajunuicBookPro test % git push -u origin main
오브젝트 나열하는 중: 14, 완료.
오브젝트 개수 세는 중: 100% (14/14), 완료.
Delta compression using up to 8 threads
오브젝트 압축하는 중: 100% (13/13), 완료.
오브젝트 쓰는 중: 100% (14/14), 3.78 KiB | 3.78 MiB/s, 완료.
Total 14 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/test-for-test-for-test/test.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

잘 생성되었다! 

 

그럼 main branch에서 branch를 따면서 git flow 연습을 해보고자 한다. 

git flow 가 뭔지 모르시는 분들은 해당 블로그의 글을 읽고 오자. 

 

먼저 dev branch를 따보자. 

(base) hajunkim@hajunuicBookPro test % git checkout -b dev   
새로 만든 'dev' 브랜치로 전환합니다

git graph 그림은 다음과 같다. (git graph에 관한 설명은 해당 글을 읽고오자.)

 

여기서 feature branch를 딴 후, 잘 작동되나 확인해보자. 

local의 dev branch를 Head 가 가리키고 있고, 해당 dev branch 는 origin | main 에서 따온 것을 알 수 있다. 

 

local의 dev branch 를 push 해서 dev branch 를 생성해보자. 

(base) hajunuicBookPro:test hajunkim$ git push origin dev
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote: 
remote: Create a pull request for 'dev' on GitHub by visiting:
remote:      https://github.com/test-for-test-for-test/test/pull/new/dev
remote: 
To https://github.com/test-for-test-for-test/test.git
 * [new branch]      dev -> dev

이로써 Head 가 remote branch인 dev | origin 을 가리키는 것을 확인 할 수 있다. 둘의 commit 상태가 동일하다. 

 

Head, Master 개념은 해당 블로그의 글 에 잘 작성되어 있지만 간단하게 한번 더 정리하자면 다음과 같다. 

  • Head: 현재 commit을 카리킨다. 
  • Master(main):  마지막 commit을 가리킨다. 

즉, master 는 내가 직접 수행한 마지막 commit을 가리키고 있고, HEAD 는 내가 지금 가리키고 있는 commit 즉 checkout 을 통해 다른 위치의 branch로 이동했을 때 가리키는 branch 의 commit을 뜻한다. 

 

다른 말로하면, HEAD는 working directory의 위치를 가리킨다. 즉 과거 버전으로 옮기고 싶다면 HEAD 를 과거 버전의 commit으로 옮기면 된다. 이 명령어가 checkout이다. → checkout 은 HEAD를 옮긴다.

 

※다시 한번 언급하지만 git graph의 UI가 직관적이지 않아서 어려우신 분들은 해당 글을 참고 바란다.

 

이후 dev|origin 에서 feature branch를 따보자. 

local에 브랜치가 생성되었고, 이를 remote 로 push 하면 

다음과 같이 생성된다. 

feat/1 local branch에 먼저 file 을 생성하여 변화를 준후, commit 해보자. 

local branch가 [EXP]: experiement_v1 commit으로 인하여 commit이 1 개 앞서나가고 있다. 

 

remote branch에 push 해서 수정 사항을 반영하자.

다음과 같이 반영된 것을 알 수 있다. 

 

feat/1 | origin 브랜치는 dev | origin , 그리고 dev | origin 은 main | origin에서 따온 branch이다. 

이로 인해 해당 push 작업을 마친 후 github 페이지에 들어가면 자동으로 feat/1 | origin branch의 update 내용을 다음의 dev | origin 은 main | origin 에도 반영(merge)을 할 것인지 확인한다. 

compare & pull request 버튼을 눌러보면 아래의 drop down 버튼을 통해 어디 branch에서 어느 branch로 수정내역을 반영할 것인지 확인한다. 

이때 base 를 선택하여 merge 할 branch를 선택할 수 있다. 

 

merge 를 마치고 나면 

remote dev branch에 merge가 반영된 것을 확인 할 수 있다. 

(github에서의 merge 작업이 git graph에 반영되기까지 시간이 좀 소요된다.)

local의 dev branch는 feat1 branch의 내용이 업데이트 되지 않았는데 origin/dev 에는 반영이 되어 다음과 같이 분할이 된 형태로 나타난다. 

 

feat/1 branch 는 본연의 역할을 마쳤다. feat branch에서 작업한 내용은 dev | origin에 병합되어 더이상 feat1 branch는 필요가 없다. 

이제 이제 해당 branch는 제거하기로 한다. 

 

local의 dev 로 checkout 을 했다. local dev 는 origin/dev 에 update 된 파일이 없다. 

생성한 파일은 v1.py 였는데 해당 파일이 사라졌다. 해당 내용을 remote로부터 local로 업데이트 해보자. 

단순하게 git pull을 하면 기대처럼 작동하지 않는다. tracking이 되지 않고 있다고 한다. 

(base) hajunuicBookPro:test hajunkim$ git pull origin dev
From https://github.com/test-for-test-for-test/test
 * branch            dev        -> FETCH_HEAD
Updating e9edaa8..f76b186
Fast-forward
 v1.py | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 v1.py

origin dev에서 pull하라고 명시적으로 작성해주니 잘 작동한다. 

dev | origin 즉, local이 remote를 follow up 한 것을 확인 할 수 있다. 

 

이 과정 속에서 dev | origin과 main | origin 의 관계가 끊긴 것으로 보인다. 

(base) hajunuicBookPro:test hajunkim$ git branch -a
* dev
  feat/1
  main
  remotes/origin/dev
  remotes/origin/feat/1
  remotes/origin/main

checkout 과정에서 remote의 feat/1 이 detach 되지는 않을까싶었는데 괜한 우려였다. 다만, local에서 checkout 하는 와중 파일이 없어지는 것을 확인했다. 늘 git graph를 잘 살피면서 작업을 해야 할 것 같다. 

(detached HEAD state 관련 글)

 

"이 과정 속에서 dev | origin과 main | origin 의 관계가 끊긴 것으로 보인다. " 를 검증하기 위하여 새로운 파일을 생성하고 push 할 때 github에서 자동 merge 를 요구하는지 확인해보자. 

 

dev에서 feature branch를 새로 판 후, 

해당 branch를 remote에도 생성한다. 

파일을 새로 한개 생성한다. 

(base) hajunuicBookPro:test hajunkim$ git push origin feat/2
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 323 bytes | 323.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/test-for-test-for-test/test

예상과는 다르게 pull request는 모든 branch에 대하여 merge 여부를 확인한다. 

다만 다른 점이 있다면, main branch 부터 따왔다고 git graph에 표기가 되어 있을 때는 dev에 merge를 마친 후에도

다음과 같이 main 에 merge pull request가 생성되었다. 

그러나 이번 경우에는 dev에 merge하고 나니 pull request 추가 요청이 없다. 

 

(base) hajunuicBookPro:test hajunkim$ git log --oneline
88c74b1 (HEAD -> feat/2, origin/feat/2) [EXP]: add feat/2 file
f76b186 (dev) Merge pull request #2 from test-for-test-for-test/feat/1
d2f82da (origin/feat/1, feat/1) [EXP]: experiment_v1
e9edaa8 (origin/main, main) [DOCS]: Add basic git commit files

git log 를 살펴보면 다음과 같이 정리된다. 

feat/2 file의 commit 까지 반영이 되었다. 

local에서의 commit 내역은 기록이 되고, remote의 merge 내역은 기록이 안되었다. 

(base) hajunuicBookPro:test hajunkim$ git log --all --oneline
2d15ef3 (origin/dev) Merge pull request #4 from test-for-test-for-test/feat/2
88c74b1 (HEAD -> feat/2, origin/feat/2) [EXP]: add feat/2 file
f76b186 (dev) Merge pull request #2 from test-for-test-for-test/feat/1
d2f82da (origin/feat/1, feat/1) [EXP]: experiment_v1
e9edaa8 (origin/main, main) [DOCS]: Add basic git commit files

log 를 모두 보기로 하면, 다음과 같이 merge 된 기록을 모두 확인 할 수 있다. 

local의 dev로 checkout해서 해당 내역을 반영해보자. 

local에서는 과거 commit으로 이동한 것이다 보니 feat2/의 v2.py file 이 삭제된다. 

git pull origin dev

해당 내역을 반영하고 다시 git log 를 찍어보자. 

(base) hajunuicBookPro:test hajunkim$ git log --all --oneline
2d15ef3 (HEAD -> dev, origin/dev) Merge pull request #4 from test-for-test-for-test/feat/2
88c74b1 (origin/feat/2, feat/2) [EXP]: add feat/2 file
f76b186 Merge pull request #2 from test-for-test-for-test/feat/1
d2f82da (origin/feat/1, feat/1) [EXP]: experiment_v1
e9edaa8 (origin/main, main) [DOCS]: Add basic git commit files

log 의 괄호안 내역은 다음과 같이 해석한다. 

https://stackoverflow.com/questions/57753595/how-to-interpret-the-brackets-in-the-git-log

 

It is a list of pointers which are pointing to the corresponding commit. I recommend you read about HEAD and origin.

 

그냥 현재 commit시 pointer 들의 동향으로 보인다.

e9edaa8 부터 차례대로 적어보면 

local: main , remote: origin/main 

local: feat/1, remote: origin/feat/1 

local: feat/2, remote: origin/feat/2

Head -> dev, remote: origin/dev (remote의 origin/feat/2 branch로 부터 local branch dev 로 pull)

 

git graph를 보는 것이 훨씬 직관적이고 전달력이 높은 것 같다. 

 

아직도 github 에 대해 완벽히 이해가 되었다고 할 수는 없지만 협업을 위한 github은 우선 이정도로 마무리한다. 

 

※추후 확인할 사항 

- local branch 에서 연결된 브랜치가 아니라, 연결된 브랜치를 따온 앞단의 branch에 push 

- local branch 끼리 merge 

- remote branch를 local에 받아오기 

 

remote branch를 local에 받아오기 

 

다음의 글을 참고: https://cjh5414.github.io/get-git-remote-branch/

 

원격 저장소에는 여러 개의 branch가 존재한다. 원격의 저장소를 pull 받은 후 $ git branch로 확인해보면 원격 저장소의 main 브랜치 외의 다른 branch 들은 받아지지 않는다.

 

원격 저장소의 branch 리스트를 확인해보자. 

git branch -r : 원격 저장소 branch 확인 
git branch -a : 원격, 로컬 저장소 branch 모두 확인

 

만약 원격 저장소의 dev/feature branch를 가져오고 싶다면, $ git checkout -t origin/dev/feature 로 가져올 수 있다. 

 

-t  [원격 저장소 branch 이름]: 로컬에 동일한 이름의 branch를 생성하면서 해당 branch로 checkout

 

-b  [생성할 branch 이름] [원격 저장소의 branch 이름]: 로컬에 branch 이름 수정하여 저장 후 checkout 

 

경우에 따라 수정 내역을 원격 저장소에 push 하지 않고 해당 branch를 참고하기 위해 로컬에 받는 경우도 있다.

 

git checkout [원격 저장소의 branch 이름]:아무런 옵션없이 원격 저장소의 branch를 checkout 하면 ‘detached HEAD’ 상태로 소스를 보고 변경 해볼 수도 있지만 변경사항들은 commit, push 할 수 없으며 다른 branch로 checkout하면 사라진다.

 

 

Comments