히스토리가있는 SVN 저장소를 새로운 Git 저장소로 어떻게 마이그레이션합니까?


1509

나는 Git 매뉴얼, FAQ, Git-SVN 크래시 코스 등을 읽었으며 모두 이것과 그에 대해 설명하지만 어디에도 다음과 같은 간단한 지시 사항을 찾을 수 없습니다.

SVN 저장소 : svn://myserver/path/to/svn/repos

Git 저장소 : git://myserver/path/to/git/repos

git-do-the-magic-svn-import-with-history \
svn://myserver/path/to/svn/repos \
git://myserver/path/to/git/repos

나는 그것이 그렇게 단순하다고 기대하지 않으며, 그것이 단일 명령이라고 기대하지 않습니다. 그러나 나는 아무것도 설명하지 않으려 고 기대합니다.이 예를 들어 어떤 단계를 취해야하는지 말하십시오.


6
점점 쉬워 졌고
John Moses

아래에서 Casey의 답변을 사용하되 "svn clone ..."명령을 실행하기 전에 user.txt 파일에 "Visual SVN Server"줄을 추가하는 방법을 참조하십시오. 여기 : stackoverflow.com/questions/8971208/ ...
맥가이버

1
또한, "GitHub 프로필에서"전자 메일을 비공개로 설정 "옵션을 선택한 경우이 주소를 users.txt의 이메일 주소로 사용하십시오. yourgituser@users.noreply.github.com 실제 이메일 주소가 표시되지 않도록
MacGyver

답변:


529

마법:

$ git svn clone http://svn/repo/here/trunk

Git과 SVN은 매우 다르게 작동합니다. Git을 배우고 SVN 업스트림의 변경 사항을 추적하려면을 배워야 git-svn합니다. git-svn 메인 페이지는 좋은 예 섹션이 있습니다 :

$ git svn --help

139
@Casey의 답변은 원래 질문에 훨씬 잘 대답합니다.
더그 윌슨

3
이것은 가지와 모든 것을 유지할 것인가? 아니면 그냥 트렁크를 복제?
Eildosa

7
@Eildosa : 트렁크를 복제합니다. 대안에 대해서는 Casey의 답변을 참조하십시오.
sleske

3
@ DougWilson하지만 여기에 Casey의 답변이 없습니다. "사용자 파일 만들기"로 시작하는 13 명의 저자가 아래 답변입니까?
Andrey Regentov

67
주변 의견을 많이 참조되는 "케이시의 대답은"어느 궁금있어 다른 사람을 위해, 그것의 이 한 (케이시 cmcginty에 자신의 닉네임을 변경).
Stefan Monov

1559

users.txtSVN 사용자를 Git에 맵핑하기위한 사용자 파일 (예 :)을 작성하십시오.

user1 = First Last Name <email@address.com>
user2 = First Last Name <email@address.com>
...

이 단일 라이너를 사용하여 기존 SVN 저장소에서 템플릿을 작성할 수 있습니다.

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt

파일에없는 SVN 사용자가 없으면 SVN이 중지됩니다. 그러나 그 후에는 파일을 업데이트하고 중단 한 부분을 선택할 수 있습니다.

이제 저장소에서 SVN 데이터를 가져옵니다.

git svn clone --stdlayout --no-metadata --authors-file=users.txt svn://hostname/path dest_dir-tmp

이 명령은 새로운 Git 저장소를 생성 dest_dir-tmp하고 SVN 저장소를 가져 오기 시작합니다. "--stdlayout"플래그는 일반적인 "trunk /, branches /, tags /"SVN 레이아웃을 의미합니다. 레이아웃 다릅니다은, 익숙해 경우 --tags, --branches, --trunk옵션 (일반적으로 git svn help).

모든 공통 프로토콜이 허용됩니다 svn://, http://, https://. URL은 http://svn.mycompany.com/myrepo/repository 와 같은 기본 저장소를 대상으로해야합니다 . URL 문자열은 있어야 하지 포함 /trunk, /tag또는 /branches.

이 명령을 실행 한 후에는 작업이 "중단 / 정지"된 것처럼 보이는 경우가 많으며 새 리포지토리를 초기화 한 후 오랜 시간 동안 중단 될 수 있습니다. 결과적으로 마이그레이션 중임을 나타내는 로그 메시지가 표시됩니다.

또한이 생략하면 참고 --no-metadata플래그를 커밋 메시지에, 힘내 해당 SVN 개정에 대한 정보를 추가합니다 (예 git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID>)

사용자 이름을 찾을 수 없으면 users.txt파일을 업데이트 한 후 다음을 수행하십시오.

cd dest_dir-tmp
git svn fetch

대규모 프로젝트가있는 경우 모든 Subversion 커밋을 가져올 때까지 마지막 명령을 여러 번 반복해야 할 수도 있습니다.

git svn fetch

완료되면 Git은 SVN trunk을 새로운 지점으로 체크 아웃합니다 . 다른 지점은 리모컨으로 설정됩니다. 다음을 사용하여 다른 SVN 분기를 볼 수 있습니다.

git branch -r

저장소에 다른 원격 브랜치를 유지하려면 각 원격 브랜치를 수동으로 작성하려고합니다. (건너 뛰기 트렁크 / 마스터)이 작업을 수행하지 않으면 마지막 단계에서 분기가 복제되지 않습니다.

git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same name

태그는 분기로 가져옵니다. 로컬 브랜치를 생성하고, 태그를 만들고, 브랜치를 삭제하여 Git에서 태그로 사용하십시오. "v1"태그로이를 수행하려면 :

git checkout -b tag_v1 remotes/tags/v1
git checkout master
git tag v1 tag_v1
git branch -D tag_v1

GIT-SVN 저장소를 깨끗한 Git 저장소로 복제하십시오.

git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir

원격 브랜치에서 이전에 생성 한 로컬 브랜치는 원격 브랜치로만 새로운 복제 된 리포지토리에 복사됩니다. (건너 뛰기 트렁크 / 마스터) 유지하려는 각 지점에 대해 다음을 수행하십시오.

