git-svn :`svn switch --relocate`와 동등한 것은 무엇입니까?


88

git-svn을 통해 미러링하는 svn 저장소가 URL을 변경했습니다.

바닐라 svn에서는 그냥 할 것 svn switch --relocate old_url_base new_url_base입니다.

git-svn을 사용하여 어떻게 할 수 있습니까?

구성 파일에서 svn url을 변경하는 것만으로는 실패합니다.


당신이 시도하고 가능성이 답변을 받아 들여야한다 : stackoverflow.com/a/4061493/1221661
프리츠

최신 답변 : stackoverflow.com/a/40523789/537554 . 같은 질문이지만 Git 사용자의 관점에서 물었습니다.
ryenus

답변:


61

이것은 내 상황을 아주 잘 처리합니다.

https://git.wiki.kernel.org/index.php/GitSvnSwitch

file://프로토콜을 사용하여 복제했고 프로토콜로 전환하고 싶었습니다 http://.

url[svn-remote "svn"]섹션 에서 설정 을 편집하고 .git/config싶지만 그 자체로는 작동하지 않습니다. 일반적으로 다음 절차를 따라야합니다.

  1. svn-remote url설정을 새 이름으로 전환하십시오 .
  2. 을 실행 git svn fetch합니다. 이것은 svn에서 적어도 하나의 새 개정판을 가져와야합니다!
  3. svn-remote url설정을 원래 URL로 다시 변경하십시오 .
  4. 실행 git svn rebase -l하여 로컬 리베이스를 수행합니다 (마지막 가져 오기 작업에서 발생한 변경 사항 포함).
  5. svn-remote url설정을 다시 새 URL로 변경하십시오 .
  6. 이제 git svn rebase다시 작동해야합니다.

모험심이 강한 영혼은 시도해 볼 수 --rewrite-root있습니다.


2
공정하기 위해 이것은 실제로 실패했으며 결국 저장소를 다시 복제했습니다. svn 디렉토리의 이름이 변경되면 git이 처리하도록하기가 어렵습니다.
Gregg Lind

나는 더 자세한 글을 받아들이고 싶지만 충분히 공평하게, 새로운 답변이 나올 때까지 받아 들일 것입니다.
kch

2
다음은 해당 절차에 대한 또 다른 설명입니다. theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray

허용 된 답변에 제공된 링크는 구식이며 현재 새 링크는 다음과 같습니다. git.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.html "일반 사례"를 따랐고 간단하고 실제로 잘 작동했습니다.
TcMaster 2011

2
@TcMaster :뿐만 아니라 나를 위해 일한 ...하지만의 왜 대답이 포함되지해야한다고 링크 , 구식이되어 쓸모 없게됩니다 ... 커뮤니티 위키 답변을 추가하겠습니다.
UncleZeiv 2011

37

다음이 정상적으로 작동하는지 확인할 수 있습니다.

  1. svn-remote.svn.rewriteRoot구성 파일 ( .git/config) 에이없는 경우 :

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. svn-remote.svn.rewriteUUID구성 파일에없는 경우 :

    git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
    

    currentRepositoryUUID로부터 얻을 수있다 .git/svn/.metadata.

  3. git config svn-remote.svn.url <newRepositoryURL>


