세미나

[교육] Git & GitHub 중급

nineDeveloper 2019. 10. 17. 08:43
728x90

규칙

Look
슬라이드 내용에 집중합니다.

D.I.Y
직접 실습합니다.

Git Rebase

Merge [Look]

  • experiment를 master로 merge

  • C3, C4를 조상으로 하는 새로운 Merge 커밋 C5 생성

Rebase [Look]


  • feature를 master에 rebase한다란
  • feature의 master에 대한 base(feature와 master의 공통 조상)를 master로 변경(rebase)

Rebase 과정 [Look]

  • base에서 현재 브랜치까지의 변경 사항을 구한다.

  • head를 master로 변경

  • 변경사항 1을 적용하여 새로운 커밋 C4'를 생성

  • 변경사항 2를 적용하여 새로운 커밋 C5'를 생성
  • feature가 C5'를 가리키도록 함
  • C4와 C5는 git 저장소 내에는 존재하나 찾아 갈 수 있는 포인터가 없는 상태(dangling)
  • 여기까지가 rebase

  • rebase된 feature를 master로 fast-foward하지 않고 merge
  • rebase를 이용한 브랜치 합치기 완료

 

SourceTree를 이용한 rebase [Look]

 

  • 연습을 위한 로컬 저장소 생성

 

  • 적당한 위치에 생성

  • master와 feature 브랜치가 갈라지도록 커밋을 생성
    • master에서 최초 커밋을 생성
    • feature 브랜치 생성
    • feature에서 커밋을 두개 생성
    • master에서 커밋을 하나 생성
    • feature로 체크아웃

 

  • feature를 master에 rebase
    • feature에 체크아웃된 상태에서 master의 컨텍스트 메뉴에서 master로 현재 바뀐 내용 재배치(현재 변경사항을 master에 재배치) 선택

 


 

  • 484f73a가 base 였던 0e28385, 7b3d74d 커밋이 master 브랜치가 가리키는 b739862 커밋 이후로 새로운 커밋 7e9463, b12731a를 생성하며 rebase

 

  • master로 체크아웃한 후 feature를 merge

  • rebase를 통행 feature를 master에 반영하며 커밋 그래프가 일렬이 된 모습

SourceTree를 이용한 rebase [DIY]

  • 로컬 저장소를 생성하세요
  • master와 feature 브랜치가 갈라지도록 커밋을 생성하세요
  • feature를 master에 rebase하세요
  • master에 feature를 merge하세요

대화형 rebase [Look]

  • 커밋을 합치고, 없애고, 순서를 바꿀 수 있다!
  • 커밋 메시지를 바꾸고 중간 커밋의 내용을 바꿀 수 있다!

커밋 합치기 [Look]

  • 변경사항 1과 변경사항 2를 동시에 적용하여 C2/3를 생성
  • C2와 C3을 하나로 합치는 효과

SourceTree를 이용한 커밋 합치기 [Look]

  • 연습을 위해 master에 커밋을 적당히 생성
  • feature 브랜치를 삭제

 

  • 7ec9463, b12731a를 하나로 합치기
  • base로 사용할 b739862의 컨텍스트 메뉴에서 'b739862' 하위 요소 대화식 재배치...(자식 커밋을 쌍방향 재배치...) 선택

 

  • 합치려는 커밋 중 제일 마지막 커밋을 선택하고 이전 것과 합치기(이전 커밋과 합치기)를 클릭

 

  • 커밋 두개가 하나로 합쳐지는 것 확인

 

  • 더블클릭하여 커밋 메시지를 다시 작성 가능

 

  • 변경사항을 확인하고 확인 클릭

 

  • 7ec9463, b12731a가 하나로 합쳐져 d3da71e가 되었고 이후 커밋은 부모가 달라졌기 때문에 새로운 해시로 생성
  • 예제는 두개의 커밋을 합쳤지만 세개 이상도 합칠 수 있습니다
  • 그래프가 한줄로 안 보이는 경우는 feature 브랜치를 삭제하지 않아서 이전 커밋에 도달할 수 있기 때문
    • 어쨌든 master만 봤을 경우 두개의 커밋이 하나로 합쳐진 결과는 다름이 없습니다

