[NDC16] Effective Git

  • View
    17.709

  • Download
    2

  • Category

    Software

Preview:

Citation preview

Effective Git

넥슨 코리아 왓 스튜디오

김찬웅

소개

김찬웅

• 2010-2014.3 <삼한제국기>

• 2014.3-2014.11 <Project N>

• 2014.12- <야생의 땅: 듀랑고>

• KGC14 <삼한제국기 포스트모템>

• NDC15 <그룹웨어에 새 에너지를>

• NDC16 <Find My AndPhone>

• NDC16 <Effective Git>

kexplo

http://chanwoong.kimcwkim@nexon.co.kr

kexplo

발표 동기

Git 초심자들을 관찰

•이전에 사용하던 VCS의 개념대로 사용

•이전 VCS와 대칭되는 명령어만 사용

• svn checkout → git clone

• svn update → git pull

• svn commit → git commit

•나쁘다는 것이 아님

•발표자도 같은 시행착오를 겪음

•Git의 좋은 점을 영업하고 싶다!

© http://d.hatena.ne.jp/gu_he_he/20120322/1332419643

나랑 Git 쓰지 않을래?

발표의 대상

Git 숙련도

초심자push, commit 정도의 기본적인 명령어 숙지

중급자고급 명령어와동작 원리 파악

여기 쯤

이런 분들에겐 조금 어려울 수 있습니다

•git을 command line으로 쓰지 않는 분

• GUI 툴을 주로 이용

•Staging area 를 아직 모르시는 분

하지 않을 이야기

•흔한 Git 입문서

• 태초에 Git이 있었고, Git은 분산 버전 관리 시스템이며 …

•Git 내부 구조

• blob, tree object, commit object, …

• 이건 다음에 기회가 된다면…

오늘 할 이야기

•Git 사용 전략

•Rebase

•바로 써먹을 수 있는 16가지 기능 소개

• 3가지 파트로 나누어서 설명

•유용할 도구 소개

오늘 할 이야기

•Git 사용 전략

•Rebase

•바로 써먹을 수 있는 16가지 기능 소개

• 3가지 파트로 나누어서 설명

•유용할 도구 소개

1. 생산성 높이기2. 로그 탐색하기3. 실수 만회하기

Git 사용 전략git flow

Forward-porting

Branching, Merge가 정말 쉽고 빠르다

쉽다 == 남용 하기 쉽다

Git-flow

gitflow

Forward

Git-flow 브랜칭 전략

•Vincent Driessen이 제안

•목적에 따라 브랜치를 분리하는 모델

• master branch: 배포 버전

• develop branch: 개발 버전

•배포와 연관 지었을 때 강력한 힘을 발휘

•Git-flow를 설치해서 쓰면, 브랜치 삭제/병합을 쉽게 해 줌

새 기능 개발

develop

새 기능 개발

develop

feature/awesome

$ git flow feature start awesome$ git commit -a$ git commit -a$ git commit -a

새 기능 개발developfeature/awesome

$ git flow finish awesome

새 배포

develop

새 배포

develop

release/v1.0.0

$ git flow release start v1.0.0$ git commit -a$ git commit -a$ git commit -a

새 배포develop

$ git flow release finish v1.0.0

mastertag v1.0.0

핫 픽스

mastertag v1.0.0

핫 픽스

master

hotfix/fix1

$ git flow hotfix start fix1$ git commit -a$ git commit -a$ git commit -a

핫 픽스

master

$ git flow hotfix finish fix1

develop

tag fix1

hotfix/fix1

큰 그림

developfeature/awesome

release/v1.0.0

master

feature

release

hotfix

tag v1.0.0

hotfix/fix1

tag fix1

큰 그림

developfeature/awesome

release/v1.0.0

master

feature

release

hotfix

tag v1.0.0

hotfix/fix1

tag fix1

큰 그림

developfeature/awesome

release/v1.0.0

master

feature

release

hotfix

tag v1.0.0

hotfix/fix1

tag fix1

큰 그림

developfeature/awesome

release/v1.0.0

master

feature

release

hotfix

tag v1.0.0

hotfix/fix1

tag fix1

장점

•가독성 향상

• feature → develop 머지 커밋 == 새로운 기능이 있구나

