2020.06.12

'뜻밖의 선물'같은 팁··· '깃(Git)' 고급 명령어 5가지

Serdar Yegulalp | InfoWorld
더 깔끔한 커밋, 더 스마트한 디버깅, 더 세련된 리포지토리를 위해 한 단계 업그레이드된 깃 기술들을 마스터하라. 

오늘날 개발자 대부분은 소프트웨어 워크플로우의 핵심인 버전 관리 시스템 깃(Git)을 배웠을 가능성이 크다. 그리고 기본 개념과 명령어도 당연히 알고 있을 것이다. 이를테면 리포지토리(repositories) 작동 방식, 브랜치(branch)를 만들고 변경사항을 커밋(commit)하는 방법, 변경사항을 머지(merge)하고 풀 리퀘스트(pull request)하는 방법 등이다.

기본을 잘 알고 있다면 이제 수준을 조금 높여야 할 때다. 워크플로우에서 깃의 더욱 강력한 기능들을 활용할 수 있도록 말이다. 
 
ⓒGetty Images

1. git rebase로 커밋 히스토리 단순화하기
한 프로젝트에 2개의 브랜치(예: 개발 브랜치와 마스터 브랜치)가 있고, 두 브랜치를 결합해야 하는 변경사항이 있다고 가정해보자. 이때 git merge 명령어는 이들을 통합하는 간단한 방법이다. 

merge는 한 브랜치의 개발 히스토리를 다른 브랜치의 머지 커밋으로 추가한다. 이를 통해 두 히스토리를 온전히 보존할 순 있지만 전체 프로젝트 히스토리를 파악하기 어려울 수 있다. 더 단순하고 깔끔한 결과를 원한다면 git rebase가 도움이 된다. 

git rebase 명령어도 2개의 브랜치를 머지하지만 약간 다르게 진행된다. git rebase는 한 브랜치가 생성된 지점부터 다른 브랜치가 통합될 수 있도록 커밋 히스토리를 다시 쓴다. 즉 덜 복잡하고 선형적인 커밋 히스토리를 만들 수 있는 것이다. 하지만 이 과정에서 다른 브랜치 및 머지 프로세스와 관련해 유용할 수도 있는 세부정보가 제거된다는 점을 유의해야 한다. 

따라서 rebase는 공용(public) 브랜치와 머지하기 전에 하나의 깔끔한 커밋 히스토리로 통합하려는 여러 비공개(private) 브랜치가 있을 경우 특히 유용하다. 이를 통해 프로젝트의 커밋 히스토리와 관련된 주요 세부사항을 변경하지 않으면서도 커밋 히스토리를 더 선형적이고 덜 복잡하게 만드는 이점을 누릴 수 있다. 

2. 머지를 git merge –squash로 정리하기
머지와 후속 커밋을 덜 복잡하게 만드는 또 다른 방법은 git merge에서 -- squash 옵션을 사용하는 것이다. -- squash는 머지할 브랜치의 모든 커밋을 가져와서 하나의 커밋으로 합친다. 

-- squash를 통한 머지의 이점은 스테이징된 파일을 어떻게 적용할지 선택할 수 있다는 것이다. 전체 변경사항을 하나로 커밋하거나 변경사항과 연관된 몇 개의 파일을 한 번에 커밋할 수 있다. 또한 이 방식은 머지할 브랜치의 커밋 히스토리가 해당 브랜치의 컨텍스트에서만 사용되거나, 혹은 어차피 폐기될 비공개 브랜치의 커밋 히스토리인 경우에도 유용하다. 

rebase와 마찬가지로 이 명령어는 내부 브랜치를 커밋하여 마스터하는 데 가장 효과적이지만, 필요한 경우 풀 리퀘스트에도 적합하다.

3. git bisect로 빠르게 버그 찾기
코드의 리그레션(regressions)은 파악하기가 매우 까다로운 부분이다. 버그를 추적하고자 코드베이스에 테스트를 추가했다고 가정해 보자. 하지만 버그가 언제 처음 나타났는지도 알 수 없으며, 리포지토리에는 수백 또는 수천 개의 커밋이 있다. 이러한 상황에서 git bisect 명령어가 유용하다. 문제를 발생시킨 커밋을 찾고자 검색해야 하는 코드의 양을 크게 줄일 수 있기 때문이다.

bisect를 활성화(git bisect start)하고 코드베이스에 두 가지 커밋을 지정해 검색 범위를 제한한다. 하나는 문제가 발생하는 커밋(통상적으로 HEAD다)이고, 다른 하나는 문제가 발생하지 않는 커밋이다. git bisect는 문제가 발생하는 커밋과 발생하지 않는 커밋 사이를 체크아웃하고 테스트를 실행한다. 이러한 이진탐색 프로세스는 버그를 발생시킨 최초의 커밋을 찾을 때까지 반복된다.

git bisect는 백사장에서 바늘을 찾아야 하는 사용자를 위한 뜻밖의 선물인 셈이다. 버그가 발견될 것이라는 희망으로 모든 커밋을 낱낱이 검색해야 하는 번거로움을 덜어주기 때문이다. 최소한으로 잡더라도 이는 해야 할 검색과 테스트의 양을 절반으로 줄여줄 것이다. 