SourceTree를 이용한 커밋 합치기 [DIY]

  • 대화형 rebase 기능을 이용하여 두개의 커밋을 하나로 합쳐보세요

커밋 없애기 [Look]

  • base인 C1을 head가 가리키고 변경사항 1을 적용
    • 적용 결과가 이전과 다르지 않기 때문에 git에서는 새로운 C2' 커밋을 생성하지 않고 C2를 그대로 사용
  • 변경사항 2를 생략하고 적용
  • C3을 없애는 효과

SourceTree를 이용한 커밋 없애기 [Look]

  • d3da71e를 없애기 위해 b739862에서 대화형 rebase 진입

 

  • 커밋을 선택하고 삭제 클릭

 

  • 삭제되는 것을 확인하고 확인 클릭

 

  • d3da71e가 삭제되고 이후 커밋들은 새로운 해시로 생성

SourceTree를 이용한 커밋 없애기 [DIY]

  • SourceTree를 이용하여 이전 커밋 중 하나를 없애보세요

커밋 순서 바꾸기 [Look]

  • 변경사항을 2, 1, 3 순서로 적용
  • C2, C3의 순서를 바꾼 효과

SourceTree를 이용한 커밋 순서 바꾸기 [Look]

  • 22efded와 7dbcc81의 순서를 바꾸기 위해 b739862에서 대화형 rebase 진입

 

  • 커밋을 선택한 후 방향 버튼 클릭

 

  • 순서가 변경된 것 확인한 후 확인 클릭

 

  • 커밋의 순서가 변경되고 새로운 해시로 생성된 것 확인

SourceTree를 이용한 커밋 순서 바꾸기 [DIY]

  • SourceTree를 이용하여 커밋의 순서를 바꿔보세요

커밋 메시지 바꾸기 [Look]

  • 변경사항 2를 적용하며 커밋메시지를 변경

SourceTree를 이용한 커밋 메시지 바꾸기 [Look]

  • 대화형 rebase 진입

  • 변경하고자하는 커밋에서 더블클릭한 후 메시지 편집

 

  • 커밋 메시지가 변경된 것 확인
  • 그리고 당연히 커밋도 새로운 해시 값으로 생성 됨

  • 아쉽게도 Windows 버전은 rebase에서 커밋 메시지를 변경하면 한글이 ?로 나오는 버그가 존재...

  • 만약 마지막 커밋만 다시 고치고 싶다면 SourceTree의 커밋 창에서 커밋 옵션의 마지막 커밋 수정을 선택하면 됩니다.
  • 커밋 메시지를 고치면 당연히 새로운 해시 값의 커밋이 생성됩니다

SourceTree를 이용한 커밋 메시지 바꾸기 [Look]

  • SourceTree를 이용하여 커밋 메시지를 변경해 보세요.

중간 커밋의 내용 바꾸기 [Look]

  • C3을 amend 하겠다고 표시후 rebase 시작

  • 변경사항 1을 적용한 후 rebase를 잠시 멈춤

  • 사용자가 추가로 수정한 후 커밋

  • git rebase --continue 명령을 통해 rebase를 계속 진행하여 마무리
  • 예제는 이전 커밋의 내용을 기반으로 변경하는 예이지만 커밋을 두번 한다든지 rebase가 멈춘 후 다시 진행하기 전까지 자유롭게 변경하면 됩니다

