정리

  • 주된 활용 목적은 오프라인 환경에서의 커밋 전달
  • remote 를 명시하지 않고 오프라인 환경간에 파일전달로 커밋을 공유할 수 있음
  • codex cli 를 컨테이너로 올릴 경우 자체적인 샌드박스가 적용됨
    • 샌드박스를 완전히 풀지 않고 seccomp, apparmor 를 건드려도, 기존에 존재하던 .git 에의 반영은 codex 샌드박스에서 막고 있음
      • 제한을 완전히 해제했을 경우에만 인스턴스 자체적으로 반영시킬 수 있다
    • 자체적으로 컨테이너 내부경로에 별도의 커밋으로 커밋시킨 후, 권한을 조절해서 이 커밋을 원래 git 에 반영함

1. 개요

git bundle은 Git 객체(objects)와 참조(refs)를 .bundle 파일로 패키징하는 명령어다. 원격 Git 서버에 접근할 수 없어도 파일을 복사해 다른 저장소로 커밋 이력을 전달할 수 있다.

저장소 A ── git bundle create ──> changes.bundle
                                         │
                                    파일 전달
                                         ▼
저장소 B <─────── git fetch ─────── changes.bundle
  • 주요 용도: 오프라인 전달, 망 분리 환경의 저장소 동기화, 커밋 이력 백업, 별도 작업 저장소에서 만든 커밋의 이전
  • 전달 대상: 선택한 참조 및 해당 참조에서 도달 가능한 Git 커밋·트리·블롭 객체(또는 기준 이력 이후의 객체)
  • 전달하지 않는 것: 미커밋 작업 파일 변경, 인덱스 상태, 저장소별 Git 설정, hooks 등 로컬 환경 상태
  • 핵심 제약: Bundle 파일은 Git 저장소처럼 clone/fetch하는 읽기 소스이며 git push의 쓰기 대상이 아니다.

2. 명령어 요약

명령어기능사용 예시
git bundle createBundle 파일 생성git bundle create backup.bundle --all
git bundle verify파일 형식 및 대상 저장소의 선행 객체 보유 여부 검증git bundle verify backup.bundle
git bundle list-headsBundle에 기록된 참조 목록 조회git bundle list-heads backup.bundle
git bundle unbundleGit 객체를 직접 풀어 저장소에 등록(저수준 명령)git bundle unbundle backup.bundle
git clone독립 실행 가능한 전체 Bundle에서 신규 저장소 생성git clone backup.bundle restored-repo
git fetch기존 저장소에 Bundle의 객체와 참조 가져오기git fetch backup.bundle main

일반적인 사용에서는 unbundle보다 clone 또는 fetch를 권장한다.

3. 기본 사용법

3.1 전체 참조 기준 Bundle 생성

원본 Git 저장소에서 실행한다.

git bundle create backup.bundle --all

--all은 모든 Git 참조를 기준으로 도달 가능한 이력을 포함한다. 다만 작업 디렉터리의 미커밋 변경 사항이나 저장소 설정까지 백업하지는 않는다.

Bundle에서 새로운 저장소를 만든다.

git clone backup.bundle restored-repo

3.2 특정 브랜치만 Bundle 생성

git bundle create feature.bundle feature

이 예시는 feature 브랜치에서 도달 가능한 전체 이력을 포함하므로 기본적으로 다른 저장소의 선행 커밋 보유를 전제로 하지 않는다.

기존 저장소에서 가져온다.

git bundle list-heads feature.bundle
git fetch feature.bundle feature
git log --oneline -5 FETCH_HEAD

fetch는 커밋 객체를 가져오지만 현재 작업 브랜치에 자동으로 병합하지 않는다. 병합하려면 변경 내용을 확인한 뒤 별도 명령을 사용한다.

git merge FETCH_HEAD

현재 브랜치와 관계없이 별도 브랜치로 검토하려면:

git switch -c imported-feature FETCH_HEAD

git switch -c의 브랜치 이름은 대상 저장소에서 사용되지 않은 이름이어야 한다.

4. 증분 Bundle

전체 이력이 아니라 기준 커밋 이후의 이력만 전달할 수 있다.

A ── B ── C ── D ── E
          ▲         ▲
       기준 커밋   feature

C에 해당하는 태그 v1.0.0이 존재한다면:

git bundle create changes.bundle v1.0.0..feature

이 Bundle에는 기준 이력 이후의 객체가 담긴다. 따라서 대상 저장소는 기준 커밋 및 필요한 선행 객체를 이미 보유해야 한다.

대상 저장소에서 검증 후 가져온다.

git bundle verify changes.bundle
git fetch changes.bundle feature

증분 Bundle은 기준 커밋이 없는 빈 디렉터리에서 git clone하는 용도로 사용할 수 없다. 기준 이력을 포함한 전체 Bundle을 먼저 전달하거나 기존 저장소에 기준 객체가 존재해야 한다.

5. 확인 및 진단

Bundle에 포함된 참조 확인:

git bundle list-heads backup.bundle

대상 저장소에서 Bundle 적용 가능성 확인:

git bundle verify changes.bundle