• 작업 내용은 feature branch로 격리되어 다른 코드와 섞이지 않음

•효율 향상

• 브랜치의 역할이 정해져 있기 때문에 Hook등을 걸기 쉬움

• hotfix 작업시 실수 방지

Forward-porting

Forward-p

gitflow

feature/blahblah

master

Forward-porting

feature/blahblah

$ git pull --rebase origin/master

origin/master

Forward-porting

master

feature/blahblah

origin/master

Forward-porting $ git pull --rebase origin/master

master

장점

•머지 그래프가 예쁘게 유지

• 작업 도중에 최신 내용을 가져 와 머지하는 순간 무지개에 가까워 짐..

•충돌 발생시 기능 작업자가 인지, 처리 가능

• 코드 리뷰 향상

•긴 기능의 작업을 피하게 됨

• 오래 된 기능 브랜치 일수록 충돌 날 확률이 올라감

• 개별 기능은 짧게 쪼개어 작업하는 원칙에도 OK

왓 스튜디오에서는

•Git-flow

• release 브랜치에 Hook을 활용

• 커밋이 올라오면 자동 빌드, 테스트, 배포

•Forward-porting

• 로그 그래프로 작업된 기능을 한 눈에 파악 가능

• 머지 했을 때, 타인의 코드에 트롤링(?)할 여지 방지

Rebaserebase 동작 원리

로그 정제하기

rebase 동작 원리

rebase

로그

정제

Rebase

•Base를 재정의(Re-)하는 기능

• Forward-porting도 Rebase를 이용한 방법

• Rebase를 통해 base를 최신 커밋 으로 지정하는 전략

B C Dfeature/abc

E FAdevelopHEAD

B C Dfeature/abc

E FAdevelop

$ git checkout feature/abc$ git rebase develop

HEAD

B C Dfeature/abc

E FAdevelop

공통 조상을 찾음

HEAD

B C Dfeature/abc

E FAdevelop

내부적으로 각 커밋마다 패치를 만들어 둠

HEAD

B C D

