Codesigner

[Git] Git Teamwork - Workflow & Generalizations 본문

Git /git

[Git] Git Teamwork - Workflow & Generalizations

eunsukimme 2019. 4. 9. 22:16

저번 포스팅에서는 science-quizzes라는 remote 레포지토리를 만들고, 이를 클론 하여 my-quizzes라는 로컬 레포지토리를 생성하였다. 그리고 science-quizzes에서 변경한 내용을 my-quizzes에 적용시키는 것 까지 실습하였다. 이번 포스팅에서는 Git을 활용한 teamworking의 workflow를 알아보고 my-quizzes에서 만든 변경사항을 science-quizzes에 적용해보며 저번 포스팅에서 배웠던 내용들과 함께 teamworking 방법을 정리해보는 시간을 가져보자

 

 

 

Git workflow

 

현재 우리는 origin/master에 있는 내용을 master 브랜치에 merge 하였다. 즉, remote 의 변경사항을 내 로컬 레포지토리에 적용시킨 것으로 내 로컬 레포지토리는 최신의 상태를 유지하게 된다. Git에서의 협업 workflow를 정리하자면 다음과 같다:

  1. remote의 변경 사항을 fetch 하고 merge 한다

  2. 작업할 새로운 브랜치를 생성한다

  3. 생성한 브랜치에서 커밋을 만들면서 작업을 진행한다

  4. 작업하는 동안 업데이트 된 remote로부터 fetch 하고 merge 한다

  5. 작업한 브랜치의 내용을 remote 로 push 한다

1 ~ 4 단계는 merge conflict 를 예방하기 위해 반복적으로 이뤄지는 단계이다. 5단계는 바로 다음 섹션에서 더 자세히 알아보도록 하고, 이번에는 remote에 push 하기 위해 로컬 레포지토리에서 quiz3.txt를 생성하고 커밋해보자

C:\Users\glafu\Desktop\my-quizzes>vim quiz3.txt

C:\Users\glafu\Desktop\my-quizzes>cat quiz3.txt
which one is the correct?
1) all human being is animal
2) all animal is human being
3) all animal is plant
4) all plant is animal

C:\Users\glafu\Desktop\my-quizzes>git add .

C:\Users\glafu\Desktop\my-quizzes>git commit -m "Add a new quiz3"
[master e8b41cb] Add a new quiz3
 1 file changed, 5 insertions(+)
 create mode 100644 quiz3.txt

C:\Users\glafu\Desktop\my-quizzes>

자, 이제 우리는 방금 생성한 quiz3.txt 를 remote로 push 할 준비가 되었다

 

 

 

git push

 

우리가 방금 생성한 quiz3.txt 를 다른 선생님들도 볼 수 있도록 remote에 등록시키자. 커맨드는 다음과 같다

git push origin your_branch_name

위 명령은 주어진 이름의 브랜치의 변경 사항들을 remote(origin)에 적용(push) 하는 것을 의미한다. 그리하여 Alice를 포함한 다른 선생님들이 remote를 fetch 한 후 merge 하여 최종적으로 우리가 만든 quiz3.txt를 볼 수 있게 되는 것이다. 우리가 작업한 quiz3.txt를 push 해보자

C:\Users\glafu\Desktop\my-quizzes>git push origin master
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 376 bytes | 75.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote:
remote: You can set the 'receive.denyCurrentBranch' configuration variable
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote:
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To C:/Users/glafu/Desktop/./science-quizzes
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'C:/Users/glafu/Desktop/./science-quizzes'

C:\Users\glafu\Desktop\my-quizzes>

에러가 뜨면서 push 가 되지 않는다. 에러 메세지는 길게 주저리주저리 설명하고 있지만 그 이유는 간단하다. 우리가 만든 remote 인 science-quizzes는 non-bare 레포지토리이기 때문이다

 

 

 

bare and non-bare repository

 

Git 에서는 레포지토리를 두 가지로 분류하고 있다. bare 레포지토리와 non-bare 레포지토리가 바로 그것이다. 이 두 레포지토리를 설명하자면 다음과 같다

 

  • bare repository - 어떠한 Working copy 들도 갖고 있지 않고 디폴트로 remote(origin)을 가지지 않는 레포지토리이다. 즉, 작업한 내용을 저장하기 위한 레포지토리

  • non-bare repository - Working copy 들을 들고 있으며 디폴트로 remote(origin)을 가지는 레포지토리. 순수하게 원본을 복사한 것과 같다. 즉, 작업을 진행하기 위한 레포지토리

우리가 처음 만든 remote 인 science-quizzes 에서 quiz1.txt 파일을 생성했던 걸 기억할 것이다. 이는 non-bare 레포지토리로, 작업이 실제로 이루어지는 레포지토리이다. 만약 bare 레포지토리로 생성하려면 다음과 같은 명령을 해주면 된다

git init --bare

이는 해당 레포지토리를 bare 레포지토리로 생성하는 기능을 한다. 우리는 처음 science-quizzes 를 init 할 때 --bare 옵션을 주지 않았기 때문에 non-bare 레포지토리가 된 것이다. 그런데 non-bare 레포지토리라는 것이 왜 my-quizzes에서 push 할 수 없다는 이유가 되는 것일까?

 

