git-svn: tương đương với `svn switch --relocate` là gì?


88

Kho lưu trữ svn mà tôi đang phản ánh thông qua git-svn đã thay đổi URL.

Trong vani svn bạn chỉ cần làm svn switch --relocate old_url_base new_url_base.

Làm cách nào để thực hiện việc này bằng git-svn?

Chỉ cần thay đổi url svn trong tệp cấu hình không thành công.


Bạn nên cố gắng và có thể chấp nhận câu trả lời này: stackoverflow.com/a/4061493/1221661
Fritz

Câu trả lời cập nhật nhất: stackoverflow.com/a/40523789/537554 . Cùng một câu hỏi, nhưng được hỏi từ quan điểm của người dùng Git.
ryenus

Câu trả lời:


61

Điều này xử lý tình huống của tôi khá tốt:

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

Tôi đã sao chép bằng file://giao thức và muốn chuyển sang http://giao thức.

Bạn rất muốn chỉnh sửa urlcài đặt trong [svn-remote "svn"]phần của .git/config, nhưng tự nó không hoạt động. Nói chung, bạn cần làm theo quy trình sau:

  1. Chuyển urlcài đặt svn-remote sang tên mới.
  2. Chạy đi git svn fetch. Điều này cần tìm nạp ít nhất một bản sửa đổi mới từ svn!
  3. Thay đổi urlcài đặt svn-remote trở lại URL ban đầu.
  4. Chạy git svn rebase -lđể thực hiện một rebase cục bộ (với các thay đổi đi kèm với hoạt động tìm nạp cuối cùng).
  5. Thay đổi urlcài đặt svn-remote trở lại URL mới.
  6. Bây giờ, git svn rebasesẽ hoạt động trở lại.

Những tâm hồn phiêu lưu có thể muốn thử --rewrite-root.


2
công bằng mà nói, điều này thực sự không thành công đối với tôi, và cuối cùng tôi đã nhân bản lại repo. Thật khó để có được git để xử lý nó khi thư mục svn được đổi tên.
Gregg Lind

Tôi muốn chấp nhận một bản viết chi tiết hơn, nhưng công bằng mà nói, tôi sẽ chấp nhận nó cho đến khi có câu trả lời mới.
kch

2
Đây là một mô tả về thủ tục: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray

liên kết được cung cấp trong câu trả lời được chấp nhận đã lỗi thời và liên kết mới hiện tại là: git.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.html Tôi đã theo dõi "Trường hợp chung" và nó rất đơn giản và thực sự hoạt động tốt.
TcMaster

2
@TcMaster: cũng phù hợp với tôi ... nhưng đó là lý do tại sao các câu trả lời không nên chỉ chứa các liên kết, chúng sẽ lỗi thời và trở nên vô dụng ... Tôi sẽ thêm một câu trả lời wiki cộng đồng.
UncleZeiv

37

