본문 바로가기
info : 유용한 정보, 체험기

Git 깃 이모저모 git fork , git branch , git clone, 포크(분기) 브랜치 클론

by 퇴근길에 삼남매가 알려드림 2022. 10. 23.

깃 포크, 깃 브랜치, 깃 클론. ( git fork vs git branch vs git clone) 비슷비슷한 것 같은데 어떤 점이 다를까?

목차

1. git fork
2. git branch
3. git clone

     

    깃 분기, 깃 포크, git fork

    깃 포크를 이용하면, 아예 다른 방향으로 코드를 발전시킬 수 있다. (divergent evolution of codebase).

    이 경우에는 기존의 레파지토리에 합치는 것을 고려하지 않는다

    만약, 깃 포크를 이용해서 메인 코드에 합치고 싶을 땐, pull request를 해야 한다.

     

    깃 포크를 이용하는 경우 :

    -예시 1. 출판된 논문의 타 연구자 코드를 이용하고, 수정하고 싶어서 깃 포크 (타 연구자 레파지토리 -> 내 레파지토리)

    • 그냥 코드를 이용하고 싶은 것일 수도 있고,
    • 코드에 새로운 내용을 넣고 싶은데 쓰기 권한이 없어서 일 수도 있고 (이 경우, 본인이 새로운 내용을 추가했다고 해도, 메인 코드에 이 내용이 추가될지 여부는 당연히 레파지토리 소유자에게 달려 있다. 할 수 있는 건 "pull request"를 해서 이런 기능을 새로 넣었는데, 넣고 싶으면 넣어볼래,라고 권유하는 정도!)
    • 코드를 새로운 방향으로 발전시키고 싶어서 (아예 합칠 예정이 없다. 그래서 fork - 분기! )

    의 경우에 이용한다.

     

    - 예시 2. 같은 팀의 코드를 보는데 나는 아예 다른 방향으로 코드를 발전시키고 싶어서 (different identity) 깃 포크

    • 기존 쓰기 권한은 있을 수 있지만, 후에 합칠 예정이 없다. (마찬가지로, 그래서 이게 분기점이 되는 것! )

     

    깃 포크를 하면 "전체 레파지토리 와 역사"를 포크 하는 시점에서 복사하여, 새로운 레파지토리를 만드는 것.

    포크 된 레파지토리는 기존 레파지토리에 합치려면 두 레파지토리의 전체 코드의 차이를 확인해야 한다. 


     

     

    git branch 깃 브랜치! 

     

    새로운 기능/변화을 위해서 임시로 만들어서 나중에 합친다. 즉 이 경우, 코드는 수렴한다 (convergent evolution of codebase)

    그리고 원래 하려던 기능을 다 만들었으면, 기존 메인 브랜치에 합치고, 임시로 만든 이 브랜치는 삭제한다. 브랜치에서 하는 커밋은 여전히 기존 레파지토리에 저장된다

     

    -예시 1: 이 코드에서 그림을 만드는 기능을 넣고 싶다. 

    그러면, 이제 브랜치 (예를 들어 브랜치 이름을 fig_add로 하면)를 만들고,  코드를 뚝딱뚝딱 고쳐서 원하는 기능을 하도록 만들고 코드가 문제없이 돌아가면 main브랜치에 merge 하고, fig_add 브랜치는 없앤다 (git branch -d fig_add).

     

    왜 이렇게 하냐면, main branch는 항상 작동해야 하기 때문이다.

    그렇기 때문에 중간에 뭔 바꾸거나, 새로운 모듈을 만들어서 넣거나 할 때 브랜치를 만들어서 (가지치기!) 변화를 주고, 이게 문제없이 작동하는 걸 확인한 후에, main에  merge 하는 것이다. 또한, 일하는 과정에서 fig_add 브랜치를 업데이트하면, 협업자들이 일 할 때 공통 레파지토리에서 코드를 복사하면서 fig_add 브랜치도 같이 다운로드하고 fig_add에서 만든 커밋 (어떤 게 바뀌었나) 도 다 볼 수 있다. 즉, 협업이 더 원활하게 이루어진다.

     

    이 때는 pull request 를 할 필요가 없다. 쓰기 권한이 있으므로 내가 일하고 있던 브랜치에서 수정된 부분을  git pull 하고, 다 끝나면 브랜치를 merge 한다.

    모든 변화를 커밋하고, 메인 브랜치로 옮기고, git_add를 merge 하는 것

    git checkout main
    -> 이제 main 브랜치로 이동함.
    git merge fig_add

    -> fig_add를 main에 합친다!  

    git branch -d fig_add

    ->이제 필요 없어진 fig_add 브랜치를 지운다.

     

    이때 항상 합치기 (merge)가 깨끗하게 일어나지 않는다. 이때 우리가 보는 게 충돌 (conflict) 메시지이다. 이땐 수동으로 변화를 적용해주는 게 필요하다. 

     

    참고: 그렇다면 git fetch 란? 

    git fetch는 원격 레파지토리에서 새로운 데이터를 다운받지만, 지금 일하고 있는 파일들과 합쳐지지는 않는 것이다. 그래서 원격 레파지토리에서 뭔가 일어하는지 확인은 해도 내가 지금 하는 일에 방해는 안 하는 것. 그렇기 때문에 git fetch는 자주 해야 한다!  

     

     

     

     

    side: git branch 확인하는 명령문

    git branch -a을 쓰면 지금 컴퓨터의 로컬 git 브랜치와, 원격 서버의 (remotes) git branch들이 있다.

    현재 내가 쓰고 있는 브랜치에 별표 (*)가 되어있다.

    git branch -a
    # output 
    * main
      remotes/origin/HEAD -> origin/main
      remotes/origin/main

    가장 기본 결과는 위와 같다.

    로컬에서 있는 브랜치는 main브랜치이고,

    원격 서버에 HEAD, main 이 있다.

    여기서 HEAD ,main 의 차이는 원격 서버를 '바로가기, symbolic'으로 가리키는지, 직접적으로 가리키는지 차이이다.

    보다 편하게, 우리 같은 초심자 입장에서는 HEAD는 우리가 깃 커밋을 할 때 어느 브랜치로 커밋을 하는지 말하는 것이라고 생각하면 된다. 원격에서는 반대로 로컬에 어디에 클론 하는지 가리키는 것으로 볼 수 있다.

     

    정확히 HEAD가 어딜 '바로가기'로 쓰는지는

     cat .git/HEAD 

    를 통해서 확인하면 된다.

     

    기본 세팅은 아래와 같다.
    ref: refs/heads/main

     

    즉, HEAD와 main 이 이 경우에는 같다. 하지만 꼭 main인 건 아니다. 

     

    하지만, 초보자 입장에서는 그냥 커밋할 때 브랜치 이름 써주면 된다. HEAD 개념 자체는 깃을 이해하는데 필요하긴 하다. 

     


     

    깃 클론, git clone

    레파지토리를  원격 머신 (깃 허브 등)에서 로컬 머신 (본인 데스크탑, 노트북)으로 복사하는 것. 

    깃 포크, 깃 브랜치와 개념이 조금 다르다. 

     

    깃 포크, 깃 브랜치, 깃 클론을 이용하는 경우는 다음과 같다.

     

    - 원격 서버에 본인이 소유한 레파지토리를 만들고 로컬 머신을 복사해서 일하려고 깃 클론.

    - 원격 서버에 있는 같이 일하는 팀 레파지토리를 로컬 머신에서 수정하려고 깃 클론.

    - 출판된 논문의 타 연구자 코드를 이용하고, 수정하고 싶어서 깃 포크 후 (타 연구자 레파지토리 -> 내 레파지토리), 로컬 머신에서 일하려고 깃 클론.

    - 본인이 소유한 레파지토리 (작동 잘 됨, main branch)에서 새로운 기능을 넣으려고, 로컬 머신에서 깃 브랜치 (이 경우 이미 깃 클론이 된 상태)

     


     

    마무리

    나중에 수정 후 원래 메인 코드에 합칠 예정이라면 깃 브랜치 (git branch) , 그게 아니라면 git fork.

    만약, 레파지토리에 쓰기 권한이 없으면 git fork.

    중간중간 원격 서버에서 무슨 일이 일어나나 확인하려면 git fetch는 자주 해주자.

     

    댓글


    TOP