SourceTree를 이용한 중간 커밋의 내용 바꾸기 [Look]

  • 빈 f 파일만 추가된 4783491 커밋의 내용을 바꿔 봅니다

  • b739862에서 대화형 rebase에 진입

 

  • 내용을 바꾸고자 하는 커밋에 체크한후 확인 클릭

  • rebase가 변경하고자하는 커밋에서 일시정지된 것 확인

  • 빈 파일 f에 내용을 추가하고
  • 새로운 파일을 하나 추가
  • stage에 올리고

  • 커밋 창에서 마지막 커밋 수정

  • 커밋

  • 4783491을 amend한 새로운 커밋 9762ff1이 생성 됨
  • rebase를 계속하면 9762ff1에 4783491에서 022b601 사이의 변경사항을 적용하여 새로운 커밋이 생성 됨

 

  • 재배치 계속을 선택

 

  • 여섯번째 커밋의 내용을 변경하여 새롭게 히스토리가 구성된 모습

SourceTree를 이용한 중간 커밋의 내용 바꾸기 [DIY]

  • 커밋 히스토리 중간의 커밋의 내용을 바꿔보세요

rebase 중 충돌해결 [Look]

  • 빈 conflict 파일을 추가하고 conflict 브랜치를 만듦

  • master에서 파일 내용을 작성

  • conflict에서 파일 내용을 작성

  • 이제 conflict를 master에 rebase

  • 충돌이 발생

  • rebase 중 충돌 발생 시 HEAD는 내 코드가 아닌 상대방 코드, 아래 쪽이 내 코드가 됨

  • conflict에 master를 merge할 때의 충돌과는 정반대

  • base에서 현재 브랜치까지의 변경 사항을 구한다.

  • head를 master로 변경
  • rebase 과정 중 rebase 하려는 기준이 되는 브랜치로 head가 이동하기 때문

  • 충돌을 해결한 후 stage로 올림

  • rebase를 계속 진행

  • rebase 완료

rebase 중 충돌해결 [DIY]

  • master에서 빈 파일 conflict를 만드세요
  • master에서 파일 내용을 추가하세요
  • conflict에서 파일 내용을 추가하세요
  • conflict를 master에 rebase하세요
  • 충돌을 해결한 후 rebase를 완료하세요

rebase 중 충돌은 계속... 계속..?! [Look]

  • master에 conflict를 merge
  • master에서 두번째 줄 추가

  • conflict에서 두번째 줄 추가

  • conflict에서 한번 더 수정

  • conflict를 master에 rebase
  • 첫번째 변경사항을 적용하며 충돌이 발생

  • 충돌을 해결하고 rebase 계속 진행

  • 두번째 변경사항을 적용하며 또 충돌이 발생


  • Tip: 미리 C4, C5를 하나로 합친 후에 rebase 한다면 충돌 해결은 한번만 하면 되겠죠

rebase를 사용하는 이유 [Look]

  • 동시에 여러 feature가 진행되고 merge될 경우
  • 여러 갈래의 merge들로 인해 히스토리 파악이 어려움

  • rebase로 feature들을 차례대로 merge(no-ff)한 것과 같이 하거나 (특정 feature의 범위를 한 눈에 파악 용이)
  • master를 일렬로 유지
  • 히스토리 파악 쉬움