참조를 원격 저장소처럼 조회:

git ls-remote backup.bundle

verify 실패 시에는 Bundle 손상 여부뿐 아니라 대상 저장소에 필요한 선행 커밋이 없는지 확인해야 한다.

6. 다른 전달 방식과 비교

구분Git BundleGit Patch (format-patch)Git Clone / Fetchtar / zip
커밋 객체 및 원래 커밋 ID 전달가능직접 전달하지 않음가능일반적으로 불가능
브랜치·태그 참조 전달가능불가능가능일반적으로 불가능
오프라인 파일 전달가능가능로컬 저장소 경유 시 가능가능
증분 전달가능가능가능별도 설계 필요
미커밋 파일 변경 포함불가능별도 diff 생성 필요불가능포함하도록 압축 가능
빈 저장소 복원선행 객체 없는 전체 Bundle일 때 가능커밋 적용용 대상 저장소 필요가능.git 포함 여부에 따라 다름
  • Bundle: Git 객체와 이력을 보존해 이동한다.
  • Patch: 변경 내용을 텍스트 패치 형태로 이동하고 수신측에서 새 커밋으로 적용할 수 있다.
  • Archive: 파일 자체를 복사하며 Git 이력 전달은 기본 목적이 아니다.

7. 읽기 전용 .git 환경에서 활용

예를 들어 컨테이너의 원본 저장소가 다음 오류를 반환하는 경우를 가정한다.

fatal: Unable to create '/workspace/stocktest/.git/index.lock': Read-only file system

이 오류는 원본 .git 경로에 Git이 필요한 잠금 파일을 만들 수 없다는 뜻이다. Git Bundle은 이 권한 문제를 우회하거나 해결하지 않는다. 대신 쓰기 가능한 별도 저장소에서 만든 커밋을 전달하는 용도로 활용할 수 있다.

7.1 쓰기 가능한 별도 저장소 준비

git clone /workspace/stocktest /tmp/stocktest-work
cd /tmp/stocktest-work

변경 및 커밋:

# 파일 수정 후
git add .
git commit -m "Fix issue"

7.2 커밋 이력 내보내기

작업 브랜치가 feature라고 가정하면:

git bundle create /tmp/changes.bundle feature

이 예시는 전체 브랜치 이력을 포함한다. 파일 크기를 줄이려면 원본과 공유하는 기준 커밋을 정한 뒤 증분 Bundle을 생성하면 된다.

# 예: base-tag가 실제로 존재할 때
git bundle create /tmp/changes.bundle base-tag..feature

7.3 원본에 반영

원본 .git이 쓰기 가능한 환경에서만 다음을 실행할 수 있다.

cd /workspace/stocktest
git bundle verify /tmp/changes.bundle
git fetch /tmp/changes.bundle feature
git log --oneline -5 FETCH_HEAD

검토가 끝나면 변경 내용을 병합하거나 원하는 커밋만 cherry-pick한다.

# 현재 브랜치에 병합하기로 결정한 경우
git merge FETCH_HEAD

결론: 원본 .git이 읽기 전용으로 유지되는 동안에는 git fetch, merge, commit 등을 원본 저장소에 정상 반영할 수 없다. 이 경우에는 마운트·실행 환경·파일시스템 권한을 수정하거나, 쓰기 가능한 별도 저장소로 결과를 전달해야 한다.

8. 운영상 주의사항

  1. 커밋 전 변경은 포함되지 않는다. 필요하면 커밋하거나 별도의 파일 복사·패치 절차를 사용한다.
  2. 증분 Bundle은 선행 객체가 필요하다. 대상 저장소에서 git bundle verify로 검증한다.
  3. Bundle은 저장소 환경 전체 백업이 아니다. 설정, hooks, 미커밋 변경 등을 따로 백업한다.
  4. Bundle로 git push할 수 없다. 파일을 다시 생성하는 방식으로 갱신해야 한다.
  5. 민감 정보 유출에 주의한다. 해당 Git 이력에 포함된 과거 비밀 정보도 Bundle에 담길 수 있다.
  6. Git LFS·서브모듈 데이터는 별도로 관리한다. Git에는 LFS 포인터 및 서브모듈 커밋 참조가 남을 수 있으나, 외부 LFS 객체나 다른 저장소의 전체 객체까지 일반 Bundle 하나가 자동으로 보관하지는 않는다.

9. 명령어 치트시트

# 전체 참조를 기준으로 생성
git bundle create backup.bundle --all
 
# 하나의 브랜치를 전체 이력과 함께 생성
git bundle create feature.bundle feature
 
# 기준 태그 이후의 이력만 생성
git bundle create incremental.bundle v1.0.0..feature
 
# 참조 목록 조회
git bundle list-heads backup.bundle
 
# 적용 가능성 검증 (대상 Git 저장소에서)
git bundle verify incremental.bundle
 
# 전체 Bundle에서 새 저장소 생성
git clone backup.bundle restored-repo
 
# 기존 저장소에 가져오기
git fetch feature.bundle feature
 
# 가져온 커밋 확인
git log --oneline -5 FETCH_HEAD

10. 공식 참고 자료