B` C` D`

feature/abc

E FAdevelop

대상 브랜치에 적용

HEAD

B C D

B C D

로그 정제하기

로그

정제

rebase

나누고 붙이고 섞고 지우고

$ git rebase –i [<커밋 범위>]

나누고 붙이고 섞고 지우고

$ git rebase –i [<커밋 범위>]

Rebase를 통해 코드를 원격 저장소에 올리기 전에,

커밋을 깔끔하게 정제할 수 있다.

16가지 기능 소개1. 생산성 높이기2. 로그 탐색하기3. 실수 만회하기

1. 생산성 높이기

stash

bisect

blame

worktree

Hunk 단위 작업하기

특정 버전의 파일 가져오기

alias

shallow clone

2. 로그 탐색하기3. 실수 만회하기

$ git stash savePopApplyListdrop

stash

bisect

blame

worktree

Hunk

단위

특정

버전

alias

shallow c

작업 물 끼어들기

•다들 겪어봤을 일

•기능 A를 작업 중인데, 기능 B를 지금 해 달라고요?

© ABC

stash는 현재 작업 디렉토리에 있는 작업 물을stash stack에 쌓아 줍니다.

WIP

WIP

stash

Working Directory

git stash save

git stash pop

보통은

•현재 작업 물을 백업 혹은 격리

•새로운 작업을 마친 후

•이전 작업 물을 되돌림

git stash

•현재 작업 물을 백업 혹은 격리

• $ git stash save

•새로운 작업을 마친 후

•이전 작업 물을 되돌림

• $ git stash pop

수동 관리도 가능

•$ git stash list

•$ git stash apply [<stash>]

•$ git stash drop [<stash>]

$ git bisect startgoodbadlogreset

bisect

stash

blame

worktree

Hunk

단위

특정

버전

alias

shallow c

어?

•어느 순간 코드가 실패한다.

•어디지?

•뭐가 문제지?

•너무 작업이 많이 쌓여서 감이 안 오는데?간담이 서늘해 진다

© http://ff663.blogspot.kr/2010/05/201058-in-english-i-feel-complete.html

bisect는 버그를 가진 커밋을 찾는데

도움을 주는 이진 검색 도구.

HEAD

$ git bisect start

HEAD

$ git bisect start$ git bisect bad

HEAD

$ git bisect start$ git bisect bad$ git bisect good f794027

f794027

HEAD

f794027

HEAD

$ git bisect good

f794027

HEAD

f794027

HEAD

f794027

HEAD

$ git bisect bad

f794027

HEAD

f794027

HEAD

$ git bisect bad

f794027

HEAD

$ git bisect bad

그 외

•$ git bisect log

•$ git bisect reset

으.. 이것도 귀찮은데?

•완전 자동화!

• 자동화 완전 좋아! (발표자는 자동화 덕후)

•$ git bisect start

•# test_error.sh는 문제가 있을 경우 1을 반환.

•$ git bisect run test_error.sh

$ git blame-L <start,end>-C

blamestash

bisect

worktree

Hunk

단위

특정

버전

alias

shallow c

blame

•bisect로 버그 커밋을 찾았다면

•이제 담당자를 찾아 격려(?)해 줄 차례

© 한빛미디어

$ git blame -L 10,11 effective_git.md

$ git blame -L 10,11 effective_git.md

파일의 시작 라인 번호

끝 라인 번호경로

$ git blame -L 10,11 effective_git.md

파일의 시작 라인 번호

끝 라인 번호경로

-C

파일명 변경 추적

$ git worktree addprunelist

worktree

stash

blame

bisect

Hunk

단위

특정

버전

alias

shallow c

작업 물 끼어들기 (데자뷰)

•다들 겪어봤을 일

•기능 A를 작업 중인데, 기능 B를 지금 해 달라고요?

© ABC

작업 물 끼어들기 (데자뷰)

•다들 겪어봤을 일

•기능 A를 작업 중인데, 기능 B를 지금 해 달라고요?

•근데 기능이 좀 커

© ABC

다음 상황에 적절

•작업 디렉토리를 통째로 바꿔야 하는 경우

• 브랜치를 바꿔야 한다거나, 브랜치를 바꿔야 한다거나…

• stash할 순 있는데, untracked 파일도 꽤 있고…

• 현재 작업 상태를 보존하고 싶을 경우

다음 상황에 적절

•작업 디렉토리를 통째로 바꿔야 하는 경우

• 브랜치를 바꿔야 한다거나, 브랜치를 바꿔야 한다거나…

• stash할 순 있는데, untracked 파일도 꽤 있고…

• 현재 작업 상태를 보존하고 싶을 경우

worktree는 여러 개의 작업 트리를 관리할 수 있게 해 줌

$ git worktree add –b emergency-fix ../temp master

$ git worktree add –b emergency-fix ../temp master

새로 만들 브랜치

새 worktree 경로

새 worktree가 chekcout할 브랜치

$ git worktree add –b emergency-fix ../temp master

$ pushd ../temp

# ... 새 작업 ...

$ popd

경로로 이동해서새 작업을 끝내고다시 돌아온다

$ git worktree add –b emergency-fix ../temp master

$ pushd ../temp

# ... 새 작업 ...

$ popd

$ rm –rf ../temp

$ git worktree pruneWorktree를 정리

Hunk 단위로 작업 (‘-p’ 옵션 활용)$ git add –p$ git checkout –p$ git stash -p

Hunk

단위

stash

blame

worktree

특정

버전

alias

bisect

shallow c

Atomic commit

• “(나눌 수 없는)최소한의 단위Atomic”로 커밋 하자

•다른 VCS에서도 권장하는 방식

•이점• 코드 리뷰 하기 쉽다

• 롤백 하기 쉽다

이론과 현실

•정말 항상 한 작업만 하나?

•가끔 실수 할 수 있다.

•작업하고 나서 바로 커밋하는 것을 깜빡 했다거나…

이론과 현실

•정말 항상 한 작업만 하나?

•가끔 실수 할 수 있다.

•작업하고 나서 바로 커밋하는 것을 깜빡 했다거나…

•이럴 때 유용한 “-p” 옵션.

•$ git add

•$ git add –p

•$ git add –p

•$ git add –p

•$ git reset –p

•$ git checkout –p

•$ git rm -p

특정 버전의 파일 가져오기$ git checkout$ git show

툭정

버전

stash

blame

worktree

Hunk

단위

alias

bisect

shallow c

checkout

•브랜치를 바꾸는 명령어

•특정 버전의 트리로 업데이트 해 주는 명령어

$ git checkout master -- Readme.md

Readme.md를 master 브랜치의 파일로 checkout

show

•1개 이상의 오브젝트(blob, tree, commit, …)를 보는 명령어

• $ git show fc1b357:Readme.md > master_Readme.md

fc1b367 커밋의 Readme.md를 master_Readme.md로 출력

alias

aliasstash

blame

worktree

Hunk

단위

특정

버전

bisect

shallow c

나는 게으른 사람입니다

•명령어 줄여 쓰기

• git status → git st

•다른 곳에서도 많이 쓰이는 개념

• 그 alias가 맞습니다.

git lg

•로그 그래프를 이쁘게 보여주는 alias

[alias]lg = log --graph --abbrev-commit --decorate --date=relative

--format=format:'%C(bold red)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(cyan)<%an>%C(reset)%C(bold yellow)%d%C(reset)' --all

shallow clone$ git clone –depth$ git fetch --depth$ git fetch --unshallow

sallow cl

stash

blame

worktree

Hunk

단위

특정

버전

alias

bisect

마지막 N개 커밋만 필요할 때

•배포 패키징, 리뷰, 빌드 머신 …

•근데 저장소가 넘나 클 때

$ git clone

$ git clone --depth 1

depth 변경

$ git fetch --depth <N>

Q. Push가 안 돼요

Q. Push가 안 돼요

$ git fetch --unshallow

2. 로그 탐색하기

3. 실수 만회하기

git log

리비전 선택하기

git log -S

옮겨진 파일 찾기

git grep

git rev-list

1. 생산성 높이기

git log

gitlog

리비

전선

gitlog

옮겨진

파일

gitgrep

gitrev

제일 간단

$ git log <sha1 hash>

git log 검색 기능

• ‘/’ 를 눌러서 검색

•n, N (search Next) 키로

검색 결과 탐색

•Vi 처럼 j, k로 위, 아래 탐색

리비전 선택하기^, ~, .., ...

리비

전선

gitlog

옮겨진

파일

gitgrep

gitrev

gitlog

특정 커밋이나 범위를 잡고 싶을 때?

•기계 라면?

• d206ec8 부터 727372a가 보고 싶구나

특정 커밋이나 범위를 잡고 싶을 때?

•기계 라면?

• d206ec8 부터 727372a가 보고 싶구나

•멍청한 나

• 음.. 전전전전 커밋 부터 전 커밋 까지가 보고 싶은데?

특정 커밋이나 범위를 잡고 싶을 때?

•기계 라면?

• d206ec8 부터 727372a가 보고 싶구나

•멍청한 나

• 음.. 전전전전 커밋 부터 전 커밋 까지가 보고 싶은데?

^ (Circumflex)

•^n

•n번째 부모 커밋을 가리킴

•n이 1일 경우 생략 가능 ( ^1 == ^ )

HEAD

HEADHEAD^HEAD^1

HEAD^2

HEADHEAD^^

HEADHEAD^^

(HEAD^)^

~ (Tilde)

• ~n은 n번 째 상위 커밋

HEAD

HEADHEAD~

HEAD~1

HEADHEAD~

HEAD~1HEAD~2

HEADHEAD~

HEAD~1HEAD~2

HEAD~3

.. (double dot)

•범위를 나타 냄

• start..end : end는 포함, start는 안 포함 하는 범위

HEAD~3..HEAD

참 쉽죠?

B C D

JIHGFE

A

develop..master의 범위를 구하시오 (3점)

develop

master

B C D

JIHGFE

A

develop..master의 범위를 구하시오 (3점)

develop

master

.. (double dot)

•커밋의 범위를 나타 냄

• start..end : end는 포함, start는 안 포함 하는 범위

.. (double dot)

•커밋의 범위를 나타 냄

• start..end : end는 포함, start는 안 포함 하는 범위

end에는 도달할 수 있고, start에선 도달할 수 없는 범위end – start 의 차집합

B C D

JIHGFE

Adevelop

master

develop..mastermaster에는 도달할 수 있고, develop에선 도달할 수 없는 범위master – develop 의 차집합

... (Triple dot)

•공통으로 가지는 것을 제외하고 서로 다른 커밋의 범위

•대칭차집합

A-B B-A

$ git log A...B

B C D

JIHGFE

Adevelop

master

develop...master

B C D

JIHGFE

Adevelop

master

develop...master

git log –S<string>

gitlog -

옮겨진

파일

gitgrep

gitrev

gitlog

리비

전선

git log –S<string> # pickaxe

•파일의 Diff 히스토리에서 문자열을 탐색

•실제의 코드 블럭을 찾는데 용의

•-M 옵션을 곁들이면, rename까지도 탐색할 수 있음.

옮겨진 파일 찾기git log --follow

옮겨진

파일

gitgrep

gitrev

gitlog

리비

전선

gitlog

기억이 안 난다

•파일명이 바뀐 것 까지는 기억이 나는데…

•바뀐게 뭐 였지?

컴퓨터를 끈다

$ git log –follow -- filepath

$ git grep

gitgrep

gitrev

gitlog

리비

전선

gitlog

옮겨진

파일

$ git grep

•평소에 많이 쓰는 그 grep과 유사

•blob object 검색이라고 생각하면 쉽다.

•파일과 위치를 알 수 있음

• $ git grep blahblah

•-- 구분 기호로 경로를 제한할 수 있음

• $ git grep blahblah -- Document

$ git grep hello

# -- 구분 기호로 경로를 제한할 수 있음

$ git grep hello -- subdirectory

$ git rev-list

gitrev-l

gitlog

리비

전선

gitlog

옮겨진

파일

gitgrep

rev-list

• commit object의 역순 리스트를 보는 명령

•파일 경로와 같이 사용할 수 있다

• 파일 중심적인 로그를 볼 때 유용

• 파일의 변경을 추적하기 좋다

$ git rev-list master -- Readme.md

rev-list

$ git rev-list master -- Readme.md

727372ac234645eeb891272b3fc73c940ea5f52f

c38dc4e678d40dd48072489fda6b8f933cdea0c2

1064cea4cfbf8bd94dff3cc3175d5de2ff5c110c

19424a1bff2223c25905c2e732a857911a0d7c54

189952e05d7cc97a7e408480d00c39c8ab754489

rev-list

$ git rev-list –n 1 master -- Readme.md

727372ac234645eeb891272b3fc73c940ea5f52f

3. 실수 만회하기

1. 생산성 높이기2. 로그 탐색하기

git reflog

git fsck

Reflog

gitreflo

gitfsck

History log를 망쳤을 때

•머지를 잘못 했다거나

•커밋을 실수로 덮어 쓰거나

• ( $ git commit –amend )

•뭘 했는진 모르겠지만, 그래프를 보니 도망가고 싶을 때

© 이말년

Commit object는 불변

•$ git commit --amend

• 사실 새 커밋을 만드는 것. (sha1 hash 값이 다르다)

B C DA

B C DA

$ git commit --amendD`

$ git commit --amend

B C DA

D`

기존 커밋은 dangling commit이 되어서 보이지 않는 것GC가 돌기 전까지 살아 있다

아직 Push를 안 했다면 희망이 있다

•Reflog엔 사용한 명령어들이 기록이 됨

아직 Push를 안 했다면 희망이 있다

•Reflog엔 사용한 명령어들이 기록이 됨

잦은 push –f 는 권장하지 않는 행동입니다.

1. 자신이 일을 저지른(?) 커밋을 찾는다

2. hash 나 HEAD@{1} 같은 ref로 HEAD를 리셋해 준다

$ git reset HEAD@{2}

복원

참 쉽죠?

fsck

gitfsck

gitreflo

dangling commit

•지정된 ref가 없어서 도달할 수 없는 커밋

B C DA

D`HEAD

dangling commit 찾기

$ git fsck

도구 소개GitlabSourcetreeGit kraken

참고

• https://git-scm.com/doc

• http://danielkummer.github.io/git-flow-cheatsheet/index.html

• https://www.sourcetreeapp.com/

• https://www.gitkraken.com/

• https://about.gitlab.com/

감사합니다.cwkim@nexon.co.kr

Recommended