4. git cherry-pick으로 커밋 재적용하기 
많은 깃 고급 명령어가 특정 상황에서만 유용한 탓에 일반적인 고급 사용자들은 이를 무시해버리는 경우가 있다. 하지만 그러한 특정 상황에 직면하게 된다면? 고급 명령어를 아는 것은 득이 된다. 

git cherry-pick은 어떤 브랜치의 커밋이든 원하는 특정 커밋을 가져다가 다른 브랜치에 적용할 수 있는 명령어다. 이는 몇 가지 특정 상황에서 유용하다.

• 잘못된 브랜치에 커밋을 했고, 올바른 브랜치에 빠르게 적용하고자 하는 경우
• 트렁크(메인 브랜치) 코드에 대한 다른 작업을 계속하기 전에 브랜치에서 트렁크까지 수정사항을 적용하려는 경우

커밋을 cherry-pick할 때 커밋을 직접 적용하는 것 외에 몇 가지 옵션이 있다는 점에 유의해야 한다. 예를 들면 --no-commit 옵션을 설정하면 체리픽된 커밋이 현재 브랜치의 준비 영역에 배치된다.

5. Git submodule로 간결하게 프로젝트 구성하기
대부분의 프로그래밍 언어가 패키지나 모듈을 가져오는 방법을 제공한다. 이와 유사하게 깃도 한 리포지토리 안에 다른 리포지토리를 자동으로 넣을 수 있는 submodule을 지원한다. 

즉 리포지토리 내부에 하위 디렉토리를 생성하고 여기에 다른 리포지토리를 자동으로 가져올 수 있다. 일반적으로 일관성을 위해 특정 커밋 해시를 명시한다. Git submodule은 아래와 같은 조건에서 가장 유용하다. 

• 해당 서브모듈이 자주 변경되지 않거나 특정 커밋에 고정된 경우. 서브모듈이 아니라 서브모듈에 대한 모든 작업을 별도로 관리해야 하는 경우.

• 모든 사용자가 서브모듈을 지원하는 깃 버전을 사용 중인 경우. 예를 들면 서브모듈 디렉토리가 언제나 서브모듈 리포지토리를 자동으로 가져오는 것은 아니다. 모든 것을 최신 상태로 가져오려면 Git submodule update 명령어를 사용해야 할 수도 있다. ciokr@idg.co.kr



2020.06.12

'뜻밖의 선물'같은 팁··· '깃(Git)' 고급 명령어 5가지

Serdar Yegulalp | InfoWorld
더 깔끔한 커밋, 더 스마트한 디버깅, 더 세련된 리포지토리를 위해 한 단계 업그레이드된 깃 기술들을 마스터하라. 

오늘날 개발자 대부분은 소프트웨어 워크플로우의 핵심인 버전 관리 시스템 깃(Git)을 배웠을 가능성이 크다. 그리고 기본 개념과 명령어도 당연히 알고 있을 것이다. 이를테면 리포지토리(repositories) 작동 방식, 브랜치(branch)를 만들고 변경사항을 커밋(commit)하는 방법, 변경사항을 머지(merge)하고 풀 리퀘스트(pull request)하는 방법 등이다.

기본을 잘 알고 있다면 이제 수준을 조금 높여야 할 때다. 워크플로우에서 깃의 더욱 강력한 기능들을 활용할 수 있도록 말이다. 
 
ⓒGetty Images

1. git rebase로 커밋 히스토리 단순화하기
한 프로젝트에 2개의 브랜치(예: 개발 브랜치와 마스터 브랜치)가 있고, 두 브랜치를 결합해야 하는 변경사항이 있다고 가정해보자. 이때 git merge 명령어는 이들을 통합하는 간단한 방법이다. 

merge는 한 브랜치의 개발 히스토리를 다른 브랜치의 머지 커밋으로 추가한다. 이를 통해 두 히스토리를 온전히 보존할 순 있지만 전체 프로젝트 히스토리를 파악하기 어려울 수 있다. 더 단순하고 깔끔한 결과를 원한다면 git rebase가 도움이 된다. 

git rebase 명령어도 2개의 브랜치를 머지하지만 약간 다르게 진행된다. git rebase는 한 브랜치가 생성된 지점부터 다른 브랜치가 통합될 수 있도록 커밋 히스토리를 다시 쓴다. 즉 덜 복잡하고 선형적인 커밋 히스토리를 만들 수 있는 것이다. 하지만 이 과정에서 다른 브랜치 및 머지 프로세스와 관련해 유용할 수도 있는 세부정보가 제거된다는 점을 유의해야 한다. 

따라서 rebase는 공용(public) 브랜치와 머지하기 전에 하나의 깔끔한 커밋 히스토리로 통합하려는 여러 비공개(private) 브랜치가 있을 경우 특히 유용하다. 이를 통해 프로젝트의 커밋 히스토리와 관련된 주요 세부사항을 변경하지 않으면서도 커밋 히스토리를 더 선형적이고 덜 복잡하게 만드는 이점을 누릴 수 있다. 

