Làm cách nào để tôi nói với git-svn về một nhánh từ xa được tạo sau khi tôi tìm nạp repo?


193

Tôi đang sử dụng git-svnđể chống lại kho Subversion trung tâm của công ty tôi. Gần đây chúng tôi đã tạo ra một nhánh tính năng mới trong repo trung tâm.

Làm thế nào để tôi nói với Git về nó? Khi tôi chạy, git branch -rtôi chỉ có thể thấy các nhánh tồn tại khi tôi chạy fetchvới repo Subversion để khởi tạo repo Git của tôi?


Câu trả lời từ đây: stackoverflow.com/questions/13376917/ cũng có thể hữu ích.
Tomasz Gandor

Câu trả lời:


294

Bạn có thể tự thêm chi nhánh từ xa,

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch

3
chỉ cần thêm liên kết này vào tài liệu dưới dạng tham chiếu kernel.org/pub/software/scm/git/docs/git-svn.html
slf

1
Từ .git / config khá dễ hiểu làm thế nào các nhánh từ xa có thể được cấu hình từ kho / nhiều kho.
Mikael Lepistö

6
Nếu tôi có thể nâng cao điều này như tám lần, tôi sẽ làm thế. Cuối cùng, một cách để thêm một chi nhánh svn được thêm vào một vị trí không chuẩn!
Tim Keat

7
Tôi nhận được fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.ở bước kiểm tra git.
phpguru

17
@phpguru Hãy thử xóa cờ tùy chọn -t để nó trở thành 'git checkout -b local-newbranch newbranch' đừng quên đưa tiền tố của điều khiển từ xa vào newbranch (ví dụ: origin / newbranch).
mj1531

96

Nếu bạn muốn theo dõi TẤT CẢ các nhánh svn từ xa, thì giải pháp đơn giản như:

git svn fetch

Điều này sẽ tìm nạp TẤT CẢ các nhánh từ xa chưa được tìm nạp.

Mẹo thêm: nếu ban đầu bạn chỉ kiểm tra thân cây và sau đó bạn muốn theo dõi TẤT CẢ các nhánh, sau đó chỉnh sửa .git/configđể trông như thế này và chạy lại git svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

Các điểm chính urlcần trỏ đến thư mục gốc của kho lưu trữ và các đường dẫn được xác định trong fetchbranchesphải liên quan đến url.

Nếu bạn muốn chỉ tìm nạp các nhánh cụ thể thay vì TẤT CẢ, có một ví dụ hay trong git svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

Với các phiên bản cũ hơn git-svn, một khi bạn đã chỉ định các nhánh như thế này, bạn có thể không nhận được các nhánh mới với git svn fetch. Một cách giải quyết khác là thêm nhiều fetchdòng hơn , như thế này:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

Một cách giải quyết khác của @AndyEstes: chỉnh sửa .git/svn/.metadatavà thay đổi giá trị của branches-maxRevhoặc tags-maxRevthành bản sửa đổi trước khi bất kỳ nhánh hoặc thẻ được chỉ định mới nào được tạo. Khi bạn đã hoàn thành việc này, hãy chạy git svn fetchđể theo dõi chi nhánh từ xa svn mới.


1
Nếu bạn đã tìm nạp bản sửa đổi để thực hiện phân nhánh svn trước khi bạn đặt các cài đặt đó, bạn có thể muốn thực hiện đặt lại git svn.
kcm1700

3
Chỉnh sửa .git/svn/.metadatarất hữu ích! Tôi đã thêm các chi nhánh bổ sung trong .git/configđó, git svn fetchkhông nhận được - vì số sửa đổi siêu dữ liệu là "quá xa". Trong một trường hợp, chỉ có cam kết cuối cùng từ một nhánh được lấy. Tôi tự còn phiền phức với các chi nhánh bị lỗi (đổi tên .git/svn/refs/remotes/svn/qa/XYZđể .git/svn/refs/remotes/svn/qa/XYZ~, giảm tồn tại của nó trong .git/packed-refs, vân vân) ... nhặt một số sửa đổi "sớm hơn" cho các siêu dữ liệu ... ran git svn fetchđể cuối cùng có được một lịch sử đầy đủ w / đúng, kết nối đồ thị.
starlocke

