예전에 진행하던 시스템에서 TO-BE Repository에 AS-IS Repository의 히스토리를 이관하고 싶다는 요청이 들어왔다. 단순 커밋메세지를 복사하는 것으로는 안된다. 왜냐? Git은 해시값 기반으로 형상관리되어 무결성 원칙이 깨질 수 있기 때문이다.

그럼 할 수 있냐 없냐? 물론 할 수 있다. 그 방법을 포스팅하고자 한다

둘 중에 하나만 골라?

(Yes or Yes!)

1. 신규 파일이 생겼거나 파일 내용에 변경점이 없다 ⇒ Confilct X

merge하는 파일에 conflict가 없다면 그냥 아래 방법대로 진행하면 된다

2. 파일 내용에 변경점이 있다 ⇒ Confilct O

그러나 merge하는 파일에 conflict가 있을 경우가 문제다

보통 conflict가 발생하면 파일 내용에 아래와 같이 입력되어 있어서 수동으로 수정해줘야 한다

<<<<<<< HEAD
현재 브랜치 내용
=======
merge하는 브랜치 내용
>>>>>>>

한 두가지 파일이면 무리 없어도 몇백개(?) 정도는 힘들지 않을까..

처음부터 히스토리까지 같이 이관하도록 하자!

본격적으로 히스토리를 이관하는 방법

  1. AS-IS Repository에서 TO-BE Repository로 이관 후, “first commit” 하고 나서 일부러 파일 내용 하나 바꿔봤다

     $ git add .
     $ git commit -m "first commit"
     $ git remote get-url origin
     	https://github.com/gain-yoo/git-history-mv.git
     $ git push -u origin main
     $ vi README.md
     $ git add .
     $ git commit -m "README 수정"
     $ git push -u origin main
    
  2. AS-IS Repository의 히스토리를 이관하기 위해 remote로 AS-IS Repository를 추가하고 fetch한다

     $ git remote add old_git_remote https://github.com/gain-yoo/terraform-study.git
     $ git fetch old_git_remote
     	remote: Enumerating objects: 81, done.
     	remote: Counting objects: 100% (81/81), done.
     	remote: Compressing objects: 100% (61/61), done.
     	remote: Total 81 (delta 26), reused 60 (delta 10), pack-reused 0
     	Unpacking objects: 100% (81/81), 68.81 KiB | 224.00 KiB/s, done.
     	From https://github.com/gain-yoo/terraform-study
     	 * [new branch]      main       -> old_git_remote/main
    
  3. merge 하면 refuse 당한다 ⇒ --allow-unrelated-histories 옵션 사용해라

    이 옵션은 allow merging unrelated histories 라고 설명되어 있다.

    덧붙이자면, 이미 존재하는 두 프로젝트의 기록(history)을 저장하는 드문 상황에 사용된다고 한다. 즉, git에서는 서로 관련 기록이 없는 이질적인 두 프로젝트를 병합할 때 기본적으로 거부하는데, 이것을 허용해 주는 것이다. (라고 아래 블로그를 참고했다)

    Git push가 안되는 경우 (fatal: refusing to merge unrelated histories)

     $ git merge old_git_remote/main
     	fatal: refusing to merge unrelated histories
     $ git merge old_git_remote/main --allow-unrelated-histories
     	Auto-merging README.md
     	CONFLICT (add/add): Merge conflict in README.md
     	Automatic merge failed; fix conflicts and then commit the result.
    

    하지만 conflict로 인해 바로 merge되지는 않는다.

    • (바로 merge되는 경우) 아래 파일 내용이 뜨고 :wq로 저장하면 merge 성공!

        Merge remote-tracking branch 'old_remote/main'
        # Please enter a commit message to explain why this merge is necessary,
        # especially if it merges an updated upstream into a topic branch.
        #
        # Lines starting with '#' will be ignored, and an empty message aborts
        # the commit.
      
        $ git merge old_remote/main --allow-unrelated-histories
        	Merge made by the 'ort' strategy.
      
        $ git push -u origin main
        	Enumerating objects: 56, done.
        	Counting objects: 100% (56/56), done.
        	Delta compression using up to 8 threads
        	Compressing objects: 100% (43/43), done.
        	Writing objects: 100% (47/47), 5.33 KiB | 779.00 KiB/s, done.
        	Total 47 (delta 21), reused 0 (delta 0), pack-reused 0
        	remote: Resolving deltas: 100% (21/21), completed with 6 local objects.
        	To https://github.com/gain-yoo/git-h-mv-2.git
        	   e467138..118a8ed  main -> main
        	branch 'main' set up to track 'origin/main'.
      
  4. conflict 생긴 파일 수정 후 commit & push

    conflict 파일을 수정하고 나니 아까 merge 했던 것도 같이 적용된다. 이제 remote 서버에 push하면 이전 히스토리 내역까지 같이 push된걸 확인할 수 있다

     $ vi README.md
     $ git merge old_git_remote/main --allow-unrelated-histories
     	error: Merging is not possible because you have unmerged files.
     	hint: Fix them up in the work tree, and then use 'git add/rm <file>'
     	hint: as appropriate to mark resolution and make a commit.
     	fatal: Exiting because of an unresolved conflict.
     $ git add README.md
     $ git commit -m "test1"
     	[main c4fe410] test1
     $ git merge old_git_remote/main --allow-unrelated-histories
     	Already up to date.
     $ git push -u origin main
    
  5. AS-IS Repository 히스토리 이관 완료!!!
  6. AS-IS Repository와 TO-BE Repository의 커밋내역을 비교하면 이전 커밋내역의 해시값도 동일하게 이관된 것을 확인할 수 있었다! 이것이 git에서의 무결성!

    Untitled 2

참고자료

git 이관 (히스토리 포함)

Categories:

Updated:

Leave a comment