Joonas' Note

Joonas' Note

All about git - 원격 저장소와 작업하는 법(fetch/push/pull) 본문

개발

All about git - 원격 저장소와 작업하는 법(fetch/push/pull)

2023. 8. 20. 23:40 joonas

    git에 대한 기본적이면서 핵심이 되는 컨셉은 아래 글에서 정리했다.
    원격 저장소에 대한 간단한 설명도 있으니 먼저 읽어보는 것을 권한다.

     

    All about git - 핵심 개념 정리

    소스코드를 저장할 개념으로 학생때부터 git과 github을 꾸준히 사용했는데, 어느덧 거의 10년차가 되었다. 그렇다보니 주변에 git 에 대한 내용을 설명하는 경우가 많았는데, 사람들이 항상 혼란스

    blog.joonas.io


    함께 작업하기

    여러 사람들과 하나의 레포지토리(repository)로 공동 작업하는 것은 여러 방법이 있다.

    문제는 이 하나인 레포지토리의 코드가 가만히 있지 않다는 것이다.

    일반적으로 각 머신에서 clone 을 받은 경우의 상황

    push

    현재 내 로컬의 브랜치 상태를 원격 레포지토리(예를 들면 GitHub)에 업로드하고 싶은 경우, push 커맨드를 사용한다.

    git push origin <branch>

    <branch> 부분을 생략한다면, 현재 브랜치를 push 한다.

    만약에 원격 저장소(remote)에서는 알지 못하는 새로운 이름의 브랜치라면, 아래와 같이 -u 옵션과 함께 실행해야한다.
    이는 원격 저장소에 새로운 브랜치를 만들어 줄 것을 요청하는 것이다.

    git push origin -u <branch>

    다른 브랜치명으로 push하기

    브랜치명 사이에 콜론을 넣으면 된다.

    git push <remote> <로컬 브랜치>:<올라갈 목적지 브랜치 명>
    # git push origin dev:dev42

    즉, 기본값은 두 이름이 동일하도록 push 되고 있던 것이었다.

    git push origin main
    # git push origin main:main (동일)

    실제로 실행했을 때의 결과는 아래와 같다.

    git push 커맨드 실행 결과
    dev가 아닌 dev-42 브랜치명로 push 되었다.

    현재 브랜치 이름은 dev 인데, dev42 라는 브랜치로 업로드 된 것을 확인할 수 있다.
    remote에 없던 브랜치라서 새로 만드는 옵션(-u)과 함께 실행하였다.

    자주 보는 오류들

    로컬 브랜치와 원격 브랜치가 서로 충돌이 난 경우
    해결 방법은, pull 을 먼저 수행한 후에 충돌을 해결하고 다시 push 하면 된다.
    (강제로 덮어쓰는 방법으로 -f 옵션이 있는데, 이건 정확히 알고 사용하는 것을 추천한다.)

    ME@~ (devvvvvv) $ git push origin
    To https://github.com/joonas-yoon/test
     ! [rejected]        devvvvvv -> devvvvvv (fetch first)
    error: failed to push some refs to 'https://github.com/joonas-yoon/test'
    hint: Updates were rejected because the remote contains work that you do
    hint: not have locally. This is usually caused by another repository pushing
    hint: to the same ref. You may want to first integrate the remote changes
    hint: (e.g., 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.

     

    로컬에 없는 브랜치 이름을 push 하려고 한 경우

    ME@~ (devvvvvv +) $ git push origin -u wrongbranchname
    error: src refspec wrongbranchname does not match any
    error: failed to push some refs to 'https://github.com/joonas-yoon/test'

    origin과 연결된 remote에 그런 브랜치가 없는 경우

    ME@~ (devvvvvv +) $ git push origin
    fatal: The current branch devvvvvv has no upstream branch.
    To push the current branch and set the remote as upstream, use
    
        git push --set-upstream origin devvvvvv
    
    To have this happen automatically for branches without a tracking
    upstream, see 'push.autoSetupRemote' in 'git help config'.

    fetch

    다음으로 알아볼 커맨드는 원격 저장소의 상태를 조회하는 fetch 이다.

     

    Git - git-fetch Documentation

    In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent. Git supports ssh, git, http, and https protoco

    git-scm.com

    git은 로컬에 있는 프로그램이고, 로컬에 있는 파일들을 대상으로 버전 관리를 진행하기 때문에, 다른 레포지토리의 상태를 알기 위해서는 fetch 를 통해 조회해야한다.

    git fetch <repository name>

    여기서 <repository name>은 로컬에 설정한 remote 이름, 예를 들면 origin과 같은 것들이다.
    무슨 이름으로 설정되었는 지 확인하고 싶다면, 아래 커맨드로 확인할 수 있다.

    git remote -v

    fetch를 실행하면 로컬 레포지토리에 없는 원격 레포지토리의 브랜치 상태를 아래와 같이 조회해볼 수 있다.

    origin에 변경이 있다면 fetch 로 받아온다

    단순히 조회라는 것을 강조하는 이유는, fetch를 실행했다고 해서 브랜치를 실제로 가져온 것은 아니기 때문이다.
    git에서 브랜치를 조회하는 git branch -l 을 실행해보고 실제로 저장되는 내부 DB를 확인해도, 로컬 브랜치와는 구분되어있다.

    fetch 후 branch 확인


    pull

    원격지로부터 브랜치를 실제로 가져오는(다운로드 받는) 커맨드는 pull 이다.
    커맨드 이름이 pull 이라서 흔히 "땡겨온다"라고 한다.

    git pull <remote> <branch>

    하지만 pull 은 설명할 내용이 없다.
    왜냐하면 pull = fetch + rebase/merge 이기 때문이다.

    # 현재 브랜치 이름이 xxx 라고 가정한다면
    git fetch origin
    git merge origin/xxx xxx
    # 또는 git rebase origin/xxx xxx

    즉, 원격 저장소(remote)의 상태를 조회(fetch)한 후에, 그 브랜치를 로컬 브랜치와 합치는(rebase/merge) 것이다.
    충돌이 발생하지 않는다면, 없는 커밋을 그대로 가져오면 되므로 (fast-forward) 아무것도 하지 않아도 된다.

    하지만 그렇지 않은 경우에는 rebase 또는 merge 를 통해 해결해야한다.
    기본값은 merge 인데, git config 에서 변경할 수 있다.

    만약 합치는 방법을 직접 지정하고 싶다면, 아래와 같이 pull 커맨드의 옵션으로 지정할 수 있다.

    git pull origin --rebase

    merge과 rebase의 차이에 대해서는 이 포스트를 참고하기를 바란다.

    실제로 해보기

    먼저 두 브랜치가 충돌이 난 상황을 만들었다.

    원격 브랜치 origin/devvvvvv 는 (커밋 A → 커밋 B) 인 상태이고,
    로컬 브랜치 devvvvvv 는 커밋 A 에서 브랜치를 딴 상태라, (커밋 A → 커밋 C) 인 상태이다.

    pull 은 fetch + merge 와 동일하므로 순서대로 진행해보면 아래와 같다.

    fetch + merge

    merge 단계에서 분명히 충돌이 있음을 확인했고, 파일 내용을 보고 직접 해결해준다.

    합쳐져야하는 파일의 내용을 직접 수정 후 add

    충돌난 부분을 해결하고 merge 단계를 마저 진행하면 아래와 같이 완료된다.
    git 그래프를 확인해보면 합쳐진 커밋(merge commit)이 생긴 것을 볼 수 있다.


    관련 글

     

    All about git - 충돌(conflict)과 merge/rebase 쉽게 이해하기

    git에 대한 기본적인 컨셉과 용어는 아래의 글에서 정리했다. All about git - 핵심 개념 정리 소스코드를 저장할 개념으로 학생때부터 git과 github을 꾸준히 사용했는데, 어느덧 거의 10년차가 되었다.

    blog.joonas.io

     

    Git - git-push Documentation

    In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent. Git supports ssh, git, http, and https protoco

    git-scm.com

     

    Git - git-pull Documentation

    Often people use git pull without giving any parameter. Traditionally, this has been equivalent to saying git pull origin. However, when configuration branch. .remote is present while on branch , that value is used instead of origin. In order to determine

    git-scm.com

     

    Comments