GitHub-flow에 rebase를 접목 [Look]

  • GitHub에 저장소를 하나 생성
  • 이때, README 초기화는 사용하지 않습니다.

  • 저장소 주소를 복사

 

  • 저장소 설정으로 진입

 

  • 원격 탭의 추가 클릭

 

  • 원격 이름은 origin, 저장소 주소를 붙여넣기

 

  • origin에 master를 push

  • feature1, feature2 브랜치를 만들어서 각각 커밋을 생성 후 push

  • feature1, feature2를 master에 merge하는 PR를 각각 생성

  • feature1을 master에 merge

  • SourceTree에서 master를 pull 받아 최신 상태를 적용

  • feature2를 master에 rebase
  • origin/feature2는 여전히 이전 커밋을 가리키는 것을 확인
  • origin/feature2의 입장에서 가지고 있지 않은 커밋 a2d2d8f, 1d903a9, b6c057d 때문에 3개 앞서 있다고 표시
  • feature2 입장에서 가지고 있지 않은 커밋 57c85ed 때문에 1개 뒤처져 있다고 표시
  • 여기서 다시 pull을 받고 push를 하면 rebase 의미가 없습니다
  • rebase한 feature2를 다시 push해야 합니다

  • push를 하려고 하면 오류가 발생하며 실패
  • push가 reject 되었습니다
  • 왜냐하면 우리가 push하려는 feature2의 어떤 조상도 origin/feaure2가 아니기 때문입니다
  • 쉽게 말해서 feature2의 줄기가 origin/feature2로 부터 나오지 않았기 때문입니다
  • force push 기능을 이용하여 강제로 push하여야 합니다

 

  • 설정으로 진입

 

  • 강제 푸시를 허용 체크

 

  • 강제 푸시 옵션을 체크한 후 다시 push

 

  • 경고 확인

  • force push 후 merge

  • feature 들이 차례대로 merge 된 모습

  • PR을 생성 후 코드 리뷰를 진행할 동안 다른 feature 들이 먼저 merge 될 수 있습니다
  • feature의 merge가 결정되면 먼저 rebase가 필요한지 확인한 후에 필요하다면 rebase 먼저 한 후에 merge를 합니다

GitHub-flow에 rebase를 접목 [DIY]

  • 실습하던 로컬 저장소를 GitHub 저장소로 push하세요
  • master에서 feature1, feature2 브랜치를 생성해 각각 커밋을 생성하세요
  • feature1, feature2를 push하여 각각 PR을 생성하세요
  • feature1을 먼저 merge하세요
  • feature2는 rebase를 한 후 force push한 후 merge하세요

모두가 함께 사용하는 브랜치를 rebase하면? [Look]

  • 팀원1과 팀원2가 feature 브랜치에서 함께 작업하고 있다면

  • 팀원1은 feature를 master에 rebase 했고
  • 팀원2는 feature에 새로운 커밋을 생성

  • 팀원1이 feature는 force push 하면
  • 팀원2가 fetch를 받았을 때 feature에 받을 것 3개 올릴 것 3개로 표시

  • 팀원2가 feature를 pull을 받으면
  • feature의 히스토리에 C2', C3'의 본래 커밋인 C2, C3까지 포함이 됨
  • 결과적으로 동일한 변경 내용을 갖는 커밋이 중복으로 히스토리에 존재하게 됨
  • 이 경우 혼란을 야기

  • 팀원2가 push를 하면 팀원2뿐 아니라 다른 사람들까지 혼란에 빠지게 됨

  • 만약 모두가 함께 사용하는 브랜치를 rebase 했다면 다른 사람들은 pull 대신 rebase 사용하기(git pull --rebase)를 통해 pull을 받으면 됨

  • pull 대신 rebase 적용 시 C3' 뒤에 다시 C2, C3가 생기지 않음
  • 변경사항 을 적용할 때 해당 변경사항이 이미 반영되어 있는지 확인 후 반영되어 있다면 제외

  • push를 하기 전 rebase는 다른 사람에게 영향을 주지 않습니다
  • push를 했더라도 해당 브랜치가 나 혼자 사용하는 브랜치라면 주의를 하면 됩니다
  • 여러 명이 함께 사용하는 브랜치를 rebase 한다면 많은 혼란을 가져올 수 있습니다
  • 하지만 히스토리를 다시 쓴다는 특성과 force push를 사용하는 특성 상 히스토리를 읽어 버릴 수 있는 가능성이 있으므로 항상 주의하여 사용하여야 합니다

GitHub/Jenkins 연동을 통한 pre merge test

GitHub Pull Request Builder 플러그인 설치 [Look]

  • Jenkins 관리

  • 플러그인 관리

  • 설치 가능 탭에서 github pull로 필터링 후 GitHub Pull Request Builder를 체크
  • 지금 다운로드하고 재시작 후 설치하기

  • GitHub Pull Request Builder 를 설치