Bạn có thể xem những cách sau có hoạt động tốt không:

  1. Nếu svn-remote.svn.rewriteRootkhông tồn tại trong tệp cấu hình ( .git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. Nếu svn-remote.svn.rewriteUUIDkhông tồn tại trong tệp cấu hình:

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

    currentRepositoryUUIDthể được lấy từ .git/svn/.metadata.

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


Tuyệt vời - cảm ơn, điều này đã làm việc tuyệt vời cho tôi (nhân bản qua file://, chuyển sang svn+ssh); chỉ cần lưu ý rằng: thủ tục này không cần phải "lấy ít nhất một bản sửa đổi mới từ svn"; cũng ./.git/svn/.metadatasau lần đầu tiên svn rebasechứa <newRepository>as reposRoot- nhưng điều này không đủ để xóa các rewrite*khóa khỏi .git/config; do đó, những chìa khóa đó nên được giữ vĩnh viễn ở đó, theo như tôi hiểu.
sdaau

1
Nó cũng có tác dụng với tôi, giống như một cái duyên. OP nên thử câu này và nhận nó là câu trả lời chính xác.
Rafareino

Hoàn hảo. Tôi đã có một dự án lớn với hàng nghìn cam kết trong lịch sử nên một bản sao mới sẽ phá hủy lịch sử (hoặc mất một thời gian dài để kiểm tra). Tôi đang sử dụng svn+ssh://và máy chủ svn của chúng tôi vừa thay đổi miền từ .sethành .comđể khử trùng tên nội bộ của chúng tôi.
UlfR

Đã làm một điều trị cho tôi. Có một repo 2 năm tuổi với 1.000 lượt cam kết, repo đã được chuyển sang máy chủ mới, vì vậy điều này tránh được một bản sao svn đầy đủ (đáng sợ).
David Victor

21

Thật không may, hầu hết các liên kết trong những câu trả lời này không hoạt động, vì vậy tôi sẽ sao chép một chút thông tin từ git wiki để tham khảo trong tương lai.

Giải pháp này đã làm việc cho tôi:

  • Chỉnh sửa svn-remote url(hoặc fetchđường dẫn) trong .git/configđể trỏ đến tên miền / url / đường dẫn mới

  • Chạy git git svn fetch. Điều này cần tìm nạp ít nhất một bản sửa đổi mới từ svn!

  • Nếu bạn thử git svn rebasengay bây giờ, bạn sẽ nhận được thông báo lỗi như sau:

    Unable to determine upstream SVN information from working tree history
    

    Tôi nghĩ rằng điều này là do git svnbị nhầm lẫn bởi thực tế là cam kết mới nhất của bạn trước khi tìm nạp sẽ có một git-svn-idđường dẫn cũ, không khớp với đường dẫn được tìm thấy trong .git/config.

  • Để giải quyết vấn đề, hãy thay đổi svn-remote url(hoặc fetchđường dẫn) trở lại miền / url / đường dẫn ban đầu

  • Bây giờ hãy chạy git svn rebase -llại để thực hiện tái cơ sở cục bộ với những thay đổi có trong thao tác tìm nạp cuối cùng. Lần này nó sẽ hoạt động, rõ ràng là vì git svnsẽ không bị nhầm lẫn bởi thực tế là git-svn-idđầu mới không khớp với đầu được tìm thấy trong .git/config.

  • Cuối cùng, thay đổi svn-remote url(hoặc fetchđường dẫn) trở lại miền / url / đường dẫn mới

  • Tại thời điểm này git svn rebasesẽ hoạt động trở lại!

Thông tin ban đầu được tìm thấy ở đây .


3

Git svn chủ yếu dựa vào URL svn. Mọi cam kết được nhập từ svn đều có git-svn-idbao gồm URL svn.

Chiến lược chuyển vị trí hợp lệ là gọi git-svn clonevào kho lưu trữ mới và hợp nhất các thay đổi vào lần đóng mới đó. Để biết quy trình chi tiết hơn, hãy xem bài viết này:

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


2

git filter-branch

Tập lệnh này , được lấy từ một mục blog , đã làm việc cho tôi. Cung cấp URL repo cũ và mới làm tham số, giống như đối với svn switch --relocate.

Tập lệnh gọi git filter-branchđể thay thế các URL Subversion trong git-svn-idthông báo cam kết, cập nhật .git/configvà cũng cập nhật git-svnsiêu dữ liệu bằng cách sử dụng tạo lại nó git svn rebase. Mặc dù git svn clonecó thể là giải pháp mạnh mẽ hơn, nhưng filter-branchphương pháp này hoạt động nhanh hơn nhiều đối với các kho lưu trữ khổng lồ (giờ so với ngày).

#!/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

Tuy nhiên, nhanh hơn git-filter-branch(ví dụ, phút thay vì giờ), nhưng tinh thần tương tự, là sử dụng git_fast_filter. Tuy nhiên, điều này đòi hỏi phải viết mã nhiều hơn một chút và không có giải pháp đóng gói sẵn sàng gọn gàng nào tồn tại. Ngược lại git-filter-branch, điều này sẽ tạo một repo mới từ repo . Nó được giả định rằng mastertrỏ đến cam kết SVN cuối cùng.

  1. Sao git_fast_filterchép từ repo Gitorious.
  2. Tạo một tập lệnh Python trong cùng một thư mục mà bạn đã nhân bản git_fast_filterdựa trên Gist này , đặt bit thực thi bằng cách sử dụng chmod +x. Điều chỉnh các đường dẫn kho lưu trữ cũ và mới. (Nội dung của tập lệnh cũng được dán bên dưới.)
  3. Khởi tạo một kho mục tiêu mới bằng cách sử dụng git init, thay đổi thư mục làm việc thành kho mới này.
  4. Thực hiện đường ống sau:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Sao chép .git/configvà có thể các tệp có liên quan khác .git/infotừ repo cũ sang repo mới.

  6. Loại bỏ .git/svn.
  7. Hãy git-svnnhận thức được bản đồ số phiên bản mới

    1. Hành hình git branch refs/remotes/git-svn master

      • Bạn điều khiển từ xa git-svn thể được gọi là khác nhau hơn refs/remotes/git-svn, tham khảo ý kiến .git/config, svn-remotephần
    2. Thực thi git svn info. Nếu lệnh này bị đóng băng, có gì đó không ổn. Nó sẽ xây dựng lại ánh xạ số sửa đổi.

    3. Loại bỏ nhánh giả refs/remotes/git-svn, nó sẽ được tạo lại bằnggit-svn

  8. Đồng bộ hóa bằng cách gọi git svn rebase.

Dưới đây là nội dung của commit_filter.py, thay thế các giá trị của IN_REPOOUT_REPOkhi thích hợp:

#!/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 -lGiải pháp trên không làm việc cho tôi. Tôi quyết định đi theo một cách khác:

  1. Sao chép repo SVN cũ thành git repo oldvà SVN mới thành git reponew
  2. Tìm nạp oldvàonew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newở trên old(sẽ thành công vì các cây ở gốc newvà ngọn của oldgiống hệt nhau)
    • git checkout master(Giả sử rằng masternhánh đang trỏ vào đầu SVN. Đây sẽ là trường hợp với một bản sao sạch; nếu không, hãy loại bỏ trước khi bạn bắt đầu.)
    • git rebase --root --onto old
  4. Xây dựng lại siêu dữ liệu git-svn của newtài khoản cho rebase
    • git update-ref --no-deref refs/remotes/git-svn master(điều chỉnh tham chiếu từ xa tùy thuộc vào cách bạn sao chép, ví dụ như nó có thể được refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info

1. Bạn có bắt đầu với một bản sao mới từ vị trí mới sang vị trí mới không? Nếu có, tại sao bạn vẫn chưa hoàn thành tại thời điểm đó? 2. Nếu bạn rebase new trên old, thì tất cả các commit cũ của bạn có đề cập đến URL cũ trong mục nhập nhật ký commit svn-id của họ không? 3. Có tài liệu nào lưu để loại bỏ .git / svn không? (3b: đó lệnh được xây dựng lại các siêu dữ liệu git-svn, git info svn?)
Micha Wiedenmann

0

Dựa trên một số câu trả lời khác cho câu hỏi này, tôi đã đưa ra một tập lệnh Ruby xử lý việc di chuyển git-svn. Bạn có thể tìm thấy nó tại https://gist.github.com/henderea/6e779b66be3580c9a584 .

Nó xử lý việc di dời mà không cần kiểm tra một bản sao khác và thậm chí nó còn xử lý trường hợp có những thay đổi chưa được đẩy trong một hoặc nhiều nhánh (vì điều đó phá vỡ logic thông thường). Nó sử dụng nội dung từ câu trả lời nhánh bộ lọc git (cho logic chính) và câu trả lời về việc sao chép các nhánh từ phiên bản repo này sang phiên bản khác (để sao chép các nhánh với các thay đổi chưa được đẩy).

Tôi đã sử dụng điều này để di chuyển một loạt các repo git-svn mà tôi có cho công việc và phiên bản script này (tôi đã trải qua vô số lần lặp lại) dường như phù hợp với tôi. Nó không phải là quá nhanh, nhưng nó dường như xử lý tất cả các trường hợp tôi gặp phải và dẫn đến một repo được chuyển vị trí hoàn toàn.

Tập lệnh cung cấp cho bạn tùy chọn tạo bản sao của repo trước khi thực hiện bất kỳ thay đổi nào, vì vậy bạn có thể sử dụng tùy chọn này để tạo bản sao lưu. Cần tạo bản sao nếu bạn có các thay đổi chưa được đẩy trong bất kỳ nhánh nào.

Tập lệnh không sử dụng bất kỳ đá quý hoặc thư viện nào khác không có trong cài đặt MRI Ruby thông thường. Nó sử dụng các thư viện readline và fileutils có trong MRI.

Hy vọng rằng kịch bản của tôi sẽ hữu ích cho người khác. Vui lòng thực hiện thay đổi đối với kịch bản.

LƯU Ý: Tôi chỉ thử nghiệm tập lệnh này với git 2.3.0 / 2.3.1 và Ruby 2.2.0 trên OS X 10.10 Yosemite (vì đó là môi trường tôi sử dụng), nhưng tôi mong đợi nó cũng hoạt động trên các môi trường khác. Tuy nhiên, không có gì đảm bảo về Windows.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.