그에 대한 설명은 다음과 같다. non-bare 레포지토리는 작업이 이루어지는 레포지토리라고 위에서 설명했다. 만약 당신이 열심히 작업한 레포지토리가 있는데, 그걸 다른 사람이 클론하여 이상하게 만들어 버린 뒤 push 하면 어떻게 될까? 상상만 해도 끔찍할 것이다. 그러므로 당신이 작업하는 레포지토리에 다른 복사본이 push 하는 걸 막을 수 있는 policy 가 필요할 것이다. 그것이 바로 bare과 non-bare 레포지토리를 구분 짓는 이유이다. 즉, non-bare 레포지토리에 함부로 push 하지 못 한다. 이 것이 바로 Github에서 pull request 가 동작하는 방법이다. 우리는 remote 소유자에게 pull request 만 할 수 있을 뿐, 강제로 push 할 수는 없다. 

 

 

 

git push 2

 

그러면 여기서 sicence-quizzes 로 push 할 방법이 없는 것인가? 그렇지 않다. 브랜치를 생성하여 그 브랜치로 이동한 뒤, push 하면 remote에서 브랜치가 생성되고 해당 브랜치로 변경사항을 적용시킬 수 있다. 다음과 같이 새로운 브랜치를 만들고 그 브랜치로 이동해보자

C:\Users\glafu\Desktop\my-quizzes>git branch new_branch

C:\Users\glafu\Desktop\my-quizzes>git checkout new_branch
Switched to branch 'new_branch'

C:\Users\glafu\Desktop\my-quizzes>

그런 다음 현재 브랜치의 작업 내용을 origin 에 push 하도록 하자

C:\Users\glafu\Desktop\my-quizzes>git push origin new_branch
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 376 bytes | 188.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To C:/Users/glafu/Desktop/./science-quizzes
 * [new branch]      new_branch -> new_branch

C:\Users\glafu\Desktop\my-quizzes>

push가 되었다! 바로 remote 이 master 브랜치가 아닌 우리가 생성한 브랜치와 같은 브랜치에 push 가 되었는데, 이를 확인해보도록 하자. science-quizzes로 이동하여 git branch 명령을 실행해보자

C:\Users\glafu\Desktop\my-quizzes>cd ../science-quizzes

C:\Users\glafu\Desktop\science-quizzes>git branch -a
* master
  new_branch

C:\Users\glafu\Desktop\science-quizzes>

새로운 브랜치가 생성되었다. 브랜치를 이동하여 mater 에서의 파일들과 new_branch에서의 내용들을 비교해보자

C:\Users\glafu\Desktop\science-quizzes>git branch -a
* master
  new_branch

C:\Users\glafu\Desktop\science-quizzes>ls
quiz1.txt  quiz2.txt

C:\Users\glafu\Desktop\science-quizzes>git checkout new_branch
Switched to branch 'new_branch'

C:\Users\glafu\Desktop\science-quizzes>ls
quiz1.txt  quiz2.txt  quiz3.txt

C:\Users\glafu\Desktop\science-quizzes>

new_branchmaster 에는 없는 quiz3.txt 가 생성된 것을 확인할 수 있다! 이제 Alice와 다른 선생님들은 그들의 로컬 레포지토리를 fetch & merge 함으로써 업데이트시켜 우리가 만든 quiz3.txt를 확인할 수 있다!

 

 

 

generalizations

 

축하한다! 당신은 이제 당장 협업에 뛰어들 수 있을 정도의 충분한 지식을 쌓았다. 이제 지금까지 배운것들을 정리해보자

 

  • remote는 Git 프로젝트 외부에 존재하는 공유 Git 레포지토리이다. remote는 웹, 공유 네트워크 혹은 로컬 컴퓨터의 한 폴더가 될 수 있다

  • Git의 협업 workflow는 여러 협업자가 같은 Git 프로젝트를 진행하는 데 있어서 merge conflict를 예방하여 유연한 개발을 가능하게 한다

우리는 또한 다음과 같은 커맨드들을 배웠다

 

  • git clone - remote 의 복사본을 생성한다

  • git remote -v - Git 프로젝트의 remote를 나열한다

  • git fetch - remote 의 변경사항을 로컬 레포지토리로 가져온다. 이 변경사항은 origin/master 브랜치에 저장된다

  • git merge origin/master - origin/master 브랜치의 내용을 현재 브랜치로 복사한다

  • git push origin <branch_name> - remote(origin)로 현재 브랜치 내용을 push 한다

우리는 remote를 로컬 컴퓨터에서 생성하였지만 대부분의 Git 프로젝트의 경우 Github에 remote를 호스팅 한다. Github는 Git 프로젝트들을 호스팅 하는 사이트인데, Github를 사용하면 어디에서든지 당신의 프로젝트에 접근할 수 있다. Github를 사용하는 방법은 추후 포스팅하도록 하고, 이번 포스팅에서 배운 내용들을 머릿속에서 잘 정리해 보도록 하자

 

 

Comments