git checkout -b local_branch origin/remote_branch

마지막으로, 삭제 된 임시 저장소를 가리키는 클린 Git 저장소에서 원격을 제거하십시오.

git remote rm origin

36
Eelke의이 블로그 게시물은 위의 답변에 대한 훌륭한 상호 참조입니다. blokspeed.net/blog/2010/09/converting-from-subversion-to-git
kgriffs

4
이것은 99 % 굉장합니다. 다음 단계를 따라 분기를 제외한 모든 것을 순서대로 얻었습니다. 마지막 단계 후에는 원격 상태였습니다 (그리고 명령을 수행하면 사라졌습니다. git remote rm origin)
Dirty Henry

4
GitHub는 매우 편리한 단계별 기능을 제공합니다 : github.com/nirvdrum/svn2git#readme
Dan Nissenbaum

8
Windows 사용자의 경우이 방법을 기반으로 PowerShell 스크립트를 만들었습니다. gist.github.com/Gimly/90df046dc38181bb18de
Gimly

5
많은 역사를 가진 큰 repos에 대한 경고 , 이것은 느리고 tedius 입니다. 나는 모든 오래된 지점과 마이그레이션 된 트렁크를 마이그레이션하려고 포기했습니다.
Jess

195

Subversion 리포지토리를 Git 리포지토리로 마이그레이션하십시오 . 먼저 Subversion 커밋 작성자 이름을 Git 커미터에 매핑하는 파일을 만들어야합니다 ~/authors.txt.

jmaddox = Jon Maddox <jon@gmail.com>
bigpappa = Brian Biggs <bigpappa@gmail.com>

그런 다음 Subversion 데이터를 Git 저장소로 다운로드 할 수 있습니다.

mkdir repo && cd repo
git svn init http://subversion/repo --no-metadata
git config svn.authorsfile ~/authors.txt
git svn fetch

Mac을 사용하는 git-svn경우을 설치하여 MacPorts에서 얻을 수 있습니다 git-core +svn.

서브 버전 리포지토리가 원하는 git 리포지토리와 동일한 시스템에있는 경우 초기화 단계에이 구문을 사용할 수 있습니다. 그렇지 않으면 모두 동일합니다.

git svn init file:///home/user/repoName --no-metadata

1
내가 다른 대답에 댓글을 때, 나는 주위의 공백을 제거했다 =에서 users.txt가져 오기가 중단 되었기 때문에 나는 빈 저장소를 얻고 있었다.
Sebastián Grignoli

8
아! 간단하고 효과적인 설명. 내 경우에는 file:///작동을 거부하고 대신 사용 svnserve.exe --daemon하고 사용 svn://localhost/home/user/repo했습니다.
Daniel Reis 2016 년

Mountain Lion을 실행하는 Mac에서 git svn은 Xcode로 이동하여 환경 설정 창의 다운로드 탭에있는 명령 줄 도구를 설치해야 작동합니다. 또는 Apple 개발자 사이트에서 찾은 OS X Mountain Lion 용 명령 줄 도구 만 설치할 수 있습니다.
Drew

3
필자의 경우 파일 authors.txt을 로 변환해야 했습니다 utf-8 without BOM.
Silvan

이것은 나를 위해 잘 작동했습니다! 내가 로컬 저장소를 한 후, 나는 시작 cmcginty의 게시물을 사용 "복제 깨끗한 Git 저장소에 당신의 GIT-SVN 저장소를 :"나는 주된 이유는 내가 @zoul의 대답이었다 좋아 생각은의 사용이다 git svn init, git svn config마지막으로 다음 git svn fetch은 쉬웠다로 이 방법을 사용하려면 올바르게 가져 오기 위해 여러 번 가져와야했습니다. git svn clone세 가지 모두를 수행하는 cmcginty의 single-line 은 너무 혼란 스러웠습니다.
mike

70

나는 svn2git 스크립트를 사용했고 매력처럼 작동합니다.


4
Q : 태그 및 분기 이름의 공백을 수정합니까 (svn에서 허용하고 git에서는 허용되지 않음)?
spazm 2016 년

2
이 안내서를 사용하면 도움이됩니다. troyhunt.com/2014/08/migrating-from-subversion-to-git-with.html
Morten Holmgaard

이것은 문제로 실패했습니다 : groups.google.com/forum/#!topic/msysgit/7MQVwRO-2N4- 참조 : github.com/nirvdrum/svn2git/issues/50 해결책은 여기에 있습니다 : stackoverflow.com/questions / 3009738 /…
HDave

그렇지 않으면 스크립트 키디를 생성하는 답변을 설명하는 것이 좋습니다.
Josh Habdas 2012 년

브랜치가 모두 SVN의 루트에 있고 트렁크 또는 태그가없는 경우는 어떻습니까?
Kal

58

git-svn을 지속적으로 사용하기 전에 Git에 익숙해지는 것이 좋습니다. 즉 SVN을 중앙 집중식 저장소로 유지하고 Git을 로컬로 사용하는 것이 좋습니다.

그러나 모든 기록이 포함 된 간단한 마이그레이션의 경우 몇 가지 간단한 단계는 다음과 같습니다.

로컬 저장소를 초기화하십시오.

mkdir project
cd project
git svn init http://svn.url

수정본 가져 오기를 시작하려는 시점을 표시하십시오.

git svn fetch -r42

(또는 모든 rev에 대해 "git svn fetch")

그 이후로 실제로 모든 것을 가져옵니다.

git svn rebase

Gitk로 가져 오기 결과를 확인할 수 있습니다. 이것이 Windows에서 작동하는지 확실하지 않으며 OSX 및 Linux에서 작동합니다.

gitk

SVN 리포지토리를 로컬로 복제 한 경우보다 쉬운 협업을 위해 중앙 집중식 Git 리포지토리로 푸시 할 수 있습니다.

먼저 빈 원격 저장소를 만드십시오 ( GitHub ?)

git remote add origin git@github.com:user/project-name.git

그런 다음 선택적으로 메인 브랜치를 동기화하여 풀 작업에 원격 마스터가 로컬 마스터와 자동으로 병합됩니다.

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