8
ĐIỀU NÀY NÊN ĐƯỢC CHẤP NHẬN TRẢ LỜI! @janos, bạn vừa tiết kiệm cho tôi hàng giờ đau đầu! Nếu bạn từng đến Ấn Độ, tôi sẽ đưa bạn đi uống bia!
Roopesh Shenoy

1
Hoặc : git svn fetch --all.
kenorb

1
Câu trả lời này thật tuyệt vời, vì nó trả lời khoảng 7 câu hỏi mà tôi không thể tìm thấy câu trả lời nào, và nó làm như vậy mà không cần viết một bài tường thuật 6 trang.
Droj

53

Có vẻ như tôi chỉ cần git svn fetch; bằng cách nào đó tôi đã thuyết phục bản thân rằng sẽ lấy toàn bộ repo thay vì chỉ thay đổi.


7
@mitjak Tại sao nó không phải là câu trả lời đúng, nếu đó là giải pháp? Tôi không hiểu sự tinh tế của câu trả lời.
rholmes 18/03

'một giải pháp' có thể không phải là 'giải pháp'
slf

1
@rholmes: Tôi khá chắc chắn mitjak có nghĩa đó là giải pháp cho vấn đề của bạn nhưng không phải là câu trả lời cho câu hỏi bạn đã hỏi. (Bởi vì bạn đã hỏi sai câu hỏi; khi bạn giải thích sai vấn đề vào thời điểm đó.)
Mike Nelson

Điều này hoạt động khi chi nhánh tồn tại tại thời điểm bạn sao chép kho svn vào git. Nó sẽ không hoạt động nếu nhánh trong kho svn được tạo sau đó.
Petr Gladkikh

3
Nó hoạt động tốt khi nhánh được tạo sau bản sao, tôi làm điều đó mọi lúc.
Tim Gautier

15

Có thể tôi đã làm hỏng nó bằng cách nào đó nhưng tôi đã làm theo hướng dẫn trong câu trả lời của vjangus và nó gần như đã hoạt động. Vấn đề duy nhất là newbranch dường như không được phân nhánh từ thân cây. Trong gitk, nó là loại "nổi" một mình; nó không có tổ tiên chung với thân cây.

Giải pháp cho vấn đề này là:

  1. Tìm SHA1 của lần xác nhận cuối cùng xảy ra trên thân cây trước khi nhánh được tạo.
  2. Tìm SHA1 của cam kết đầu tiên trên nhánh mới (thông báo có thể là "Đã tạo chi nhánh mới, được sao chép từ trung kế @ 12345" hoặc một cái gì đó)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- không nên có đầu ra. Nếu có đầu ra, bạn có thể đã chọn sai cam kết.
  4. git checkout local-newbranchsau đó git rebase <sha1 from step 1>. Điều này sẽ nổi local-newbranchloạn lên cây mới nhưng remotes/newbranchvẫn bị ngắt kết nối.
  5. Chuyển đến tệp .git/refs/remotes/newbranchvà chỉnh sửa tệp để chứa SHA1 đầy đủ của cam kết mới (trên đã bị loại bỏ newbranch) tương ứng với cam kết cũ mà nó hiện đang trỏ tới. (Hoặc có thể sử dụng git-update-ref refs/remotes/newbranch <new-SHA>. Cảm ơn bạn inger.)
  6. Lần git svn dcommittới newbranch, bạn sẽ nhận được một loạt tin nhắn về việc cập nhật một số nhật ký. Điều này là bình thường tôi nghĩ.

Tôi khuyên bạn nên giữ gitk --alltoàn bộ thời gian và làm mới nó thường xuyên để theo dõi những gì bạn đang làm. Tôi vẫn chưa quen với git và git svn, vì vậy vui lòng đề xuất cải tiến cho phương pháp này.


2
Cảm ơn, điều này nghe có vẻ hữu ích. Khoảng 5. có lẽ 'git-update-ref refs / remote / newbranch <new-SHA>' là tùy chọn an toàn hơn.
nhập

Chỉ cần thử cách của vjangus một lần nữa và nó hoạt động hoàn hảo. Dù sao tôi cũng sẽ để nó ở đây vì nó có thể có giá trị với ai đó ...
MatrixFrog

1
giải pháp vjangus luôn tạo ra nhánh mới bị ngắt kết nối từ thân cây. Tôi cho rằng điều này là do cách SVN không có manh mối về cách thức nội dung thực tế được sao chép xung quanh.
bogdan.mustiata

