GitLab 에서 GitHub로 Repository를 이전했다.
나중에 또 필요할 때를 대비해서 일단 순서부터 기록 겸...
Repository A를 Repository B로 옮기는 순서 [출처]
- git bash를 연다
- A를 clone받기
$ git clone --bare [A주소]
- 폴더 이동하고 B에 푸시하기
$ cd [A 폴더] $ git push --mirror [B주소]
- 임시 로컬 저장소A를 지우기
$ cd .. $ rm -rf [A 폴더]
옮기다 보니 ... git clone의 bare/mirror 옵션에 대해 궁금한 게 생겼다.
Bare?
그런데 bare가 정확히 무엇을 말하는 것일까? bare의 단어 뜻은 알지만 여기선 어떻게 사용되고 있는 걸까. git 공식 문서에서는 bare에 대해 단독으로 설명한 건 없고 git clone --bare 등으로 명령어와 괸련된 것밖에 없는 것 같다. 몇몇 문서의 문구에서 가져온 바로는 아래 두 문구가 유의미한 게 아닐까...
a new bare repository — a repository that doesn’t contain a working directory.
That is, instead of creating <directory> and placing the administrative files in <directory>/.git, make the <directory> itself the $GIT_DIR.
Bare Repo / Non-Bare Repo
찾다보니 non-bare repository와의 차이점은 무엇일까 하는 호기심도 생겼다. 그래서 차이점도 검색해보았는데, 많은 답변이 달린 스택오버플로우의 문서를 보면서 최대한 이해해보려고 했다. 그중에서 Greg Owen 의 게시글이 가장 와닿아 가볍게 정리해두고 넘어간다. Greg은 용어를 임의로 정의하고(?) 설명했는데 이해에 도움이 되었다. 그가 보충 설명을 해둔 블로그도 있는데 이건 나중에 읽고 정리를 해보는 게 좋겠다.
Snapshot: repo의 모든 파일들. 코드, 등... (working tree)
History: repo가 존재한 이래로 파일의 모든 변경이력과 상태
Non-bare Repo [ Default ] | Bare-repository | |
Snapshot | O | X |
History | O | O |
쉽게 생각해서 bare-repo는 working tree가 없는, 협업을 위해 추적하고 상태의 변화를 기록하는 것이고 non-bare는 내용물까지 함께 있는 것이라고 생각하면 될 것 같다.
Git clone bare/mirror
아무튼 다시 돌아와서 그렇다면 git clone bare와 git clone mirror의 차이점이 무엇일까?
먼저 한번 직접 원격 레포지토리를 git clone bare와 mirror를 해서 실험해봤다.
git clone bare / mirror의 디렉토리상 차이점
diff 명령어로도 차이를 비교해보았다.
$ diff baregit/originalrepo.git mirrorgit/originalrepo.git
diff baregit/originalrepo.git/config mirrorgit/originalrepo.git/config
8a9,10
> fetch = +refs/*:refs/*
> mirror = true
Common subdirectories: baregit/originalrepo.git/hooks and mirrorgit/originalrepo.git/hooks
Common subdirectories: baregit/originalrepo.git/info and mirrorgit/originalrepo.git/info
Common subdirectories: baregit/originalrepo.git/objects and mirrorgit/originalrepo.git/objects
Only in mirrorgit/originalrepo.git: refs
ref..가 있고 없고의 차이가 있다는 것 같다. 그럼 ref는 뭘까? 일단 이건 나중에 따로 더 공부해보기로 하자.
설명을 찾아서
git 공식문서상의 서술
--bare
Make a bare Git repository. That is, instead of creating <directory>
and placing the administrative files in <directory>/.git
, make the <directory>
itself the $GIT_DIR
. This obviously implies the --no-checkout
because there is nowhere to check out the working tree. Also the branch heads at the remote are copied directly to corresponding local branch heads, without mapping them to refs/remotes/origin/
. When this option is used, neither remote-tracking branches nor the related configuration variables are created.
git clone -mirror 공식문서
--mirror
Set up a mirror of the source repository. This implies --bare
. Compared to --bare
, --mirror
not only maps local branches of the source to local branches of the target, it maps all refs (including remote-tracking branches, notes etc.) and sets up a refspec configuration such that all these refs are overwritten by a git remote update
in the target repository.
Atlassian Git Tutorial에서의 git clone파트 :: git clone -mirror vs. git clone -bare
git clone --bare
Similar to git init --bare, when the -bare argument is passed to git clone, a copy of the remote repository will be made with an omitted working directory. This means that a repository will be set up with the history of the project that can be pushed and pulled from, but cannot be edited directly. In addition, no remote branches for the repo will be configured with the -bare repository. Like git init --bare, this is used to create a hosted repository that developers will not edit directly.
git clone --mirror
Passing the --mirror argument implicitly passes the --bare argument as well. This means the behavior of --bare is inherited by --mirror. Resulting in a bare repo with no editable working files. In addition, --mirror will clone all the extended refs of the remote repository, and maintain remote branch tracking configuration. You can then run git remote update on the mirror and it will overwrite all refs from the origin repo. Giving you exact 'mirrored' functionality.
나름의 정리 ( git clone[non-bare(normal)] vs git clone --bare vs git clone --mirror )
문서를 봐도 잘 모르겠어서 두 개의 게시글을 더 참조해서 보다가 이해 겸 정리로 표로 정리해보고 있었는데, Atlassian에서 좋은 게시글을 발견해서 추가함.
- 스텍오버플로우에서 설명이 잘 되어있는 글: What's the difference between git clone --mirror and git clone --bare
- 다른 분이 자료로 작성한 bare과 mirror의 차이점 (normal, no-checkout 옵션도 포함) git clone [bare/mirror] 에 대해서 알아보기
- Atlassian git tutorial 의 멋진 설명 ... 깔끔하게 설명해두었다.
스택오버플로우 설명의 전제
Suppose origin has a few branches (master (HEAD), next, pu, and maint), some tags (v1, v2, v3), some remote branches (devA/master, devB/master), and some other refs (refs/foo/bar, refs/foo/baz, which might be notes, stashes, other devs' namespaces, who knows).
원본이 브런치, 태그, 원격브런치, refs를 갖고 있다고 가정할 때...
git clone origin-url (non-bare) |
git clone --bare origin-url | git clone --mirror origin-url | |
Local branch | You will get a local branch master (HEAD) tracking a remote branch origin/master and remote branches origin/next, origin/pu, and origin/maint 원격 브랜치를 추적하는 로컬 브랜치가 생긴다. |
You will get local branches master (HEAD),next,pu, andmaint, no remote tracking branches. 원격 추적 브랜치가 생성되지 않음 |
You'll get local branches master (HEAD), next, pu, and maint, remote branches devA/master and devB/master. 원격 브런치가 생성됨 |
Remote Tracking | The tracking branches are set up so that if you do something like git fetch origin, they'll be fetched as you expect. 원격 추적 이뤄짐 |
You will get no remote tracking branches. That is, all branches are copied as is, and it's set up completely independent, with no expectation of fetching again. 원격 추적 X |
Remote tracking is set up so that if you run git remote update all refs will be overwritten from origin, as if you'd just deleted the mirror and recloned it. 하려면 할 수 있으나 삭제됨 |
Remote Branches | Any remote branches (in the cloned remote) and other refs are completely ignored. | Any remote branches (in the cloned remote) and other refs are completely ignored. | |
Tags | You will get all of the tags copied. | You will get all of the tags copied. | You will get all of the tags copied. |
refs | Every last one of those refs will be copied as-is. You will get other refs refs/foo/bar and refs/foo/baz. | ||
Interchangeable? | It's supposed to be a functionally identical copy, interchangeable with the original. | ||
어디까지? | Commit 이력만 담고 있음. "refs/heads/*" |
commit 이력과 기타를 모두 담고 있음. "refs/pull/*" (GitHub에서 Pull-Request를 할 때 사용되는 commit들이 기록되는 위치) |
|
언제 쓰지? | 완전히 별개로 분리독립할 때? | 언젠가 원본 repo에서 업데이트가 필요할 것 같을 때 쓰면 될 것 같다. | |
초간단정리(?) | clone한 곳과 연결됨 | clone한 곳과 연결 x, 완벽하게 독립적 |
clone한 원본과 tracking할수있는 설정을 유지하고 있음. git remote 명령어로 원본 repo에서 overwrite를 할 수 있음. |
참고문헌
Gitlab에서 github으로 커밋이력까지 함께 복사하기
What's the -practical- difference between a Bare and non-Bare repository?
What's the difference between git clone --mirror and git clone --bare
git clone [bare/mirror] 에 대해서 알아보기
나중에 참조하면 좋을 곳
https://velog.io/@helmodev/Git-MirrorBare
https://pinocc.tistory.com/138
https://www.youtube.com/watch?v=_AtF3toaOj0