그 후, 당신은 내 자신을 시도하는 데 관심이있을 수 있습니다 git_remote_branch 원격 지점을 다루는 데 도움이되는 도구 .

첫 번째 설명 게시물 : " 깃 원격 지점 "

최신 버전에 대한 후속 조치 : " git_remote_branch와 공동 작업하는 시간 "


매우 도움이되었으며 완벽하게 작동했습니다. 원격 저장소에 동기화하는 경우 수행해야 할 마지막 단계가 하나 더 있다고 덧붙입니다. git config 단계 후에git push origin master
mag382

31

Subversion에서 Git으로의 원활한 마이그레이션 (또는 두 가지를 동시에 사용)을위한 새로운 솔루션이 있습니다 : SubGit .

이 프로젝트를 직접 진행하고 있습니다. 우리는 리포지토리에서 SubGit을 사용합니다. 일부 팀원은 Git과 Subversion을 사용하며 지금까지는 매우 잘 작동합니다.

SubGit을 사용하여 Subversion에서 Git으로 마이그레이션하려면 다음을 실행해야합니다.

$ subgit install svn_repos
...
TRANSLATION SUCCESSFUL 

그런 다음 svn_repos / .git에 Git 저장소를 가져 와서 복제하거나 계속해서 Subversion과이 새로운 Git 저장소를 함께 사용할 수 있습니다. SubGit은 항상 동기화 상태를 유지합니다.

Subversion 저장소에 여러 프로젝트가 포함 된 경우 svn_repos / git 디렉토리에 여러 Git 저장소가 작성됩니다. 번역을 실행하기 전에 사용자 정의하려면 다음을 수행하십시오.

$ subgit configure svn_repos
$ edit svn_repos/conf/subgit.conf (change mapping, add authors mapping, etc)
$ subgit install svn_repos

SubGit 을 git-svn이 아닌 순수 Git으로 마이그레이션하여 Subversion을 필요한 한 계속 유지하면서 사용을 시작할 수 있습니다 (예 : 이미 구성된 빌드 도구).

도움이 되었기를 바랍니다!


4
subgit import명령을 사용하여 한 번만 가져 오기 에는 라이센스가 필요하지 않은 것 같습니다. svn:ignore속성을 .gitignore파일로 정확하게 변환하는 것도 포함됩니다.
krlmlr

1
SubGit은 개인 키나 명령 줄에서 설정 한 플래그를 인식하지 못합니다. 문서가 매우 열악합니다. 이것은에 대한 대안이 아닙니다 git svn.
pfnuesel 2016 년

1
오류 : 'svn_repos'는 유효한 구성된 위치가 아닙니다. SubGit 구성 파일이 없습니다.
Jon Davis

19

공식 git-svn 맨 페이지를 참조하십시오 . 특히 "기본 예"를보십시오.

전체 Subversion 관리 프로젝트 추적 및 기여 (트렁크, 태그 및 브랜치로 완료) :

# Clone a repo (like git clone):
    git svn clone http://svn.foo.org/project -T trunk -b branches -t tags

귀하의 복제 명령이 작동했습니다. 위의 명령은 빈 git repos 만 제공했습니다. 유일한 차이점은 명시적인 '-T 트렁크'인 것 같습니다.
user1984717 1


14

SubGit (vs 죽음의 블루 스크린)

subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

그게 다야

+ 첫 번째 명령으로 생성 된 Git 저장소 인 SVN에서 업데이트합니다.

subgit import  directory/path/Local.git.Repo

거대한 저장소를 위해 즉시 Git으로 마이그레이션하는 방법을 사용했습니다.
물론 준비가 필요합니다.
그러나 개발 프로세스를 멈추지 않을 수도 있습니다.

여기 내 방법이 있습니다.

내 솔루션은 다음과 같습니다.

  • SVN을 Git 저장소로 마이그레이션
  • 팀이로 전환하기 직전에 Git 저장소를 업데이트하십시오 .

큰 SVN 저장소에는 마이그레이션에 많은 시간이 걸립니다.
그러나 완료된 마이그레이션을 단 몇 초만에 업데이트합니다.

물론 SubGit , mama를 사용하고 있습니다. git-svn은 나를 죽음의 블루 스크린으로 만듭니다 . 끊임없이. 그리고 git-svn은 Git의 " filename too long "치명적인 오류 로 지루 합니다.

단계

1. SubGit 다운로드

2. 이주 및 갱신 명령을 준비하십시오.

우리가 Windows를 위해 그것을한다고 가정 해 봅시다 (리눅스로 포팅하는 것은 쉽지 않습니다).
SubGit의 설치 빈에서 디렉토리 (subgit-2.XX \ bin)에서 두 개의 .bat 파일을 작성하십시오.

마이그레이션을위한 파일 / 명령 내용 :

start    subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

여기서 "시작"명령은 선택 사항입니다 (Windows). 시작시 오류를 볼 수 있으며 SubGit 완료 후 셸을 열어 두었습니다.

git-svn과 비슷한 추가 매개 변수를 여기에 추가 할 수 있습니다 . SVN 작성자의 전자 메일 주소 도메인을 수정하기 위해 --default-domain myCompanyDomain.com 만 사용 하고 있습니다.
표준 SVN 저장소의 구조 (트렁크 / 분기 / 태그)가 있고 "작성자 매핑"에 문제가 없었습니다. 그래서 나는 더 이상 아무것도하지 않습니다.

(분기와 같은 태그를 마이그레이션하거나 SVN에 여러 분기 / 태그 폴더가있는 경우보다 자세한 SubGit 접근 방식 을 사용하는 것이 좋습니다 )

팁 1 : --minimal-revision YourSvnRevNumber를 사용하여 상황이 어떻게 빨리 나오는지 확인하십시오 (일부 디버깅). 특히 유용한 저자 이름 또는 이메일을 보는 것이 유용합니다.
또는 마이그레이션 기록 깊이를 제한합니다.