2. 머지를 git merge –squash로 정리하기
머지와 후속 커밋을 덜 복잡하게 만드는 또 다른 방법은 git merge에서 -- squash 옵션을 사용하는 것이다. -- squash는 머지할 브랜치의 모든 커밋을 가져와서 하나의 커밋으로 합친다. 

-- squash를 통한 머지의 이점은 스테이징된 파일을 어떻게 적용할지 선택할 수 있다는 것이다. 전체 변경사항을 하나로 커밋하거나 변경사항과 연관된 몇 개의 파일을 한 번에 커밋할 수 있다. 또한 이 방식은 머지할 브랜치의 커밋 히스토리가 해당 브랜치의 컨텍스트에서만 사용되거나, 혹은 어차피 폐기될 비공개 브랜치의 커밋 히스토리인 경우에도 유용하다. 

rebase와 마찬가지로 이 명령어는 내부 브랜치를 커밋하여 마스터하는 데 가장 효과적이지만, 필요한 경우 풀 리퀘스트에도 적합하다.

3. git bisect로 빠르게 버그 찾기
코드의 리그레션(regressions)은 파악하기가 매우 까다로운 부분이다. 버그를 추적하고자 코드베이스에 테스트를 추가했다고 가정해 보자. 하지만 버그가 언제 처음 나타났는지도 알 수 없으며, 리포지토리에는 수백 또는 수천 개의 커밋이 있다. 이러한 상황에서 git bisect 명령어가 유용하다. 문제를 발생시킨 커밋을 찾고자 검색해야 하는 코드의 양을 크게 줄일 수 있기 때문이다.

bisect를 활성화(git bisect start)하고 코드베이스에 두 가지 커밋을 지정해 검색 범위를 제한한다. 하나는 문제가 발생하는 커밋(통상적으로 HEAD다)이고, 다른 하나는 문제가 발생하지 않는 커밋이다. git bisect는 문제가 발생하는 커밋과 발생하지 않는 커밋 사이를 체크아웃하고 테스트를 실행한다. 이러한 이진탐색 프로세스는 버그를 발생시킨 최초의 커밋을 찾을 때까지 반복된다.

git bisect는 백사장에서 바늘을 찾아야 하는 사용자를 위한 뜻밖의 선물인 셈이다. 버그가 발견될 것이라는 희망으로 모든 커밋을 낱낱이 검색해야 하는 번거로움을 덜어주기 때문이다. 최소한으로 잡더라도 이는 해야 할 검색과 테스트의 양을 절반으로 줄여줄 것이다. 

4. git cherry-pick으로 커밋 재적용하기 
많은 깃 고급 명령어가 특정 상황에서만 유용한 탓에 일반적인 고급 사용자들은 이를 무시해버리는 경우가 있다. 하지만 그러한 특정 상황에 직면하게 된다면? 고급 명령어를 아는 것은 득이 된다. 

git cherry-pick은 어떤 브랜치의 커밋이든 원하는 특정 커밋을 가져다가 다른 브랜치에 적용할 수 있는 명령어다. 이는 몇 가지 특정 상황에서 유용하다.

• 잘못된 브랜치에 커밋을 했고, 올바른 브랜치에 빠르게 적용하고자 하는 경우
• 트렁크(메인 브랜치) 코드에 대한 다른 작업을 계속하기 전에 브랜치에서 트렁크까지 수정사항을 적용하려는 경우

커밋을 cherry-pick할 때 커밋을 직접 적용하는 것 외에 몇 가지 옵션이 있다는 점에 유의해야 한다. 예를 들면 --no-commit 옵션을 설정하면 체리픽된 커밋이 현재 브랜치의 준비 영역에 배치된다.

5. Git submodule로 간결하게 프로젝트 구성하기
대부분의 프로그래밍 언어가 패키지나 모듈을 가져오는 방법을 제공한다. 이와 유사하게 깃도 한 리포지토리 안에 다른 리포지토리를 자동으로 넣을 수 있는 submodule을 지원한다. 

즉 리포지토리 내부에 하위 디렉토리를 생성하고 여기에 다른 리포지토리를 자동으로 가져올 수 있다. 일반적으로 일관성을 위해 특정 커밋 해시를 명시한다. Git submodule은 아래와 같은 조건에서 가장 유용하다. 

• 해당 서브모듈이 자주 변경되지 않거나 특정 커밋에 고정된 경우. 서브모듈이 아니라 서브모듈에 대한 모든 작업을 별도로 관리해야 하는 경우.

• 모든 사용자가 서브모듈을 지원하는 깃 버전을 사용 중인 경우. 예를 들면 서브모듈 디렉토리가 언제나 서브모듈 리포지토리를 자동으로 가져오는 것은 아니다. 모든 것을 최신 상태로 가져오려면 Git submodule update 명령어를 사용해야 할 수도 있다. ciokr@idg.co.kr

X