GitHub 접근용 비밀번호 생성 [Look]

  • Jenkins에서 GitHub 저장소로 접근할 수 있도록 일회용 비밀번호를 생성해야 합니다.

  • GitHub에서 오른쪽 상단 Settings 클릭

  • 왼쪽 하단 Personal access tokens 클릭

  • 오른쪽 상단 Generate new token 클릭

  • Token description에 나중에 참고할 수 있는 설명을 적음
  • 권한은 repo에 체크 후 create token 클릭

  • 생성된 비밀번호는 지금 한번만 볼 수 있기 때문에 복사한 후 다른 곳에 잘 보관

  • Jenkins 관리 - 시스템 설정의 GitHub Pull Request Builder에서
  • Credentails의 Add 클릭
  • 사내 GitHub를 사용하고 있을 경우 API URL에 https://github.nhnent.com/api/v3를 입력

  • Username은 git, 비밀번호는 아까 복사한 값을 붙여넣고 Add 클릭

  • Description에 나중에 알아 볼 수 있도록 설명을 적고 저장
  • github.com과 사내 GitHub를 동시에 사용하고 있을 경우 추가 버튼을 눌러고 각각의 접근 정보를 추가하면 됩니다

Jenkins Job 생성 [Look]

  • 새로운 Job을 하나 생성하고 구성을 시작

  • General의 GitHub project에 GitHub 저장소 페이지 주소

  • 소스 코드 관리의 Git에 체크
  • Repository URL은 저장소의 git 주소
  • Credentials에 아까 생성한 권한으로 선택
  • 고급을 누른 후 Refspec에 +refs/pull/*:refs/remotes/origin/pr/* 입력
  • Branch Specifier에 ${sha1} 입력

  • 빌드 유발의 GitHub Pull Request Builder 체크
  • GitHub API credentials에 아까 생성한 credentails 선택
  • Admin list에 저장소 멤버 중 관리자로 지정할 아이디를 한줄 씩 작성
    • 여기 작성한 아이디가 테스트 결과, 댓글 등을 입력한 것과 같이 동작
  • Use github hooks for build triggering에 체크
    • GitHub 쪽 변경사항을 polling 뿐 아니라 hook을 통해서 받을 수 있도록 하는 설정이며 좀더 빠르게 반응하도록 합니다
    • github.com <-> 사내 jenkins 조합의 경우 github.com에서 내부 jenkins에 hook을 발송할 수 없기 때문에 polling으로만 구성해야 합니다
    • Crontab line을 변경하여 polling 스케쥴 설정 가능합니다

  • Build에 test를 위한 빌드 세팅을 하고 구성 저장

  • jenkins에서 구성을 저장하면 GitHub 저장소의 Settings - Webhooks에 자동으로 훅 설정이 됨
    • GHPRB 플러그인의 hook 주소는 http://젠킨스 주소/ghprbhook/

PR 생성 [Look]

  • 전달 받은 int 두개를 더하는 메소드를 일부러 고장내는 PR를 생성

  • PR 생성 후 얼마 지나지 않아 check가 있다고 표시 됨

  • 일부러 테스트를 통과할 수 없게 만들었기 때문에 check가 실패

GHPRB 자세한 설정 [Look]

  • GitHub Pull Request Builder는 기본적으로
    • 저장소 관리자가 PR를 생성한 경우: 자동으로 빌드
    • 그외 사용자가 PR을 생성한 경우: 관리자의 승인이 있으면 빌드

  • 관리자가 아닌 사용자가 PR를 생성했을 때 GHPRB 플러그인은 관리자의 승인을 묻는 댓글을 생성
  • 관리자 중 한명이 ok to test라고 댓글을 남기면 빌드

  • 모든 PR을 자동으로 빌드하려면
    • Build every pull request automatically without asking (Dangerous!).에 체크
    • PR에 새로운 커밋이 올라오면 무조건 자동으로 빌드
  • 모든 PR을 자동으로 빌드하지 않으려면
    • Only use trigger phrase for build triggering에 체크
    • Trigger phrase에 빌드 유발 텍스트 설정

GitHub Protected branches [Look]

  • 특정 브랜치에 강제 push/삭제 차단, 머지 전 check 통과 등을 강제할 수 있는 기능

  • GitHub 저장소 페이지 - Settings - Branches
  • Protected branches에서 보호할 브랜치 선택


  • Protect this branch
    • 보호 기능을 활성화
  • Require pull request reviews before merging
    • 머지 전 PR에 대한 승인이 필요
    • Dismiss stale pull request approvals when new commits are pushed
      • 승인 후 새로운 커밋이 추가되었을 경우 이전 승인을 무시
    • Require review from Code Owners
      • 지정된 코드 오너의 승인이 필요
  • Require status checks to pass before merging
    • 머지 전 체크 통과가 필요
    • require branches to be up to date before merging
      • PR 테스트가 반드시 보호된 브랜치의 최신 상태를 포함하고 있어야 함
    • Status checks found in the last week for this repository
      • 지난 일주일간 이 저장소의 check를 찾아 표시
      • 체크하면 반드시 해당 check를 통과해야 함
  • Include administrators
    • 저장소 관리자까지 포함

  • CODEOWNERS 파일
    • gitignore의 패턴 규칙과 동일
    • 개인은 물론 팀도 지정 가능

# 이것은 주석입니다. # 각 줄에 파일 패턴과 오너를 하나 이상 적습니다. # 이 오너들은 저장소의 모든 파일에 대한 기본 오너입니다. # 나중에 적힌 것들이 매칭되지 않는 한 @global-owner1과 @global-owner2는 # 누군가 PR을 열었을 때 리뷰 요청을 받게 됩니다. * @global-owner1 @global-owner2 # 순서가 중요합니다. 나중에 매칭된 것이 가장 우선순위가 높습니다. # 누군가 JS 파일만 변경한 PR을 오픈할 경우 글로벌 오너가 아닌 @js-owner만 리뷰를 요청 받게 됩니다. *.js @js-owner # 만약 원한다면 이메일 주소를 사용할 수도 있습니다. github 사용자 계정에 등록된 이메일이어야 합니다. docs/* docs@example.com


  • Review required
    • 이 PR이 승인 되지 않았아 머지가 불가능
  • All checks have failed
    • 이 PR의 테스트가 실패하여 머지가 불가능
  • This branch is out-of-date with the base branch
    • base 브랜치의 최신 내용이 반영되어 있지 않기 때문에 머지가 불가능

  • Comment
    • 승인은 하지 않고 의견을 남김
  • Approve
    • 승인을 하며 의견을 남김
  • Request changes
    • 반드시 의견에 대하여 변경을 해야 함

여러가지 Git workflow 들

Gitflow [Look]


메인 브랜치

  • 항상 존재하는 브랜치

master

  • 배포된 소스가 있는 브랜치

develop

  • 다음 배포를 위한 소스가 있는 브랜치
  • 개발이 완료되면 일련의 과정을 통해 master로 merge

서포팅 브랜치

  • master와 develop 외에 팀 멤버들이 병렬로 일할 수 있도록 도와주는 브랜치
  • 메인 브랜치와는 다르게 필요할 때마다 생성하였다가 삭제

feature 브랜치

  • 브랜치 생성: develop으로 부터
  • merge: develop으로
  • prefix: feature/
  • feature 브랜치는 특정 기능 하나에 대하여 develop으로부터 생성하여 개발하며 개발이 완료되면 다시 develop 브랜치로 merge

release 브랜치

  • 브랜치 생성: develop으로 부터
  • merge: master와 develop으로
  • prefix: release/
  • release 브랜치는 배포를 위한 준비를 할 수 있는 브랜치
  • 각종 메타 데이터(버전 명 등)를 변경하거나 작은 버그를 수정
  • 배포 준비가 되면 master와 develop에 각각 merge
  • merge된 master를 배포
  • release 브랜치를 따로 가져가기 때문에 develop 브랜치에서는 바로 다음 배포를 위한 기능을 시작할 수 있습니다

hotfix 브랜치

  • 브랜치 생성: master로 부터
  • merge: master와 develop으로
  • prefix: hotfix/
  • hotfix 브랜치는 배포된 버전에 긴급한 변경 사항이 있을 때 활용
  • 핫픽스가 완료되면 master와 develop에 각각 merge
  • merge된 master를 배포

GitHub Flow [Look]

  • Gitflow는 너무 복잡
  • 대부분의 케이스에서 Gitflow 처럼 복잡한 workflow가 불필요

  • master 브랜치는 항상 배포 가능한 상태여야 한다
  • 새로운 기능 개발은 명확한 브랜치 이름으로 master에서 생성한다
  • 토픽 브랜치의 커밋은 비번하게 push 한다
  • 피드백, 도움이 필요하거나 merge할 준비가 되었다면 PR을 생성한다
  • 누군가 리뷰를 하고 승인을 했다면 master에 merge한다
  • master에 merge한 커밋은 즉시 배포한다

master 브랜치는 항상 배포 가능한 상태여야 한다

  • GitHub Flow의 유일한 강제 사항
  • master의 최신 커밋은 최대한 빠르게 배포
  • 배포한 커밋에 문제가 있어 이전 커밋을 되돌려야 하는 케이스는 매우 드물다
    • 문제가 있을 경우 revert 커밋을 하든지 문제를 해결한 후 merge
  • master 브랜치는 배포하거나 브랜치를 만들기 위해 항상 stable해야 한다
    • 모든 브랜치에 push된 내용은 자동으로 테스트 수행하며 결과를 채팅창으로 받음

명확한 브랜치 이름으로 master에서 생성한다

  • master에서 명확한 이름으로 브랜치를 만들어 작업을 시작한다

    • fetch를 통해 나뿐 아니라 다른 사람들의 현재 작업 현황을 파악할 수 있다
    • 당분간 현재 브랜치 작업을 중단하였을 때 다시 돌아왔을 때 이름만 보고 어떤 브랜치였는지 기억해내기 쉽다
  • GitHub의 브랜치 페이지를 통해 최근 작업 중인 브랜치와 작업 상태를 러프하게 알 수 있다

    • 마치 신규 기능 목록

토픽 브랜치를 지속적으로 push

  • 서버에 꾸준히 push함으로 개인 컴퓨터 문제로 인한 loss 걱정이 없다
  • fetch / GitHub 브랜치 페이지를 통해 우리의 TODO들을 파악할 수 있다

언제나 PR을 생성

  • 라인 단위로 코멘트 가능
  • PR 자체에도 코멘트 가능
  • 새로운 커밋을 push하면 반영 됨
  • 이 모든 것이 타임라인으로 표시 됨
  • PR이 너무 오래 열려 있어 master와 멀어졌다면 master를 merge

리뷰가 완료된 것만 merge

  • master에 바로 작업하지 않고 토픽 브랜치에서만 작업하며 완료되었다고 생각했을 때 merge
    • 다른 사람에게 승인을 받음. 
      , 
    • 이후에 CI를 통과한 브랜치만 merge

리뷰 후 즉시 배포

  • master에 merge가 되면 내가 당장 배포하지 않더라도 몇 시간 내에 다른 사람이 merge한 커밋을 기반으로 새로운 작업을 시작하고 배포할 수 있다
    • 다른 사람이 내가 잘못 개발한 내용을 배포하는 것을 원하지 않기 때문에 사람들은 토픽 브랜치가 merge 되었을 때 정말 stable한지 확인하려는 경향이 있다
  • 채팅창을 통해 회사 내 누구나 배포가 가능
    • hubot depoy github to production
    • 6명의 다른 사람들(디자이너와 서포팅 스텝 포함)이 하루 사이에 24번 배포한 기록

GitLab Flow [Look]

  • GitHub Flow는 심플하지만 배포, 환경, 릴리즈 등을 해결해주지 못 함

Production branch

  • GitHub Flow는 master 브랜치의 지속적인 배포를 가정하지만 적합하지 않은 케이스도 존재
    • 예> iOS 앱은 배포 시 심사 과정이 필요, 배포 시간이 제한적일 때(운영 팀이 10am ~ 4pm까지 일할 때)
  • 배포가 필요할 때 master에서 production으로 merge를 하여 배포
  • production에 hotfix가 필요할 경우 production에서 패치하는 것이 아니라 master에서 패치 후 master 검증 후 production에 cherrypick
    • production에서만 패치 후 패치 결과가 master에는 잊어버리고 반영되지 않는 문제를 해결하기 위해

Environment branches

  • production 단계 전 pre-production 환경이 존재한다면 pre-production 배포를 위해 master에서 pre-production으로 merge
  • 리얼 배포를 위해서는 pre-production에서 production으로 merge

Release branches

  • 마이너 버전 릴리즈 브랜치가 존재
  • 릴리즈 브랜치는 stable한 master에서 시작
  • 릴리즈 브랜치를 생성하는 때는 최대한 늦게 가져가 각각의 브랜치에 버그를 픽스 해야 하는 상황을 최소화
    • 릴리즈가 공개된 후에는 치명적인 버그만 픽스
  • 가능하다면 버그 픽스는 master에서 진행 후 각 브랜치로 cherry-pick
    • master에 반영하는 것을 잊어 이후 릴리즈에서 버그가 다시 나타나는 것을 방지
    • 패치 버전은 새 태그를 사용하여 표시

NHN Edu 서버개발팀은? [Look]

  • 단기간의 배포 일정
    • 6/28, 7/18, 7/26
  • 장기간의 배포 일정
    • 코드 네임을 부여
    • strewberry, tomato
  • 같은 시간에 여러 배포 일정의 작업이 필요
  • Gitflow 기반으로 develop 역할의 브랜치를 여러개 사용
  • rebase 적극 활용

  • 모든 배포 일정 브랜치는 develop에서 시작
  • 각 브랜치 내에서 feature 브랜치 생성, merge
  • PR를 통해 자동 테스트
  • merge 전 rebase를 이용

  • 다가오는 배포 일정의 개발이 완료되면 해당 브랜치를 이용하여 QA 진행

  • QA 완료 후 master와 develop에 merge

  • 남은 배포 일정 브랜치들을 develop에 rebase (이때 -p 옵션을 이용하여 머지 커밋을 유지)

  • 각자의 feature 브랜치를 각 배포 일정 브랜치에 rebase
    • 이 때 rebase 중 충돌이 많이 발생하면 cherry-pick

  • hotfix가 필요할 경우 hotfix 브랜치 생성 후 master와 develop에 merge

  • 다시 각 배포 일정 브랜치와 각자의 feature 브랜치를 rebase

우리 팀에 적합한 Git workflow는? [Look]

  • Gitflow
    • 체계적으로 관리 가능
    • 복잡한 절차
  • GitHub Flow
    • 간단한 절차
    • 너무 간단한...
  • GitLab Flow
    • 절충안
    • 웹보다 동시에 여러 릴리즈 버전들이 현실 세계에 존재할 때 적합
  • rebase를 적용
    • 히스토리 보기 편함
    • 절차가 복잡, 커밋을 잃을 수도 있는 리스크

Git/GitHub 토론

  • Git/GitHub 관련 자유롭게 토론해보아요.
728x90