팁 2 : 다음 업데이트 명령 / 파일을 실행하여 마이그레이션이 중단되고 ( Ctrl+ C) 복원 될 수 있습니다 .
큰 리포지토리에 대해서는이 작업을 수행하지 않는 것이 좋습니다. "메모리 부족 Java + Windows 예외"를 받았습니다.

팁 3 : 결과 베어 리포지토리의 복사본을 만드는 것이 좋습니다.

업데이트 할 파일 / 명령 내용 :

start    subgit import  directory/path/Local.git.Repo

마지막 팀의 Git 저장소 커밋을 얻으려는 경우 언제든지 실행할 수 있습니다.

경고! 베어 리포지토리 (예 : 분기 생성)를 만지지 마십시오.
다음 치명적인 오류가 발생합니다.

복구 할 수없는 오류 : 동기화되지 않았으며 동기화 할 수 없습니다 ... Subversion 개정판을 Git 커밋으로 변환하는 중 ...

3. 첫 번째 명령 / 파일을 실행하십시오. 큰 저장소를 만드는 데 시간이 오래 걸립니다. 겸손한 저장소에 30 시간.

그게 다야
두 번째 파일 / 명령을 실행하여 언제든지 SVN에서 Git 리포지토리를 업데이트 할 수 있습니다. 그리고 개발 팀을 Git으로 전환하기 전에.
몇 초 밖에 걸리지 않습니다.



유용한 작업이 하나 더 있습니다.

로컬 Git 저장소를 원격 Git 저장소로 푸시

당신의 경우입니까? 계속합시다.

  1. 리모컨 구성

운영:

$ git remote add origin url://your/repo.git
  1. 거대한 로컬 Git 저장소를 원격 저장소로 초기 전송 준비

기본적으로 Git은 큰 덩어리를 보낼 수 없습니다. 치명적인 : 원격 끝이 예기치 않게 끊어졌습니다.

실행 해 봅시다 :

git config --global http.postBuffer 1073741824

524288000-500MB 1073741824-1GB 등

로컬 인증서 문제를 해결하십시오 . git-server가 깨진 인증서를 사용하는 경우.

인증서를 비활성화했습니다 .

또한 Git 서버는 수정해야 할 요청 금액 제한이있을 수 있습니다 .

  1. 모든 마이그레이션 을 팀의 원격 Git 저장소로 푸시하십시오 .

로컬 Git으로 실행하십시오.

git push origin --mirror

( 이전 Git 버전의 경우 git push origin '* : *' )

다음과 같은 오류가 발생 하면 error : git spawn을 생성 할 수 없습니다 : 해당 파일이나 디렉토리가 없습니다 ... 저의 저장소를 완전히 활용하여이 오류 (30 시간)를 해결했습니다. 다음 명령을 시도해 볼 수 있습니다

git push origin --all
git push origin --tags

또는 Git다시 설치하십시오 ( 나에게 쓸모없는 ). 또는 모든 태그에서 브랜치를 만들고 푸시 할 수 있습니다. 아니면 ...


10

리포 지

복잡한 경우에는 Eric S. Raymond의 reposurgeon 이 선택 도구입니다. SVN 외에도 fast-export형식을 통해 다른 많은 버전 제어 시스템 과 CVS도 지원 합니다. 저자는 EmacsFreeBSD 와 같은 고대 저장소의 성공적인 변환을보고합니다 .

이 도구 는 오랜 역사를 가진 어려운 저장소 레이아웃에서도 SVN의 속성을 파일 로 변환하는 것과 같은 거의 완벽한 변환을 목표svn:ignore.gitignore합니다. 많은 경우 다른 도구를 사용하는 것이 더 쉬울 수 있습니다.

reposurgeon명령 행 문서 를 자세히 살펴보기 전에 단계별 변환 프로세스를 다루는 훌륭한 DVCS 마이그레이션 안내서 를 읽으십시오 .



8

설치해야합니다

git
git-svn

이 링크 http://john.albin.net/git/convert-subversion-to-git 에서 복사했습니다 .

1. 모든 Subversion 커미터 목록을 검색하십시오.

Subversion은 단순히 각 커밋의 사용자 이름을 나열합니다. Git의 커밋에는 훨씬 풍부한 데이터가 있지만 가장 간단하게 커밋 작성자는 이름과 전자 메일을 나열해야합니다. 기본적으로 git-svn 도구는 작성자 및 전자 메일 필드에 SVN 사용자 이름 만 나열합니다. 그러나 약간의 작업으로 모든 SVN 사용자 목록과 해당 Git 이름 및 이메일 목록을 만들 수 있습니다. 이 목록은 git-svn에서 일반 svn 사용자 이름을 적절한 Git 커미터로 변환하는 데 사용할 수 있습니다.

로컬 Subversion 체크 아웃 루트에서 다음 명령을 실행하십시오.

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt

모든 로그 메시지를 가져오고 사용자 이름을 뽑아 내고 중복 된 사용자 이름을 제거하며 사용자 이름을 정렬하여“authors-transform.txt”파일에 배치합니다. 이제 파일의 각 줄을 편집하십시오. 예를 들어 다음과 같이 변환하십시오.

jwilkins = jwilkins <jwilkins>

이것으로 :

jwilkins = John Albin Wilkins <johnalbin@example.com>

2. git-svn을 사용하여 Subversion 저장소를 복제하십시오

git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp

1 단계에서 만든 authors-transform.txt 파일을 사용하여 표준 git-svn 변환을 수행하고 git 저장소를 홈 디렉토리의“~ / temp”폴더에 배치합니다.

svn : ignore 속성을 .gitignore로 변환

svn repo가 ​​svn : ignore 속성을 사용하는 경우 다음을 사용하여 쉽게 .gitignore 파일로 변환 할 수 있습니다.

cd ~/temp
git svn show-ignore > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'

4. 저장소를 베어 git 저장소로 푸시

먼저 Bare 저장소를 작성하고 기본 분기가 svn의 "trunk"분기 이름과 일치하게하십시오.

git init --bare ~/new-bare.git
cd ~/new-bare.git
git symbolic-ref HEAD refs/heads/trunk

