5 minute read

이틀에 걸쳐 Git을 이용하여 Github 저장소를 관리하고 팀 협업의 전체적인 흐름을 배웠다.

이전 프로젝트를 진행할 때는 Github Desktop을 이용하여 GUI로 간편하게 작업했었는데, git을 이용하여 작업하는 방법도 배웠다.

기본적인 명령어(Ex: add, commit, push, pull)는 어느 정도 알고 있었는데, 충돌이 일어났을 때의 대처법과 잘못 push한 파일들을 되돌리는 방법 등 몰랐던 부분들을 강사분께서 알려주셨다.

내가 몰랐던 부분을 배우는지라 확실히 집중이 더 잘되었다.


1. Git


리눅스 커널 관리를 위해 만든 분산형 버전 관리 시스템으로 구조가 단순하고 빠른 속도를 자랑한다.

Branch를 이용하여 비선형적 개발을 할 수 있으며 소스 코드를 주고받지 않고 동시 작업이 가능하여 생산성이 증가하고, 인터넷 연결없이 개발하다가 인터넷 연결 시 한번에 push가 가능하다.


1.1 기본 명령어


  • Clone

    git bash에서 가장 먼저 작업해주어야 하는 일은 github repository를 내 로컬과 연결해주어야 한다.

    그러기 위해서 repository를 생성하고 url 주소를 가져와 다음의 명령어를 실행한다.

    
      $ git clone [REPO_ADDRESS]
    
    

    clone이 완료되면 다음과 같이 각각의 저장소가 복제되어 로컬에서 접속할 수 있게 된다.

    image.png



  • Status

    현재 git이 add하고 있었는지, commit하고 있었는지 등 사용자가 진행하던 작업의 상태를 볼 수 있는 명령어이다.

    git add 및 commit, push 등 어떤 작업을 수행해도 되는지 확인 후 진행한다.

    
      $ git status
    
    

    다음과 같이 더 이상 commit할 것이 없고 working tree가 비어있다면 add 작업을 진행해도 된다.

    image.png



  • add

    작업 디렉토리 상의 변경 내용을 스테이징 영역에 추가하는 명령어이다.

    자신이 작업했던 내용은 commit 하기 전 까지는 git 저장소의 변경 이력에는 아무것도 남지 않는다.

    
      $ git add [FILE_NAME]
    
    

    다음과 같이 example.py를 add 할 수 있다.

    image.png



  • commit

    변경된 코드(작업했던 내용)를 기록으로 남긴다.

    commit message를 통해 어떤 내용을 작업했는지 간단한 설명을 남기고, Conventional Commits를 참고하여 작성한다.

    
      $ git commit
    
    

    Conventional Commits는 다음과 같다.

    Prefix 설명
    feat 기능 개발 관련
    fix 오류 개선 혹은 버그 패치
    docs 문서화 작업
    test 테스트 코드 관련
    conf 환경설정 관련
    build 빌드 작업 관련
    ci Continuous Integration 관련
    chore 패키지 매니저, 스크립트 등
    style 코드 포매팅 (세미콜론, 들여쓰기 등) 관련

    명령어를 실행하면서 -m 명령어를 통해 바로 commit message를 작성할 수 있으나 해당 작업이 무슨 작업인지 헷갈릴 때에는 vi로 직접 확인한 뒤 변경하는 것이 옳다.

    image.png



  • push

    add 및 commit으로 기록했던 내용들을 Repository에 올리는 명령어이다.

    다음과 같은 명령어로 실행할 수 있다.

    
      $ git push [REMOTE] [BRANCH]
    
    

    다음과 같이 push 한 다음 Repository를 확인해보면 파일이 업로드된 것을 볼 수 있다.

    image.png

    image.png


1.2 .gitignore / Conflict 해결


  • .gitignore

    .gitignore 파일은 특정 파일 or 특정 디렉토리를 추적하지 않도록 명시하기 위한 파일이다.

    즉, 어떤 파일을 repository에 올릴 때, 불필요한 파일들이 올라가는 것을 방지할 때 사용하는 필수적인 파일이다.

    .gitignore.io

    위의 사이트에서 프로젝트에 사용되는 운영체제, 프로그래밍 언어, 개발 환경 등에 맞춰 생성된 내용을 붙여넣기만 해주면 된다.



  • branch

    branch는 초기 코드에서 분기점을 생성하여 독립적으로 코드를 변경하도록 하는 모델이다.

    다음의 명령어를 통해 현재 어떤 branch가 존재하는지 확인할 수 있다.

    
      $ git branch
    
    

    또한, 다음의 명령어를 통해 새로운 브랜치를 생성한 다음

    
      $ git branch [BRANCH_NAME]
    
    

    해당 명령어를 통해 원하는 branch로 전환할 수 있다.

    
      $ git switch [BRANCH_NAME]
    
    

    만약 branch를 삭제할 때에는 다음과 같이 작성해 주면 된다.

    
      $ git branch -D [BRANCH_NAME]
    
    

  • merge

    초기 코드에서 branch를 이용하여 분기점이 생성된 후 다시 합칠 때 충돌이 일어날 수 있다.

    예를 들어 초기 코드에서 for 반복문이 다음과 같이 작성되어 있고

    
      for i in range(20) :
    
          print(i)
    
    

    branch로 분기점이 생성된 다음 해당 branch에서 작업한 내용이 다음과 같다면

    
      for i in range(30) :
    
          print(i)
    
    

    for 문의 범위가 같지 않기에 충돌이 발생할 것이다.

    예를 들어 main에서 작성된 처음 파일이 다음과 같을 때,


    
      def test() :
    
          for i in range(20) :
    
              print(i)
    
    
    
      test()
    
    

    해당 내용을 add 후 commit한 뒤 branch를 생성하여 해당 브랜치에서 다음과 같은 작업을 수행했다고 치자.


    
      def test() :
    
          for i in range(30) :
    
              print(i)
    
    
    
      test()
    
    

    다시 main에서 다음과 같이 파일을 수정한다.


    
      def test() :
    
          for i in range(40) :
    
              print(i)
    
    
    
      test()
    
    

    이제 main에서 두 파일을 합병한다면 다음과 같이 충돌이 발생한다.

    image.png

    vi 편집기로 확인하면 다음과 같이 코드 사이에 문자들이 존재하고, 중복된 부분이 존재한다.

    image.png

    이를 해결하여 add 후 commit을 한다면 충돌을 해결할 수 있다.



  • rebase

    rebase는 각각의 branch를 하나의 branch로 덮어쓰는 방식을 사용한다.

    작업했던 branch 하나에서 다음의 명령어를 통해 진행할 수 있다.

    
      $ git rebase main
    
    