Kinh nghiệm của tôi với một repo git-svn lớn là các nhánh svn luôn được tạo trong git tách ra khỏi thân cây. Phải có cách nào đó để kết nối chúng, nhưng tôi đã không dành thời gian để tìm ra nó. AFAIK, bạn không thể khởi động lại nhánh git được kết nối với nhánh svn, vì điều đó sẽ làm rối logic logic dcommit. Chúng ta vừa học cách sống với nó.
Spencer

7

Đơn giản hóa câu trả lời của vjangus:

Nếu bạn đang sử dụng bố cục tiêu chuẩn trong SVN và đã thực hiện init svn thông thường, git-svn sẽ thực hiện công cụ cấu hình cho bạn. Chỉ:

  1. Tìm bản sửa đổi chi nhánh trong SVN
  2. Tìm nạp bản sửa đổi đó bằng git-svn
  3. Tạo từ xa theo dõi chi nhánh địa phương mới

Một ví dụ. SVN url là svn+ssh://gil@svn.myplace.com/repo. Chi nhánh SVN tôi đang tìm là newbranch. Chi nhánh git địa phương (theo dõi từ xa newbranch) sẽ được git-newbranch.

Bước 1: tìm bản sửa đổi bản sao chi nhánh

    # svn log --stop-on-copy svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch | đuôi -4
    r7802 | ai đó | 2014 / 03-21 18:54:58 +0000 (Thứ Sáu, 21 tháng 3 năm 2014) | 1 dòng

    phân nhánh đầu đến newbranch
    -------------------------------------------------- ----------------------

Vì vậy, điểm nhánh trong SVN là phiên bản 7802.

Bước 2: Lấy bản sửa đổi

    # git svn tìm nạp -r 7802
    Tìm thấy điểm nhánh có thể: svn + ssh: //gil@svn.myplace.com/repo/trunk => svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch, 7801
    Tìm thấy nhánh cha mẹ: (refs / điều khiển từ xa / thân cây) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Theo dõi phụ huynh với do_switch
    Thành công theo cha mẹ
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs / điều khiển từ xa / newbranch)

git-svn đã làm tất cả công việc và bây giờ biết về điều khiển từ xa:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / điều khiển từ xa / newbranch

Bước 3: Tạo chi nhánh địa phương mới theo dõi từ xa:

    # git thanh toán -b git-newbranch -t newbranch
    Kiểm tra các tệp: 100% (413/413), đã hoàn tất.
    Chi nhánh git-newbranch được thiết lập để theo dõi các ref / điều khiển từ xa / newbranch tại địa phương.
    Chuyển sang một nhánh mới 'git-newbranch'

Làm theo điều này cuối cùng đã cho phép tôi hiểu ( show-reflà vô giá)! Đối với bất kỳ ai bị mắc kẹt với các nhánh từ xa tham chiếu sai, bạn có thể xóa chúng (tôi phải làm git branch -d newbranchvà sau đó buộc xóa thư mục ref trong .git/svn/refs/remotes/newbranch) và sau đó bắt đầu lại ở bước 2 (ở trên).
tutuDajuju

5

Tôi chưa tìm thấy tài liệu nào về tính năng này, nhưng có vẻ như cấu hình git svn hỗ trợ nhiều mục tìm nạp. Bằng cách này, bạn cũng có thể thêm các nhánh riêng biệt mà không cần thêm một mục lưu trữ svn từ xa khác vào cấu hình của mình cũng như không sử dụng ký tự đại diện để có được tất cả các nhánh của thư mục nhất định.

Giả sử rằng cây SVN của bạn thực sự khó chịu khi có rất nhiều nhánh mà không có logic nào về vị trí của chúng, ví dụ như có các nhánh và thư mục con chứa nhiều nhánh hơn.

I E

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

và bạn chỉ muốn tự tay chọn một số nhánh được đưa vào kho git của bạn.

Trước tiên, bạn có thể khởi tạo kho lưu trữ của mình chỉ với thân cây mà không cần thêm bất kỳ nhánh nào:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

Sau đó, bạn sẽ thấy cấu hình sau:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

bất cứ khi nào bạn muốn tìm nạp chi nhánh mới từ MyRepo, bạn chỉ có thể thêm các mục tìm nạp mới vào cấu hình bằng cách:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

