Pro git - 7.12
Updated:
Pro git - Bundle
1. Bundle
-
Git 데이터를 네트워크를 거쳐 전송하는 일반적인 방법(HTTP, SSH등) 외에 Bundle이라는 것이 있다.
- 예를 들어 네트워크가 불통인데 변경사항을 동료에게 보낼 때
- 출장을 나갔는데 보안상의 이유로 로컬 네트워크에 접속하지 못할 때
- 통신 인터페이스 장비가 고장났을 때, 갑자기 공용 서버에 접근하지 못할 때
-
누군가에게 수정사항을 이메일로 보내야 하는데 40개 씩이나 되는 커밋을
format-patch
로 보내고 싶지 않을 때 git bundle
명령은 보통git push
명령으로 올려 보낼 모든 것을 감싸서 한 바이너리 파일로 만든다.-
이 파일을 이메일로 보내거나 USB로 다른 사람에게 보내서 다른 저장소에 풀어서(Unbundle) 사용한다.
- 간단한 예제를 보자. 이 저장소에는 커밋 두 개가 있다.
$ git log
commit 9a466c572fe88b195efd356c3f2bbeccdb504102
Author: Scott Chacon <schacon@gmail.com>
Date: Wed Mar 10 07:34:10 2010 -0800
second commit
commit b1ec3248f39900d2a406049d762aa68e9641be25
Author: Scott Chacon <schacon@gmail.com>
Date: Wed Mar 10 07:34:01 2010 -0800
first commit
- 이 저장소를 다른 사람에게 통째로 보내고 싶은데 그 사람의 저장소에 Push 할 권한이 없거나, 그냥 Push 하고 싶지 않을 때,
git bundle create
명령으로 Bundle을 만들 수 있다.
$ git bundle create repo.bundle HEAD master
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 441 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
- 이렇게
repo.bundle
이라는 이름의 파일을 생성할 수 있다. - 이 파일에는 이 저장소의
master
브랜치를 다시 만드는 데 필요한 모든 정보가 다 들어 있다. bundle
명령으로 모든 Refs를 포함하거나 Bundle에 포함할 특정 구간의 커밋을 지정할 수 있다.-
이 Bundle을 다른 곳에서 Clone 하려면 위의 명령처럼 HEAD Refs를 포함해야 한다.
-
repo.bundle
파일을 다른 사람에게 이메일로 전송하거나 USB 드라이브에 담아서 나갈 수 있다. - 혹은
repo.bundle
파일을 일할 곳으로 어떻게든 보내놓으면 이 Bundle 파일을 마치 URL에서 가져온 것처럼 Clone 해서 사용할 수 있다.
$ git clone repo.bundle repo
Cloning into 'repo'...
...
$ cd repo
$ git log --oneline
9a466c5 second commit
b1ec324 first commit
- Bundle 파일에 HEAD Refs를 포함하지 않으려면
-b master
옵션을 써주거나 포함시킬 브랜치를 지정해줘야 한다. -
그렇지 않으면 Git은 어떤 브랜치로 Checkout 할지 알 수 없다.
- 이제 새 커밋 세 개를 추가해서 채운 저장소를 다시 원래 Bundle을 만들었던 저장소로 USB든 메일이든 Bundle로 보내 새 커밋을 옮겨보자.
$ git log --oneline
71b84da last commit - second repo
c99cf5b fourth commit - second repo
7011d3d third commit - second repo
9a466c5 second commit
b1ec324 first commit
- 먼저 Bundle 파일에 추가시킬 커밋의 범위를 정해야 한다.
- 전송할 최소한의 데이터를 알아서 인식하는 네트워크 프로토콜과는 달리 Bundle 명령을 사용할 때는 수동으로 지정해야 한다.
- 전체 저장소를 Bundle 파일로 만들 수도 있지만, 차이점만 Bundle로 묶는 게 좋다.
-
예제에서는 로컬에서 만든 세 개의 커밋만 묶는다.
- 우선 차이점을 찾아내야 Bundle 파일을 만들 수 있다.
- 숫자를 사용하여 커밋의 범위를 지정할 수 있다.
- 원래 Clone 한 브랜치인 master에는 없던 세 개의 커밋을 얻어내려면
origin/master..master
또는master ^origin/master
파라미터를 쓰면 된다. log
명령으로 시험해볼 수 있다.
$ git log --oneline master ^origin/master
71b84da last commit - second repo
c99cf5b fourth commit - second repo
7011d3d third commit - second repo
- 이제 Bundle 파일에 포함할 커밋을 얻었으니 묶어보자.
git bundle create
명령에 Bundle 파일의 이름과 묶어 넣을 커밋의 범위를 지정한다.
$ git bundle create commits.bundle master ^9a466c5
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), 775 bytes, done.
Total 9 (delta 0), reused 0 (delta 0)
-
이제 디렉토리에
commits.bundle
파일이 생겼다. 이 파일을 동료에게 보내면 원래의 저장소에 일이 얼마나 진행되었든 간에 파일 내용을 적용할 수 있다. - 이 Bundle 파일을 동료가 받았으면 원래 저장소에 적용하기 전에 무엇이 들어 있는지 살펴볼 수 있다.
- 우선
bundle verify
명령으로 파일이 올바른 Git Bundle인가, 제대로 적용하는 데 필요한 모든 히스토리가 현재 저장소에 있는가 확인한다.
$ git bundle verify ../commits.bundle
The bundle contains 1 ref
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
The bundle requires these 1 ref
9a466c572fe88b195efd356c3f2bbeccdb504102 second commit
../commits.bundle is okay
- 만약 앞에서 Bundle 파일을 만들 때 커밋 세 개로 만들지 않고 마지막 두 커밋으로만 Bundle 파일을 만들면 커밋이 모자라기 때문에 최초에 Bundle을 만들었던 저장소에 새 Bundle 파일을 합칠 수 없다.
- 이런 문제를
verify
명령으로 확인할 수 있다.
$ git bundle verify ../commits-bad.bundle
error: Repository lacks these prerequisite commits:
error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 third commit - second repo
- 제대로 만든 Bundle 파일이라면 커밋을 가져와서 최초 저장소에 합칠 수 있다.
- 데이터를 가져올 Bundle 파일에 어떤 브랜치를 포함하고 있는지 살펴보려면 아래와 같은 명령으로 확인할 수 있다.
$ git bundle list-heads ../commits.bundle
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
- 앞에서
verify
명령을 실행했을 때도 브랜치 정보를 확인할 수 있다. - 여기서 중요하게 짚을 부분은
fetch
명령이나pull
명령으로 가져올 대상이 되는 브랜치를 Bundle 파일에서 확인하는 것이다. - 예를 들어 Bundle 파일의 master 브랜치를 작업하는 저장소의 other-master 브랜치로 가져오는 명령은 아래와 같이 실행한다.
$ git fetch ../commits.bundle master:other-master
From ../commits.bundle
* [new branch] master -> other-master
- 이런 식으로 작업하던 저장소의 master 브랜치에 어떤 작업을 했든 상관없이 Bundle 파일로부터 커밋을 독립적으로 other-master 브랜치로 가져올 수 있다.
$ git log --oneline --decorate --graph --all
* 8255d41 (HEAD, master) third commit - first repo
| * 71b84da (other-master) last commit - second repo
| * c99cf5b fourth commit - second repo
| * 7011d3d third commit - second repo
|/
* 9a466c5 second commit
* b1ec324 first commit
git bundle
명령으로 데이터를 전송할 네트워크 상황이 여의치 않거나 쉽게 공유할 수 있는 저장소를 준비하기 어려울 때도 히스토리를 쉽게 공유할 수 있다.