그런 다음 임시 저장소를 새 Bare 저장소로 푸시하십시오.

cd ~/temp
git remote add bare ~/new-bare.git
git config remote.bare.push 'refs/remotes/*:refs/heads/*'
git push bare

~ / temp 저장소를 안전하게 삭제할 수 있습니다.

5. "트렁크"지점의 이름을 "마스터"로 변경

주요 개발 지점의 이름은“트렁크”이며 Subversion의 이름과 일치합니다. 다음을 사용하여 이름을 Git의 표준 "마스터"지점으로 바꾸고 싶을 것입니다.

cd ~/new-bare.git
git branch -m trunk master

6. 가지와 태그 정리

git-svn은 모든 Subversions 태그를 Git에서“tags / name”형식으로 매우 짧은 분기로 만듭니다. 다음을 사용하여 모든 분기를 실제 Git 태그로 변환하려고합니다.

cd ~/new-bare.git
git for-each-ref --format='%(refname)' refs/heads/tags |
cut -d / -f 4 |
while read ref
do
  git tag "$ref" "refs/heads/tags/$ref";
  git branch -D "tags/$ref";
done

이 단계는 약간의 타이핑이 필요합니다. :-) 그러나 걱정하지 마십시오. 유닉스 쉘은 git for-each-ref로 시작하는 매우 긴 명령에 대해> 보조 프롬프트를 제공합니다.


7

GitHub는 이제 SVN 저장소에서 가져 오는 기능이 있습니다. 그래도 시도하지 않았습니다.


3
GitHub의 현재 권장 사항다른 답변svn2git 에서 제안 된 프로그램 을 사용하는 입니다.
ntc2

완벽하게 두 개의 큰 프로젝트를 가져 왔습니다. 모든 SVN 브랜치를 가져 왔습니다 (리포지토리 경로에 \ trunk 부분을 사용하지 마십시오). 내가 아직 모르는 한 가지는 Github이 새로운 커밋을 추적하는지 여부입니다.
Fr0sT

7

git, SVN 및 bash를 사용하는 다소 확장 된 답변. 여기에는 트렁크 / 분기 / 태그 디렉토리 레이아웃과 함께 기존 레이아웃을 사용하지 않는 SVN 리포지토리에 대한 단계가 포함됩니다 (SVN은 이러한 종류의 레이아웃을 강제로 수행하지 않습니다).

먼저이 bash 스크립트를 사용하여 기여한 다른 사람들에 대해 SVN 저장소를 스캔하고 맵핑 파일의 템플리트를 생성하십시오.

#!/usr/bin/env bash
authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
for author in ${authors}; do
  echo "${author} = NAME <USER@DOMAIN>";
done

만들려면이 옵션을 사용 authors하면 사용하여 개발자가 세트로 사용자 이름과 이메일 SVN 사용자 이름 매핑 파일 git config속성 user.nameuser.email (GitHub의 같은 서비스는 일치하는 이메일을 가지고위한 것이 좋다고 참고).

그런 다음 git svnsvn 저장소를 git 저장소로 복제하여 매핑에 대해 알려주십시오.

git svn clone --authors-file=authors --stdlayout svn://example.org/Folder/projectroot

git svn은 존재하는 모든 태그 또는 분기에 대한 모든 개정판을 개별적으로 체크 아웃하므로 매우 오래 걸릴 수 있습니다. (SVN의 태그는 실제로 브랜치이므로 Git에서와 같이 끝납니다). 필요하지 않은 SVN에서 오래된 태그와 분기를 제거하여 속도를 높일 수 있습니다.

동일한 네트워크 또는 동일한 서버의 서버에서 이것을 실행하면 실제로 속도를 높일 수 있습니다. 또한 어떤 이유로이 프로세스가 중단되면 다음을 사용하여 다시 시작할 수 있습니다

git svn rebase --continue

많은 경우에 당신은 여기에서 끝납니다. 그러나 SVN 저장소에 SVN에 디렉토리가있는 비 전통적인 레이아웃이있는 경우 git 브랜치를 넣으려는 경우 몇 가지 추가 단계를 수행 할 수 있습니다.

가장 간단한 방법은 서버에 새로운 SVN 저장소를 작성하여 규칙을 따르고 svn copy디렉토리를 트렁크 또는 분기에 두는 것입니다. 마지막으로 시도했을 때 디렉토리가 저장소의 루트에있는 경우 이것이 유일한 방법 일 수 있습니다.git svn 단순히 체크 아웃을 거부했습니다.

git을 사용 하여이 작업을 수행 할 수도 있습니다. 에 대한git svn clone 단순히 디렉토리를 사용하면 자식 지점에 넣어 싶습니다.

실행 후

git branch --set-upstream master git-svn
git svn rebase

이를 위해서는 Git 1.7 이상이 필요합니다.


이 정보를 다음 링크와 결합 할 것을 제안합니다 : sailmaker.co.uk/blog/2013/05/05/…
Joan PS

7

단계별 가이드를 게시했습니다 ( heresvn 태그를 git 태그로 변환하고 svn 분기를 git 분기로 변환하는 것을 포함하여 svn을 git로 변환 )를 .

짧은 버전 :

1) 특정 개정 번호에서 svn을 복제하십시오. (개정 번호는 이전하려는 가장 오래된 것이어야 함)

git svn clone --username=yourSvnUsername -T trunk_subdir -t tags_subdir -b branches_subdir -r aRevisionNumber svn_url gitreponame

2) svn 데이터를 가져옵니다. 이 단계는 가장 시간이 걸리는 단계입니다.

cd gitreponame
git svn fetch

오류없이 끝날 때까지 자식 svn 가져 오기를 반복하십시오.

3) 마스터 브랜치 업데이트

git svn rebase

4) 참조를 복사하여 svn 분기에서 로컬 분기 작성