Hoặc bạn có thể chỉnh sửa cấu hình tương tự trong .git / config

Để tìm nạp các nhánh mới sau khi thêm chúng vào cấu hình, chỉ cần chạy:

git svn fetch -r 10000:HEAD

[Chỉnh sửa] Đôi khi có vẻ cần phải chạy tìm nạp với tham số --all để tìm nạp các nhánh mới được thêm vào:

git svn fetch --all -r 10000:HEAD

4

Thay vì xử lý các quirks git-svn, bạn có thể thử SubGit .

Người ta phải cài đặt SubGit vào kho Subversion. Sau đó, người ta có thể sử dụng luồng công việc git tiêu chuẩn thay vì sử dụng các lệnh git-svn đặc biệt:

  1. Đẩy các cam kết mới:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Lấy các thay đổi đến

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Tạo một nhánh mới:

    git-svn:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

Xem tài liệu SubGit để biết thêm chi tiết.


1
SubGit có nhược điểm là nó tạo ra hai kho lưu trữ - một svn và một kho chứa git "bóng". Đây có thể là một vấn đề đối với các kho lưu trữ SVN khổng lồ ...
Udo

@Udo nếu kho SVN có một vài dự án, người ta có thể chỉ định một trong số chúng và đồng bộ hóa nó với kho Git. Trong trường hợp này, không cần phải chuyển đổi toàn bộ kho Subversion thành Git. Nhưng nếu một người có một dự án SVN khổng lồ trong kho lưu trữ này, thì người ta có thể chuyển đổi không phải toàn bộ lịch sử của kho lưu trữ này mà là lịch sử bắt đầu từ một số sửa đổi tối thiểu. Điều này cho phép giảm kích thước của kho lưu trữ Git đã dịch.
vadishev

1
@Udo - bất kỳ công ty nào không sẵn sàng mua máy chủ kho lưu trữ của họ một ổ cứng có những ưu tiên của họ bị rối tung. Nhưng hầu hết các nơi có kho lưu trữ khổng lồ đều coi kho của họ khá nghiêm trọng và yêu cầu không gian đĩa cho kho lưu trữ nói chung không phải là vấn đề lớn, ngay cả đối với các công ty có hàng thập kỷ lịch sử và hàng chục triệu dòng mã và hàng trăm nghìn bản sửa đổi. Đó là hình thức cụ thể nhất của công ty về tài sản trí tuệ cốt lõi của họ và không gian đĩa khá rẻ. Nó có thể kích hoạt nhu cầu nâng cấp bộ điều khiển RAID, nhưng ngay cả như vậy, việc tăng năng suất ...
Bob Kerns

@Bob Kerns - Vấn đề là SVN và Git "kích thước khôn ngoan" và không tương thích. Đây không phải là một câu hỏi về lưu trữ đĩa hay như vậy. Nhưng bạn có thể làm việc với kho SVN khổng lồ vì thông thường bạn chỉ cần kiểm tra một vài tệp / dự án. Nhưng bạn không thể sao chép một kho lưu trữ Git khổng lồ - ít nhất nó cũng không gây cười ;-) Bởi "khổng lồ", ý tôi là một số hợp đồng biểu diễn.
Udo

2

Để thêm vào câu trả lời của vjangus, điều này đã giúp tôi, tôi cũng thấy hữu ích khi thêm sử dụng ghép git để buộc các nhánh vào thân cây tại điểm thích hợp - cho phép git xem lịch sử và thực hiện kết hợp chính xác.

Đây chỉ đơn giản là một trường hợp thêm một dòng vào .git/info/graftsbăm:

<initial branch commit> <parent commit in trunk>

ví dụ.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Tín dụng cho http://evan-tech.livejournal.com/255341.html

(Tôi sẽ thêm nhận xét này dưới dạng nhận xét, nhưng tôi không đủ danh tiếng.)


0

Nếu bạn không kiểm tra với bố cục hợp lệ, bạn sẽ không thể kiểm tra chi nhánh từ xa.

Đây là những gì tôi làm:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

Sau đó, bạn có thể chuyển sang một chi nhánh từ xa:

git checkout --track -b branch_name branch_name

Sau đó, bạn sẽ tự động được chuyển sang chi nhánh của bạn.

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.