환상적입니다. 감사합니다. 이것은 나를 위해 잘 작동했습니다 (를 통해 복제 file://,로 전환 svn+ssh). 주의 할 점 :이 절차는 "svn에서 적어도 하나의 새 개정판을 가져올"필요가 없습니다. 또한 ./.git/svn/.metadataafter first svn rebase<newRepository>as를 포함 reposRoot하지만 이것은 rewrite*키 를 제거하기에 충분하지 않습니다 .git/config. 따라서 해당 키는 내가 이해하는 한 영구적으로 보관되어야합니다.
sdaau

1
그것은 매력처럼 나에게도 효과가 있었다. OP는 이것을 시도하고 정답으로 가져와야합니다.
Rafareino 2015

완전한. 나는 역사상 수천 개의 커밋을 가진 큰 프로젝트를 가지고 있었기 때문에 새로운 클론이 역사를 파괴했을 것입니다 (또는 체크 아웃하는 데 정말 오랜 시간이 걸립니다). 나는 사용 svn+ssh://하고 있으며 svn-server가 내부 이름을 삭제 .se하기 .com위해 도메인을에서 로 변경했습니다 .
UlfR

나를 위해 대접을 받았습니다. 1,000 개의 커밋이있는 2 년 된 리포지토리가 있으면 리포지토리가 새 호스트로 이동되었으므로 (두려운) 전체 svn 클론을 피할 수있었습니다.
David Victor

21

불행히도이 답변의 대부분의 링크가 작동하지 않으므로 향후 참조를 위해 git wiki 에서 약간의 정보를 복제 할 것입니다.

이 솔루션은 저에게 효과적이었습니다.

  • 새 도메인 / URL / 경로를 가리 키도록 svn-remote url(또는 fetch경로)를 편집합니다..git/config

  • 실행 git git svn fetch. 이것은 svn에서 적어도 하나의 새 개정판을 가져와야합니다!

  • git svn rebase지금 시도하면 다음 과 같은 오류 메시지가 표시됩니다.

    Unable to determine upstream SVN information from working tree history
    

    git svn가져 오기 전에 최신 커밋이에서 git-svn-id찾은 경로와 일치하지 않는 이전 경로를 가리키는 사실 로 인해 혼란 스럽기 때문이라고 생각합니다 .git/config.

  • 해결 방법으로 원래 도메인 / URL / 경로로 다시 변경 svn-remote url(또는 fetch경로)

  • 이제 git svn rebase -l다시 실행 하여 마지막 가져 오기 작업에서 발생한 변경 사항으로 로컬 리베이스를 수행합니다. 이번에는 분명히 있기 때문에, 작업 git svn사실에 의해 혼동되지 않습니다 git-svn-id새로운 머리가있는 것을 발견과 일치하지 않습니다 .git/config.

  • 마지막으로 svn-remote url(또는 fetch경로)를 새 도메인 / URL / 경로로 다시 변경하십시오.

  • 이 시점에서 git svn rebase다시 작동합니다!

원래 정보는 여기 에서 찾았 습니다 .


3

Git svn은 svn URL에 크게 의존합니다. svn에서 가져온 모든 커밋에는git-svn-id 에는 svn URL을 포함하는가 있습니다.

유효한 재배치 전략은 다음을 호출하는 것입니다. git-svn clone 새 저장소 하고 변경 사항을 새 닫기에 병합하는 것입니다. 자세한 절차는 다음 문서를 참조하십시오.

http://www.sanityinc.com/articles/relocating-git-svn-repositories


2

git filter-branch

블로그 항목 에서 가져온 이 스크립트 는 저에게 효과적이었습니다. 다음과 같이 이전 및 새 저장소 URL을 매개 변수로 제공하십시오.svn switch --relocate .

스크립트 는 커밋 메시지에서 git filter-branchSubversion URL을 교체하기 위해 호출 하고 업데이트 하며을 사용하여 메타 데이터를 다시 생성하여 업데이트합니다 . 더 강력한 솔루션 일 수 있지만 이 접근 방식은 대규모 리포지토리의 경우 훨씬 더 빠르게 작동합니다 (시간 대 며칠).git-svn-id.git/configgit-svngit svn rebasegit svn clonefilter-branch

#!/bin/sh

# Must be called with two command-line args.
# Example: git-svn-relocate.sh http://old.server https://new.server
if [ $# -ne 2 ]
then
  echo "Please invoke this script with two command-line arguments (old and new SVN URLs)."
  exit $E_NO_ARGS
fi

# Prepare URLs for regex search and replace.
oldUrl=`echo $1 | awk '{gsub("[\\\.]", "\\\\\\\&");print}'`
newUrl=`echo $2 | awk '{gsub("[\\\&]", "\\\\\\\&");print}'`

filter="sed \"s|^git-svn-id: $oldUrl|git-svn-id: $newUrl|g\""
git filter-branch --msg-filter "$filter" -- --all

sed -i.backup -e "s|$oldUrl|$newUrl|g" .git/config

rm -rf .git/svn
git svn rebase

1

git_fast_filter

그러나 더 빠르지 만 git-filter-branch(즉, 몇 시간이 아닌 몇 분) 정신적으로 비슷하게 git_fast_filter. 그러나 이것은 약간 더 많은 코딩이 필요하며 깔끔한 준비된 솔루션이 없습니다. 과는 대조적으로 이전 저장소에서 저장소를 git-filter-branch만듭니다 . 마지막 SVN 커밋 을 가리키는 것으로 가정합니다 .master

  1. 복제 git_fast_filterGitorious 저장소에서 합니다.
  2. 이 Gist를git_fast_filter 기반으로 복제 한 동일한 디렉토리에 Python 스크립트를 만들고 다음을 사용하여 실행 가능한 비트를 설정합니다.chmod +x . 이전 및 새 저장소 경로를 조정합니다. (대본의 내용도 아래에 붙여 넣습니다.)
  3. 다음을 사용하여 새 대상 저장소 초기화 git init 작업 디렉토리를이 새 저장소로 변경하십시오.
  4. 다음 파이프를 실행하십시오.

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. 복사 .git/config및 기타 관련 파일을.git/info이전 저장소에서 새 저장소로 하십시오.

  6. 제거 .git/svn.
  7. 확인 git-svn새로운 버전 번호 매핑 인식

    1. 실행 git branch refs/remotes/git-svn master

      • git-svn 리모컨은 refs/remotes/git-svn, consult .git/config, svn-remote섹션 과 다르게 호출 될 수 있습니다.
    2. 을 실행합니다 git svn info. 이 명령이 중지되면 문제가있는 것입니다. 개정 번호 매핑을 다시 작성해야합니다.

    3. 가짜 분기를 제거하면 다음에 refs/remotes/git-svn의해 다시 생성됩니다.git-svn

  8. 를 호출하여 동기화하십시오 git svn rebase.

다음은의 내용입니다 commit_filter.py. IN_REPO및 의 값을 OUT_REPO적절하게 바꿉니다.

#!/usr/bin/python

from git_fast_filter import Commit, FastExportFilter
import re
import sys

IN_REPO = "https://svn.code.sf.net/p/matsim/code"
OUT_REPO = "https://svn.code.sf.net/p/matsim/source"

IN_REPO_RE = re.compile("^git-svn-id: %s" % re.escape(IN_REPO), re.M)
OUT_REPO_RE = "git-svn-id: %s" % OUT_REPO

def my_commit_callback(commit):
  commit.message = IN_REPO_RE.sub(OUT_REPO_RE, commit.message)
  sys.stderr.write(".")

filter = FastExportFilter(commit_callback = my_commit_callback)
filter.run()

0

위의 git svn rebase -l솔루션은 저에게 효과적이지 않았습니다. 나는 그것에 대해 다른 방식으로 가기로 결정했습니다.

  1. 이전 SVN repo를 git repo에 복제 old하고 새 SVN을 git repo에 복제new
  2. 가져 오기 oldnew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. new위에 Rebase old(의 뿌리 new와 끝의 나무가 성공해야old 가 동일 함)
    • git checkout master( master분기가 SVN 헤드를 가리키고 있다고 가정합니다 . 이것은 깨끗한 클론의 경우입니다. 그렇지 않으면 시작하기 전에 dcommit합니다.)
    • git rebase --root --onto old
  4. git-svn 메타 데이터를 다시 빌드합니다. newrebase를 고려
    • git update-ref --no-deref refs/remotes/git-svn master(복제 방법에 따라 원격 참조를 조정하십시오. 예를 들어 refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info

1. 새 위치의 새 복제본으로 시작합니까? 그렇다면 왜 그 시점에서 완료되지 않았습니까? 2. new를 old에서 rebase하는 경우 이전 커밋이 모두 svn-id commit 로그 항목에 이전 URL을 언급합니까? 3. .git / svn을 제거하기 위해 저장 한 문서가 있습니까? (3B : 명령하면 자식 - svn의 메타 데이터를 재 구축, 자식 svn의 정보?)
미샤 Wiedenmann

0

이 질문에 대한 다른 응답을 바탕으로 git-svn 재배치를 처리하는 Ruby 스크립트를 작성했습니다. https://gist.github.com/henderea/6e779b66be3580c9a584 에서 찾을 수 있습니다. .

다른 복사본을 확인하지 않고 재배치를 처리하며, 하나 이상의 분기에 푸시되지 않은 변경 사항이있는 경우 (일반 논리를 위반하기 때문에)도 처리합니다. git filter-branch 답변 (주 논리 용)과 저장소의 한 인스턴스에서 다른 인스턴스로 분기를 복사하는 것에 대한 답변 (푸시되지 않은 변경 사항이있는 분기 복사 용)의 내용을 사용합니다.

나는 이것을 사용하여 작업을 위해 가지고있는 git-svn 저장소를 재배치 했으며이 버전의 스크립트 (수없이 반복되었습니다)가 나를 위해 작동하는 것 같습니다. 초고속은 아니지만 내가 만난 모든 경우를 처리하고 완전히 재배치 된 저장소를 생성하는 것 같습니다.

스크립트는 변경하기 전에 리포지토리의 복사본을 생성하는 옵션을 제공하므로이 옵션을 사용하여 백업을 생성 할 수 있습니다. 분기에 푸시되지 않은 변경 사항이있는 경우 사본을 작성해야합니다.

이 스크립트는 일반적인 MRI Ruby 설치에 포함되지 않은 gem이나 기타 라이브러리를 사용하지 않습니다. MRI에 포함 된 readline 및 fileutils 라이브러리를 사용합니다.

내 스크립트가 다른 사람에게 유용하다는 것이 증명되기를 바랍니다. 스크립트를 자유롭게 변경하십시오.

참고 : 이 스크립트는 OS X 10.10 Yosemite에서 git 2.3.0 / 2.3.1 및 Ruby 2.2.0으로 만 테스트했지만 (내가 사용하는 환경이기 때문에) 다른 환경에서도 작동 할 것으로 예상합니다. 그러나 Windows에 대한 보장은 없습니다.

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