cp .git/refs/remotes/origin/* .git/refs/heads/

5) svn 태그를 git 태그로 변환

git for-each-ref refs/remotes/origin/tags | sed 's#^.*\([[:xdigit:]]\{40\}\).*refs/remotes/origin/tags/\(.*\)$#\2 \1#g' | while read p; do git tag -m "tag from svn" $p; done

6) 저장소를 github와 같은 더 나은 곳에 두십시오.

git remotes add newrepo git@github.com:aUser/aProjectName.git
git push newrepo refs/heads/*
git push --tags newrepo

더 자세한 정보가 필요하면 내 게시물을 읽 거나 문의하십시오.


6

git svn clone아래와 같이 명령을 사용할 수 있습니다 .

  • svn log -q <SVN_URL> | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors.txt

위의 명령은 SVN 커밋에서 authors 파일을 만듭니다.

  • svn log --stop-on-copy <SVN_URL>

위의 명령은 SVN 프로젝트가 생성 될 때 첫 번째 개정 번호를 제공합니다.

  • git svn clone -r<SVN_REV_NO>:HEAD --no-minimize-url --stdlayout --no-metadata --authors-file authors.txt <SVN_URL>

위 명령은 로컬에 Git 저장소를 만듭니다.

문제는 브랜치와 태그를 푸시로 변환하지 않는다는 것입니다. 수동으로 수행해야합니다. 예를 들어 지점의 경우 다음과 같습니다.

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
* master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$$ git checkout -b MyDevBranch origin/MyDevBranch
Branch MyDevBranch set up to track remote branch MyDevBranch from origin.
Switched to a new branch 'MyDevBranch'
$ git branch -a
* MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$

태그의 경우 :

$git checkout origin/tags/MyDevBranch-1.0
Note: checking out 'origin/tags/MyDevBranch-1.0'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 3041d81... Creating a tag
$ git branch -a
* (detached from origin/tags/MyDevBranch-1.0)
  MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$ git tag -a MyDevBranch-1.0 -m "creating tag"
$git tag
MyDevBranch-1.0
$

이제 마스터, 브랜치 및 태그를 원격 git 저장소로 푸시하십시오.

$ git push origin master MyDevBranch MyDevBranch-1.0
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (14/14), 2.28 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To https://github.com/pankaj0323/JDProjects.git
 * [new branch]      master -> master
 * [new branch]      MyDevBranch -> MyDevBranch
 * [new tag]         MyDevBranch-1.0 -> MyDevBranch-1.0
$

svn2git 유틸리티

svn2git 유틸리티는 브랜치 및 태그를 사용하여 수동 작업을 제거합니다.

command를 사용하여 설치하십시오 sudo gem install svn2git. 그 후 아래 명령을 실행하십시오.

  • $ svn2git <SVN_URL> --authors authors.txt --revision <SVN_REV_NO>

이제 브랜치, 태그를 나열하고 쉽게 푸시 할 수 있습니다.

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
  MyDevBranch
* master
  remotes/svn/MyDevBranch
  remotes/svn/trunk
$ git tag
  MyDevBranch-1.0
$ git push origin master MyDevBranch MyDevBranch-1.0

20 개의 가지와 태그가 있다고 상상해보십시오 .svn2git은 많은 시간을 절약 할 수 있으므로 기본 명령보다 더 좋습니다. 기본 git svn clone명령을 둘러싼 멋진 래퍼 입니다.

완전한 예를 보려면 내 블로그 항목을 참조하십시오 .




3

SourceTree를 사용하는 경우 앱에서 직접 수행 할 수 있습니다. File-> New / Clone으로 이동하여 다음을 수행하십시오.

  1. "원본 경로 / URL"로 원격 SVN URL을 입력하십시오.
  2. 메시지가 표시되면 자격 증명을 입력하십시오.
  3. "대상 경로"로 로컬 폴더 위치를 입력하십시오.
  4. 이름을 알려주세요.
  5. 고급 옵션에서 "유형의 로컬 저장소 작성"드롭 다운에서 "Git"을 선택하십시오.
  6. 선택적으로 복제 할 개정을 지정할 수 있습니다.
  7. 클론을 누르십시오.

SourceTree에서 저장소를 열면 커밋 메시지가 마이그레이션되었음을 알 수 있습니다.

이제 저장소-> 저장소 설정으로 이동하여 새 원격 저장소 세부 사항을 추가하십시오. 원하는 경우 SVN 리모컨을 삭제하십시오 ( "구성 파일 편집"옵션을 통해이 작업을 수행했습니다).

준비가 되었으면 자유롭게 코드를 작성하여 새 원격 저장소로 코드를 푸시하십시오.


쉽고 빠른 감사합니다!
Rikard

감사합니다. 이것은 나를 위해 일했습니다 .SourceTree와 Stash를 사용하고 있습니다.
VK_217

3

GitLab 사용자 를 위해 SVN에서 마이그레이션하는 방법에 대해 간략히 설명했습니다.

https://gist.github.com/leftclickben/322b7a3042cbe97ed2af

SVN에서 GitLab으로 마이그레이션하는 단계

설정

  • SVN은에서 호스팅됩니다 svn.domain.com.au.
  • SVN을 통해 액세스 할 수 있습니다 http(다른 프로토콜이 작동해야 함).
  • GitLab는 다음에서 호스팅됩니다 git.domain.com.au:
    • 네임 스페이스를 사용하여 그룹이 생성됩니다 dev-team.
    • 하나 이상의 사용자 계정이 생성되어 그룹에 추가되며 마이그레이션에 사용되는 계정에 대한 SSH 키가 있습니다 (테스트 사용 ssh git@git.domain.com.au).
    • 프로젝트 favourite-projectdev-team네임 스페이스 에서 생성됩니다 .
  • 이 파일 users.txt형식의 관련 사용자 세부, 한 줄에 하나의 사용자 포함 username = First Last <address@domain.com.au>, usernameSVN 로그에 주어진 이름이다. (특히 Casey 사용자의 답변에 대한 자세한 내용은 참조 섹션의 첫 번째 링크를 참조하십시오).

버전

  • Subversion 버전 1.6.17 (r1128011)
  • 자식 버전 1.9.1
  • GitLab 버전 7.2.1 ff1633f
  • 우분투 서버 14.04

명령

bash
git svn clone --stdlayout --no-metadata -A users.txt 
http://svn.domain.com.au/svn/repository/favourite-project
cd favourite-project
git remote add gitlab git@git.domain.com.au:dev-team/favourite-project.git
git push --set-upstream gitlab master

그게 다야! GitLab 웹 UI에서 프로젝트 페이지를 다시로드하면 커밋과 파일이 모두 나열됩니다.

노트

  • 알 수없는 사용자가있는 경우, git svn clone명령은 중지하는 경우, 갱신에있는 것 users.txt, cd favourite-project그리고 git svn fetch그것을 중지 된 위치에서 계속됩니다.
  • 표준 trunk- tags- branchesSVN 저장소에 대한 레이아웃이 필요합니다.
  • 받는 사람 주어진 SVN URL git svn clone명령은 바로 위의 수준에서 중지 trunk/, tags/그리고 branches/.
  • git svn clone명령은 상단에 경고를 포함하여 많은 출력을 생성합니다. 경고를 무시했습니다.

이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다.
Blackhole

1
동의하지 않습니다. 링크 된 내용이 변경 될 수 있으며 여기에 복제 된 내용은 업데이트되지 않으므로 오래되었을 수 있습니다 (실제로이 답변을 게시 한 이후로 변경되었다고 생각합니다). 가이드 라인은 링크에 대한 관련 컨텍스트를 포함한다고 말하고 있습니다. 실제 질문은 링크로 도매로 대답했습니다. 여기에 전체 링크 된 리소스를 복사 할 필요가 없습니다. 내가 이것으로 공감 했습니까?!
leftclickben

2

다른 한편으로, git-stash 명령은 git-svn dcommits로 git을 시도 할 때 신의 선물입니다.

전형적인 과정 :

  1. 자식 리포지토리 설정
  2. 다른 파일에 대한 작업을 수행
  3. git을 사용하여 일부 작업을 확인하기로 결정했습니다.
  4. ~를 결정하다 svn-dcommit
  5. "더러운 색인으로 커밋 할 수 없습니다"오류가 발생합니다.

해결책 (git 1.5.3 이상 필요) :

git stash; git svn dcommit ; git stash apply

2

다음은 하나 이상의 SVN 저장소를 git으로 변환하고 GitHub로 푸시하는 종속성이없는 간단한 쉘 스크립트입니다.

https://gist.github.com/NathanSweet/7327535

약 30 줄의 스크립트에서 : git SVN을 사용하여 복제하고 SVN :: ignore 속성에서 .gitignore 파일을 생성하고 베어 git 저장소로 푸시하고 SVN 트렁크의 이름을 마스터로 바꾼 다음 SVN 태그를 git 태그로 변환하여 GitHub에 푸시합니다 태그를 유지하면서.

12 개의 SVN 저장소를 Google 코드에서 GitHub로 옮기기 위해 많은 고통을 겪었습니다. Windows를 사용하는 데 도움이되지 않았습니다. 루비는 오래된 데비안 박스에서 모든 종류의 문제가 발생했으며 Windows에서 작동시키는 것은 농담이었습니다. 다른 솔루션은 Cygwin 경로와 작동하지 못했습니다. 일단 무언가가 작동하더라도 GitHub에 태그를 표시하는 방법을 알 수 없었습니다 (비밀은 --follow-tags).

결국 나는 위에 링크 된 두 개의 짧고 간단한 스크립트를 함께 모았으며 훌륭하게 작동했습니다. 솔루션은 그보다 더 복잡 할 필요는 없습니다!


2
이 스크립트를 사용했습니다. 약간의 흔적과 오류 후, 그것은 나를 위해 일했습니다. --follow-tags는 그 이후에만 지원 되므로 Git 1.8.3 이상 이 필요합니다 .
nrobey

2

나는 Windows 컴퓨터에 있고 작은 배치를 만들어 역사 만 (하지만 분기가없는) SVN 저장소를 GIT 저장소로 옮길 수 있습니다.

transfer.bat http://svn.my.address/svn/myrepo/trunk https://git.my.address/orga/myrepo

아마도 누구나 사용할 수 있습니다. TMP 폴더를 생성하여 git을 사용하여 SVN 저장소를 확인하고 새 원점을 추가하고 밀어 넣습니다 ... 폴더를 다시 삭제합니다.

@echo off 
SET FROM=%1 
SET TO=%2 
SET TMP=tmp_%random%

echo from:  %FROM% 
echo to:    %TO% 
echo tmp:   %TMP%

pause

git svn clone  --no-metadata --authors-file=users.txt %FROM% %TMP%  
cd %TMP% 
git remote add origin %TO% 
git push --set-upstream origin master


cd .. 
echo delete %TMP% ... 
pause

rmdir /s /q %TMP%

여전히 사용자 매핑과 함께 users.txt가 필요합니다.

User1 = User One <u.1@xxx.com>

이 답변을 통해 모든 리포지토리를 문제없이 BitBucket으로 옮길 수있었습니다.
Gonzalingui 12

다행. 나는 Gitea에 대한 경험 만 가지고 있었지만 ~ ~ 40의 repos를이 방법으로 전달했습니다.
cljk

아주 좋아요! Thnx
b3wii

경고; 잘못된 문자셋 문제가 발생했습니다. 나는 이것을 너무 늦게 인식했지만 수정하는 데 몇 시간이 걸렸습니다. (!) 당신의 결과의 repo 정확한 예상 소스가 들어 있는지 확인하십시오
cljk

1

방금 Git 커뮤니티에 내 공헌을 추가하고 싶었습니다. 전체 가져 오기를 자동화하는 간단한 bash 스크립트를 작성했습니다. 다른 마이그레이션 도구와 달리이 도구는 jGit 대신 기본 자식에 의존합니다. 이 도구는 또한 수정 내역이 많거나 얼룩이있는 리포지토리도 지원합니다. github을 통해 사용할 수 있습니다 :

https://github.com/onepremise/SGMS

이 스크립트는 SVN에 저장된 프로젝트를 다음 형식으로 변환합니다.

/trunk
  /Project1
  /Project2
/branches
     /Project1
     /Project2
/tags
 /Project1
 /Project2

이 체계는 또한 인기 있고 지원됩니다 :

/Project1
     /trunk
     /branches
     /tags
/Project2
     /trunk
     /branches
     /tags

각 프로젝트는 프로젝트 이름으로 동기화됩니다.

Ex: ./migration https://svnurl.com/basepath project1

전체 저장소를 변환하려면 다음 구문을 사용하십시오.

Ex: ./migration https://svnurl.com/basepath .

0

Subversion과 함께 Git을 효과적으로 사용 하는 것은 git-svn에 대한 소개입니다. 기존 SVN 저장소의 경우 git-svn은 이것을 매우 쉽게 만듭니다. 새 저장소를 시작하는 경우 빈 SVN 저장소를 만든 다음 반대 방향으로 진행하는 것보다 git-svn을 사용하여 가져 오는 것이 훨씬 쉽습니다. 새로운 Git 리포지토리를 생성 한 후 SVN으로 가져 오기를 수행 할 수 있지만 Git을 처음 사용하고 커밋 히스토리를 보존하려는 경우 특히 고통 스럽습니다.


0

Windows 용 Ruby 설치 프로그램을 다운로드하여 최신 버전을 설치하십시오. 경로에 Ruby 실행 파일을 추가하십시오.

  • svn2git 설치
  • 시작 메뉴-> 모든 프로그램-> Ruby-> Ruby로 명령 프롬프트 시작
  • 그런 다음“gem install svn2git”을 입력하고 입력하십시오

    Subversion 저장소 마이그레이션

  • Ruby 명령 프롬프트를 열고 파일을 마이그레이션 할 디렉토리로 이동하십시오.

    그런 다음 svn2git http : // [도메인 이름] / svn / [저장소 루트]

  • 프로젝트 코드 크기에 따라 프로젝트를 Git으로 마이그레이션하는 데 몇 시간이 걸릴 수 있습니다.

  • 이 주요 단계는 아래와 같이 Git 리포지토리 구조를 만드는 데 도움이됩니다.

    SVN (/ Project_components) 트렁크-> Git 마스터 SVN (/ Project_components) 분기-> Git 분기 SVN (/ Project_components) 태그-> Git 태그

원격 저장소를 작성하고 변경 사항을 푸시하십시오.


0

GitHub에는 수입 업체가 있습니다. 리포지토리를 만든 후에는 URL을 통해 기존 리포지토리에서 가져올 수 있습니다. 해당되는 경우 자격 증명을 요청하고 거기에서 이동합니다.

실행되면 작성자를 찾을 수 있으며 GitHub의 사용자에게 간단히 매핑 할 수 있습니다.

나는 지금 몇 개의 저장소에 사용했으며, 꽤 정확하고 훨씬 빠릅니다! ~ 4000 커밋이있는 리포지토리의 경우 10 분이 걸렸으며 친구가 4 일이 지난 후!


0

여기에 몇 가지 답변은 https://github.com/nirvdrum/svn2git참조 하지만 큰 저장소의 경우 속도가 느릴 수 있습니다. https://github.com/svn-all-fast-export/svn2git을 사용해 보았습니다. 정확히 같은 이름을 가진 도구 인 대신하지만 SVN에서 힘내에 KDE를 마이그레이션하는 데 사용되었다.

설정하는 데 약간 더 많은 작업이 있었지만 전환이 완료되면 다른 스크립트가 몇 시간을 소비하는 데 몇 분이 걸렸습니다.


0

이 목표를 달성하기위한 여러 가지 방법이 있습니다. 나는 그중 일부를 시도하고 Windows OS에 git과 svn이 설치된 것으로 실제로 작동하는 것을 발견했습니다.

전제 조건 :

  1. 창에 자식 (이것을 사용했습니다) https://git-scm.com/
  2. 콘솔 도구가 설치된 svn (거북 svn을 사용했습니다)
  3. SVN 저장소의 덤프 파일. svnadmin dump /path/to/repository > repo_name.svn_dump

최종 목표 달성 단계 (히스토리가있는 모든 리포지토리를 git, 먼저 로컬 git, 원격으로 이동)

  1. REPO_NAME_FOLDER 디렉토리에 빈 저장소 (콘솔 도구 또는 tortoiseSVN 사용)를 작성 cd REPO_NAME_PARENT_FOLDER하고 dumpfile.dump를 REPO_NAME_PARENT_FOLDER에 넣으십시오.

  2. svnadmin load REPO_NAME_FOLDER < dumpfile.dump 이 작업을 기다립니다. 시간이 오래 걸릴 수 있습니다

  3. 이 명령은 자동이므로 두 번째 cmd 창을 엽니 다. svnserve -d -R --root REPO_NAME_FOLDER 왜 file : /// ......을 사용하지 않습니까? Unable to open ... to URL:답변 https://stackoverflow.com/a/6300968/4953065 덕분에 다음 명령이 실패합니다.

  4. 새 폴더 SOURCE_GIT_FOLDER 만들기

  5. cd SOURCE_GIT_FOLDER
  6. git svn clone svn : // localhost /이 작업을 기다립니다.

마지막으로, 우리는 무엇을 얻습니까?

로컬 리포지토리를 확인하십시오.

git log

이전 커밋을 보시겠습니까? 그렇다면-괜찮습니다

이제 소스와 오래된 svn 기록이있는 완전한 기능을 갖춘 로컬 자식 저장소가 있습니다. 이제 서버를 다른 서버로 옮기려면 다음 명령을 사용하십시오.

git remote add origin https://fullurlpathtoyourrepo/reponame.git
git push -u origin --all # pushes up the repo and its refs for the first time
git push -u origin --tags # pushes up any tags

내 경우에는 태그가 필요하지 않은 태그 명령이 필요합니다.

행운을 빕니다!


0

svn 하위 모듈 / 폴더 'MyModule'을 태그 나 분기가없는 기록이있는 자식으로 변환

svn ignore list를 유지하려면 1 단계 후 위의 주석을 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.