Git
Chapters ▾ 2nd Edition

A2.4 Appendix B: 애플리케이션에 Git 넣기 - go-git

go-git

Go 언어로 작성한 서비스에 Git 기능을 통합하려고 한다면 순수하게 Go 언어로만 작성된 라이브러리 구현체가 있다. Go 언어로 작성된 라이브러리기에 네이티브 의존성이 없으며 메모리관리에서 오류가 날 가능성이 적다. 또한 Go 언어로 작성되었기에 Go 표준 성능 측정 도구(CPU, 메모리 프로파일, 경쟁상태 탐지 등)를 사용할 수 있다.

go-git은 확장성과 호환성에 중점을 두며 Plumbing API 대부분을 지원한다. 관련 내용은 https://github.com/src-d/go-git/blob/master/COMPATIBILITY.md 에서 확인할 수 있다.

Go 라이브러리 API를 사용하는 기본적인 예제는 다음과 같다.

import 	"gopkg.in/src-d/go-git.v4"

r, err := git.PlainClone("/tmp/foo", false, &git.CloneOptions{
    URL:      "https://github.com/src-d/go-git",
    Progress: os.Stdout,
})

위 코드를 실행하면 Repository 인스턴스를 할당받게 되고 이 인스턴스를 통해 저장소 정보를 가져오거나 어떤 변화를 줄 수 있다.

// HEAD가 가리키는 브랜치 Ref를 가져오기
ref, err := r.Head()

// Ref가 가리키는 커밋 개체를 가져오기
commit, err := r.CommitObject(ref.Hash())

// 커밋 히스토리 정보를 가져오기
history, err := commit.History()

// 히스토리에서 커밋을 하나씩 반복하여 정보를 출력하기
for _, c := range history {
    fmt.Println(c)
}

고급 기능

go-git에 몇 가지 주목할만한 고급 기능이 있다. 하나는 플러그 가능한 저장소 시스템이며 Libgit2의 “Backend” 비슷하다. 기본 구현은 메모리 저장소이기에 접근 속도가 매우 빠를수 밖에 없다.

r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
    URL: "https://github.com/src-d/go-git",
})

플러그 가능한 저장소는 다양한 재밌는 옵션을 제공한다. 예를 들어 https://github.com/src-d/go-git/tree/master/_examples/storage 내용을 보면 레퍼런스, 개체, 설정정보 등을 Aerospike 데이터베이스에 저장하는 예제를 볼 수 있다.

다른 고급 기능으로는 유연한 파일 시스템 추상화가 있다. https://godoc.org/github.com/src-d/go-billy#Filesystem 문서를 보면 쉽게 파일을 여러가지 다른 방식으로 저장하는 내용을 볼 수 있다. 하나의 큰 파일 덩어리로 처리할 수도 있고 메모리에 모두 적재시킬 수도 있다.

또 다른 고급기능을 사용하는 예제로 세세하게 설정가능한 HTTP 클라이언트를 사용하는 구현을 https://github.com/src-d/go-git/blob/master/_examples/custom_http/main.go 에서 찾아볼 수 있다.

customClient := &http.Client{
	Transport: &http.Transport{ // 모든 인증서를 통과시키기
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	},
	Timeout: 15 * time.Second,  // 15초 타임아웃
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse // 리다이렉트 응답을 따라가지 않기
	},
}

// 기본 https 클라이언트를 새로 작성한 임의의 클라이언트로 교체하기
client.InstallProtocol("https", githttp.NewClient(customClient))

// 새로 설정한 클라이언트를 사용하여 https 주소로 시작하는 저장소를 Clone 하기
r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{URL: url})

더 읽어볼 거리

go-git의 다양한 기능을 모두 다루는 것은 이 책이 담을 수 없는 영역에 있다. go-git에 흥미가 생기고 있다면 냉큼 https://godoc.org/gopkg.in/src-d/go-git.v4 로 가서 API 문서를, https://github.com/src-d/go-git/tree/master/_examples 로 가서 다양한 구현 예제를 찾아보기 바란다.