[첫화면으로]Git/저장소병합

마지막으로 [b]

14 번째 수정본

git 저장소 두 개를 병합

1. 상황

저장소 A와 B가 있다.

A - /
    /fileA

B - /
    /fileB

A 저장소를 B에 합치면서, 기존 커밋 로그 등도 다 가져오고 싶다.

(커밋 로그 같은 거 가져올 필요가 없다면... 그냥 fileA를 복사하면 된다)

2. 디렉토리 이동이 필요없는 경우

B - /
    /fileA
    /fileB

이렇게 만들 경우는 쉽다.

$ cd B
# A저장소의 master브랜치를 fetch로 가져온다 (branch_A는 임의로 지은 이름)
$ git fetch ../A/ master:branch_A
# B저장소의 master브랜치에서 그것을 병합한다
$ git merge branch_A

뭐 그나마 기분이 나쁜 거라면, 시작 커밋이 서로 다른 두 히스토리를 합쳤으니까 한 커밋에서 시작하는 게 아니라 두 커밋에서 시작해서 나중에 합쳐진 형태의 그래프가 된다.

원한다면 한쪽 히스토리와 다른 히스토리를 연결할 수도 있다. Git의 "두 저장소를 잇기"와 "CVS에서 Git로 이전하기" 참조.

3. 한쪽 저장소를 서브디렉토리에 두고 싶은 경우

B - /
    /A/fileA
    /fileB

이렇게 하려니, 은근히 복잡하다.

사실 이게 맞는지 제대로 정리가 안 되었는데, 반나절 동안 직접 해보면서 발견한 내용만 적어본다.

아래 내용들은 거의 다 [merge - How to import existing GIT repository into another? - Stack Overflow] 질문글에 달린 답변들이 출처이다.

3.1. fetch로 가져오고 mv로 옮기고 merge

# 여기서는 remote 저장소 추가를 했는데, 안 하고 그냥 위와 같이 fetch해도 될 것이다
[B (master)]$ git remote add repoA ../A/
[B (master)]$ git fetch repoA
From ../A
 * [new branch]      master     -> repoA/master

# 임시 브랜치를 만들고
[B (master)]$ git checkout -b TEMP repoA/master
Branch TEMP set up to track remote branch master from repoA.
Switched to a new branch 'TEMP'

# fileA를 A 서브디렉토리로 옮기고 커밋
[B (TEMP)]$ mkdir A
[B (TEMP)]$ git mv fileA A/fileA
[B (TEMP)]$ git commit -m "move fileA to A/"
[TEMP d13a3ce] move fileA to A/
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename fileA => A/fileA (100%)

# master 브랜치에서 병합
[B (TEMP)]$ git checkout master
Switched to branch 'master'
[B (master)]$ git merge TEMP
Merge made by the 'recursive' strategy.
 A/fileA |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 A/fileA

# 뒷정리
[B (master)]$ git remote rm repoA
[B (master)]$ git branch -d TEMP
Deleted branch TEMP (was d13a3ce).

이렇게 하면 git log를 했을 때 두 저장소의 로그도 잘 보인다. 그리고 A디렉토리로 옮기는 것을 나타내는 커밋 로그도 있어서 직관적이다.

문제는 뭐냐 하면, A 서브디렉토리 아래 있는 파일들의 개별 로그를 보는 게 귀찮다

# 이렇게 하면 A로 옮긴 이력만 나온다
$ git log -- A/fileA
commit d13a3ce29b1ffccc5ce1cda062883c750ddac390
Author: Geunyoung Park <gypark@gmail.com>
Date:   Thu Feb 11 00:42:59 2016 +0900

    move fileA to A/

# --follow를 붙여주어 rename에 관한 이력도 추적하게 해야 한다
$ git log --follow A/fileA
d13a3ce move fileA to A/
b010c01 A2
abcad74 init A

그런데 --follow 옵션을 붙일 때는 대상 파일을 하나밖에 지정할 수 없다. (보통은 파일 하나만 보면 충분하겠지만)

3.2. subtree merge

# 역시 원격 저장소를 추가하고 fetch
[B (master)]$ git remote add repoA ../A/
[B (master)]$ git fetch repoA
warning: no common commits
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From ../A
 * [new branch]      master     -> repoA/master

# 서브트리 병합인데, 이 단락들의 동작 원리는 나도 잘 모르겠다
[B (master)]$ git merge -s ours --no-commit repoA/master
Automatic merge went well; stopped before committing as requested
[B (master|MERGING)]$ git read-tree --prefix=A/ -u repoA/master
[B (master|MERGING)]$ git commit -m "imported A as a subtree."
[master 8d9a587] imported A as a subtree.

첫번째 방법과 비교하면, A 서브디렉토리로 이동하는 커밋이 따로 없다. 그리고 아마도 이게 중요한 장점일 것 같은데, A저장소가 갱신되면 그것을 받아와서 반영할 수 있다.

# 원래의 A저장소가 갱신된 후에 B저장소 쪽에서
[B (master)]$ git pull -s subtree repoA master
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../A
 * branch            master     -> FETCH_HEAD
Merge made by the 'subtree' strategy.
 A/fileA |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

그러니까, 별개의 프로젝트로 관리되고 있는 저장소를 통채로 가져와서 내 프로젝트의 일부로 사용하면서, 원 프로젝트쪽에서 새로 변경된 사항이 생기면 그것을 바로 가져와서 반영할 수 있는 것이다.

아마 최근 버전의 git은 subtree 병합에 대한 명령어가 따로 있는 것 같았다. /서브프로젝트 문서도 참고하자.

그런데 여기서 첫 번째와 똑같은 단점이 나온다. fileA의 변경이력만 추려내려면 귀찮다. 게다가 더 헷갈린다.

# 이렇게 하면 역시 B에 병합하는 커밋만 나옴
$ git log -- A/fileA
commit 8d9a5873987f558808ec4f1ec732cedccbb5e866
Merge: 42275bc b010c01
Author: Geunyoung Park <gypark@gmail.com>
Date:   Thu Feb 11 01:01:50 2016 +0900

    imported A as a subtree.

# 게다가 이렇게 하면, 이젠 아무것도 안 나옴
$ git log --follow -- A/fileA

# --follow는 여전히 붙인 채로
# 우리가 prefix로 지정한 A/ 부분은 빼고 원래 파일명만 써줘야 한다
$ git log --follow -- fileA
d48c21d A3
b010c01 A2
abcad74 init A

4. 기타 & comments

이름:  
Homepage:
내용:
 

컴퓨터분류

이 수정본 편집일: 2016-2-11 1:13 am (변경사항 [d])
3925 hits | Permalink | 변경내역 보기 [h] | 현재 수정본 보기 | 14 번째 수정본 소스 보기