1.3 git branching strategy


branch를 이용하여 git 버전을 관리하는 전략으로는 크게 3가지가 존재한다.

  • git flow

    가장 전통적이고 많이 쓰이는 모델이다. 각 단계가 명확히 구분(master, develop, feature 등)되어 역할이 존재하며 복잡하다.

    git flow

  • github flow

    브랜치 모델을 단순화한 것으로, CI 의존성이 높고, github의 pull requests가 있어야 한다.

    github flow

  • gitlab flow

    github flow에서 배포 단계까지 추가한 것이다.

    gitlb flow


1.4 Trouble-shoot

작업 중(후) 해결해야할 문제가 발생하여 branch 이동, push 취소 등의 작업을 수행하는 명령어들이다.


  • Stash

    작업 중 branch 이동이 필요하거나 작업사항을 잠시 미뤄둘 때 사용하는 명령어이다.

    
      $ git stash save '[MESSAGE]'
    
    

    위의 명령어로 작업사항을 임시 저장소에 쌓을 수 있고 다음의 명령어를 통해 가장 최근의 작업사항을 복구할 수 있다.

    
      git stash pop
    
    

    pop 뒤에 index를 넣어 원하는 작업을 복구시킬 수도 있다.



  • Undo

    작업 디렉토리에서 변경사항을 취소할 때 사용하는 명령어이다.

    어떤 작업을 수행해서 파일이 변경되었는데, 가장 최신의 commit 상태로 되돌릴 수 있다.

    
      $ git restore [FILE_NAME]
    
    

    만약 git add 명령어로 스테이징 영역에 올라간 상태라면 다음과 같이 취소할 수 있다.

    
      $ git restore --staged [FILE_NAME]
    
    


  • Reset, Revert

    reset은 repository에 업로드 되었을 때 이를 없었던 일로 되돌리는 명령어이다.

    하지만 해당 명령어를 사용한다 하더라도 나의 local과, clone한 remote repository에서만 지워질 뿐, 다른 local에 남아있기에 충돌이 발생할 가능성이 존재한다.

    따라서 잘못된 push로 특정 시점으로 되돌려야 하는 상황이라면 revert를 이용하여 잘못을 인정하고 되돌리는 편이 좋다.

    
      $ git revert --no-commit [COMMIT_NAME]
    
    

    reset을 사용하여 없었던 일로 만드는 것은 사실 불가능하다. 기록도 남고, 나의 local에서만 지워지기에 팀 협업에 있어 근본적으로 문제를 해결할 방법이 되지 못한다.

    따라서 잘못된 점을 발견했다면 팀원들에게 전달, 문제를 인식하고 이를 해결할 방법을 모색하는 방향으로 진행해야 한다.


2. 마치며


이전까지 프로젝트를 진행할 때 github desktop을 굉장히 유용하게 썼었다.

하지만 git을 제대로 배우고 난 다음 문제를 해결하는 방법, 프로젝트 관리 등 github desktop에서 해결하기 까다로운 문제들을 git을 이용하여 해결하는 방법을 배우고 나니 git을 먼저 습득한 다음 GUI 도구들을 이용하는 것이 옳다는 생각이 들었다.

또한 팀 협업에 있어 역할 분담소통의 중요성을 깨닫는 계기가 되었다.


지금까지 나는 어떤 프로젝트 or 새로운 점을 배웠을 때, 한번에 정리하여 github blog에 업로드하였다.

해당 과정에서 시간이 좀 지난 작업의 경우 전부 기억하는 것은 힘들었고, 기록에 남기는 것은 더더욱 힘들었다.

이를 방지하기 위해 내가 오늘 어떤 점을 배웠고, 어떤 일을 하였는지 간단하게 기록하는 TIL을 작성하는 방법을 강사님께서 알려주셨다.

확실히 이번애 git에 대한 내용을 정리할 때도 하루하루 했던 일들을 정리하고나니 전체로 합치는 과정에서도 더욱 수월하게 진행할 수 있었다.


이번 git 강의는 팀 협업에 있어 많은 것을 얻어갈 수 있는 강의였다.

이전에는 매번 직접적인 소통을 통해 프로젝트를 관리하는 방식을 사용하여 팀원끼리의 시간을 맞춰 진행했었다면 git을 이용하여 기록을 남겨 팀원 각각의 시간에 맞춰 작업 및 피드백을 할 수 있다는 점에서 훨씬 편리하게 관리할 수 있었다.