既存のGitリポジトリをSVNにプッシュする


384

私はすべての作業をGitで行っており、GitHubにプッシュしています。私はソフトウェアとサイトの両方に非常に満足しており、この時点で自分の作業方法を変更したくありません。

私のPhDアドバイザーは、すべての学生に、大学でホストされているSVNリポジトリに作業を保存するように依頼しています。既存のSVNリポジトリをGitにプルダウンしようとする大量のドキュメントとチュートリアルを見つけましたが、Gitリポジトリを新しいSVNリポジトリにプッシュすることについては何もありませんでした。git-svnと新鮮なブランチを組み合わせてこれを行う方法がいくつかあるに違いないと思いますが、私はGitの初心者であり、それらのどれにも自信がありません。

次に、いくつかのコマンドを実行して、選択したときにコミットをそのSVNリポジトリーにプッシュしたいと思います。Gitを使い続け、SVNリポジトリにGitの内容をミラーリングさせたいと思います。

これが何かの違いを生むなら、私がSVNにコミットする唯一の人になります。


1
注:これを行うと、おそらく元の日付スタンプが失われます。新しい日付は、Subversionへのインポートの時刻に基づいています。
nobar 2013

一部が自動化への探索中に、次のポスト役に立つを見つけることができ、より最新の情報をお探しの方のために:deliciousbrains.com/deploying-wordpress-plugins-travis
ジョシュHabdas

回答:


402

私もこれが必要でした。Bombeの回答といくつかのいじくりの助けを借りて、私はそれを機能させました。ここにレシピがあります:

Gitのインポート-> Subversion

1. cd /path/to/git/localrepo
2. svn mkdir --parents protocol:///path/to/repo/PROJECT/trunk -m "Importing git repo"
3. git svn init protocol:///path/to/repo/PROJECT -s
4. git svn fetch
5. git rebase origin/trunk
5.1.  git status
5.2.  git add (conflicted-files)
5.3.  git rebase --continue
5.4.  (repeat 5.1.)
6. git svn dcommit

#3の後、次のような不可解なメッセージが表示されます。

より高いレベルのURLの使用: protocol:///path/to/repo/PROJECT => protocol:///path/to/repo

無視してください。

#5を実行すると、競合が発生する可能性があります。これらの問題を解決するには、「マージされていない」状態のファイルを追加し、リベースを再開します。最終的には、これで完了です。次に、を使用して、SVNリポジトリに同期しdcommitます。それで全部です。

リポジトリの同期を保つ

次のコマンドを使用して、SVNからGitに同期できるようになりました。

git svn fetch
git rebase trunk

GitからSVNに同期するには、次を使用します。

git svn dcommit

最後のメモ

ライブリポジトリに適用する前に、ローカルコピーでこれを試すことができます。Gitリポジトリのコピーを一時的な場所に作成できます。cp -rすべてのデータがリポジトリ自体にあるため、単にを使用します。次に、以下を使用して、ファイルベースのテストリポジトリを設定できます。

svnadmin create /home/name/tmp/test-repo

そして、以下を使用して作業コピーをチェックアウトします。

svn co file:///home/name/tmp/test-repo svn-working-copy

これにより、永続的な変更を加える前に、いろいろなことができるようになります。

補遺:失敗した場合 git svn init

git svn init誤って間違ったURLで実行し、作業のバックアップを取るほど賢くなかった場合(質問しないでください...)、同じコマンドをもう一度実行することはできません。ただし、次のコマンドを実行して変更を取り消すことができます。

rm -rf .git/svn
edit .git/config

そして、セクション[svn-remote "svn"]sectionを削除します。

その後、git svn init新たに実行できます。


2
いい答えだ。これはコミット日もめちゃくちゃですか?
Drew Noakes 2010年

4
良い質問-残念ながら、どちらの答えもわかりません。これは、私が機能することがわかったもののより実用的なガイドです。私はすべての詳細を完全には理解していません。コミット日については、テストを行って調べることができると思います。物事をテストするために、ローカル(fsベース)のsvnリポジトリを初期化できることを覚えておいてください。
troelskn 2010年

10
手順5の代わりに「git rebase --onto trunk --root」を使用して同じ手順を実行しましたが、はるかに成功しました。トンの代わりに、解決するマージ競合のほんの一握り。
kubi

5
私の場合、このシーケンスは機能しませんでした。常に「HEAD履歴から上流のSVN情報を特定できません」というメッセージが表示されました。したがって、dcommitは不可能です。
Fedir RYKHTIK、2012年

2
気にしないで、SVNの標準設定(trunk / branchs / tags /)に従いたくなかったので、賢くして-sを省略しようとしました。それなしではまったく機能しません。
James McMahon

33

これが私たちがそれを機能させた方法です:

マシンのどこかにGitリポジトリのクローンを作成します。

.git / configを開き、以下を追加します(Gitリポジトリの読み取り専用SVNミラーのメンテナンスから):

[svn-remote "svn"]
    url = https://your.svn.repo
    fetch = :refs/remotes/git-svn

次に、コンソールウィンドウから次のように入力します。

git svn fetch svn
git checkout -b svn git-svn
git merge master

ここで、何らかの理由でここが壊れた場合は、次の3行を入力します。

git checkout --theirs .
git add .
git commit -m "some message"

そして最後に、SVNにコミットできます。

git svn dcommit

注:後でそのフォルダを常にスクラップします。


6
1これは実際に与えて上に保持他の回答とは対照的に、(トランク/ベース何を持っていない)私のために働いたUnable to determine upstream SVN information from HEAD history.
stijn


2
このテクニックを試しましたが、履歴はインポートされませんでした。ところで、「git merge master」は「git merge --allow-unrelated-histories master」になりました
Berend de Boer

1
SVNの内容をgitの内容で上書きしたい場合は、を使用してくださいgit merge -s recursive -Xtheirs --allow-unrelated-histories master
user1475814

28

git rebase直接使用すると、最初のコミットが失われます。Gitはそれを別の方法で扱い、リベースできません。

完全な履歴を保存する手順があります:http : //kerneltrap.org/mailarchive/git/2008/10/26/3815034

ここで解決策を書き起こしますが、クレジットはビョルンのためのものです。

git-svnを初期化します。

git svn init -s --prefix=svn/ https://svn/svn/SANDBOX/warren/test2

--prefixを使用すると、「svn / trunk」のようなリモートトラッキングブランチが提供されます。これは、ローカルブランチを単に「トランク」と呼んでも、あいまいな名前を取得しないため便利です。そして-s、標準のトランク/タグ/ブランチのレイアウトへのショートカットです。

SVNから最初のものをフェッチします。

git svn fetch

次に、ルートコミットのハッシュを調べます(単一のコミットが表示されます)。

git rev-list --parents master | grep '^.\{40\}$'

次に、空のトランクコミットのハッシュを取得します。

git rev-parse svn/trunk

移植片を作成します。

echo <root-commit-hash> <svn-trunk-commit-hash> >> .git/info/grafts

これで、「gitk」がsvn/trunkマスターブランチのベースとなる最初のコミットとして表示されます。

移植片を永続化します。

git filter-branch -- ^svn/trunk --all

移植片を落とす:

rm .git/info/grafts

gitkは引き続きsvn/trunkmasterの祖先に表示されます。

トランクの上に履歴を線形化します。

git svn rebase

そして今、 "git svn dcommit -n"はトランクにコミットすることを伝えます。

git svn dcommit

この手法が上記とどのように異なるのかをより明確に説明できますか。
cmcginty 2009年

3
「git rev-parse svn / trunk」を実行しようとすると、作業ツリーにない不明なリビジョンまたはパスが報告されます。
Adam Ness

これは私にとってうまくいった唯一の答えですが、git filter-branchとdropraftの手順は必要ありませんでした。Graftの作成後にリベースを行い、次にgit svn dcommitを行いました。
fc7

8

プロジェクトのSubversionリポジトリに新しいディレクトリを作成します。

# svn mkdir --parents svn://ip/path/project/trunk

Gitで管理されたプロジェクトに変更し、git-svnを初期化します。

# git svn init svn://ip/path/project -s
# git svn fetch

SVNプロジェクトディレクトリがまだ空であるため、これにより単一のコミットが作成されます。次に、そのコミットに基づいてすべてをリベースしますgit svn dcommit。これで完了です。ただし、コミット日が大幅に混乱します。


hassox.blogspot.com/2007/12/using-git-with-svn.htmlの指示に従ってこの回答を使用しました。 これらのコマンドを実行し、「#git branch -a」を実行してトランク名を確認しました。次に、#git checkout -b local-svn trunk#git merge master#git svn dcommit .gitvnre .svnディレクトリを忘れないでください!
cflewis 2009年

同じ操作を行ったばかりなので、しばらくの間('09年1月)、gitがルートコミットでリベース操作を実行できることを明示したいと思いました。これにより、多くの古い記事が示すよりもプロセスがはるかに単純になります。its.arubything.com/ 2009/1/4 /…の
Louis Jacomet

"-s" git svn initオプションは何をしますか?これはgit svnのmanページにはありません。
ネイサン、

manページをもう一度読んでください。「-s」がそこにあるので、検索してください。「--stdlayout」のエイリアスです。
ボンベ

7

Git->完全なコミット履歴を持つSVN

私はGitプロジェクトを持っていて、それをSVNに移動する必要がありました。これが私が作った方法で、コミット履歴全体を保持しています。失われるのは、libSVNがローカル時刻を設定するため、元のコミット時刻のみですgit svn dcommit

方法:

  1. ものをインポートしてgit-svnで複製したいSVNリポジトリがあります:

    git svn clone https://path.to/svn/repository repo.git-svn`
    
  2. そこに行く:

    cd repo.git-svn
    
  3. Gitリポジトリのリモートを追加します(この例ではC:/Projects/repo.gitを使用しています)。SVNにプッシュしてold-gitという名前を付けます:

    git remote add old-git file:///C/Projects/repo.git/
    
  4. old-gitリポジトリのマスターブランチから現在のリポジトリに情報を取得します。

    git fetch old-git master
    
  5. old-gitリモートのマスターブランチをチェックアウトして、現在のリポジトリのoldと呼ばれる新しいブランチに入れます。

    git checkout -b old old-git/master`
    
  6. HEADをold-git / masterの上に置くようにリベースします。これにより、すべてのコミットが維持されます。これは基本的に、Gitで行われたすべての作業をSVNからアクセスしている作業の上に置くことです。

    git rebase master
    
  7. 次に、masterブランチに戻ります。

    git checkout master
    

    そして、きれいなコミット履歴があることがわかります。これは、SVNにプッシュしたいものです。

  8. 作業をSVNにプッシュします。

    git svn dcommit
    

それで全部です。それは非常にクリーンでハッキングがなく、すべてが箱から出して完全に機能します。楽しい。


同様のプロセスは、chani.wordpress.com
/

のように見えます。しかし、私は彼女のやり方がかなりわかりにくく、私の方がはるかに短い(19/23よりも8ステップ)と思います。多分私は彼女を正しく取得していないかもしれませんが、彼女は2番目の弾丸でsvnコマンドとgitコマンドを混合していると思います。
codedave 2017

ああ、そうです、違いは、プロセスがgitをSVNリポジトリのルートにインポートし、彼女がそれをサブフォルダーにインポートすることgit svnです。そのため、いくつかの準備が必要です。
TWiStErRob 2017

ステップ7で、古いgitマージはありませんか?私にとっては、あなたが変更していないマスターのdcommitを作成しているようです。
アレクサンダー

@Alexanderは 'git rebase master'を使用して、2つの親を持つマージコミットのない線形マージである早送りマージを生成します。ここでは、線形の履歴が必要です。
codedave


3

既存のGitリポジトリを空のSVNリポジトリにコミットする必要がありました。

これは私がこれをどうやってやったかです:

$ git checkout master
$ git branch svn
$ git svn init -s --prefix=svn/ --username <user> https://path.to.repo.com/svn/project/
$ git checkout svn
$ git svn fetch
$ git reset --hard remotes/svn/trunk
$ git merge master
$ git svn dcommit

問題なく動作しました。これが誰かの役に立つことを願っています。

私はSVNリポジトリへの別のユーザー名で自分自身を承認する必要があったので(私originは秘密/公開鍵認証を使用しています)、--usernameプロパティを使用する必要がありました。


あなたがインストールする必要がありgit-svn、これが可能になる前に、参照stackoverflow.com/questions/527037/git-svn-not-a-git-command
flexponsive

2

Gitをメインリポジトリとして使用し続け、リビジョンをSVNに「エクスポート」する必要があるだけの場合は、Tailorを使用してSVNリポジトリの同期を保つことができます。異なるソース管理システム間でリビジョンをコピーでき、Gitで行った変更でSVNを更新します。

私はGitからSVNへの変換を試していませんが、SVN-> SVNの例については、この回答を参照してください。


2

機能したさらに別のシーケンス(各ステップにいくつかのコメントを付けて):

  1. インストールgit-svnsubversionツールキット:

    sudo apt-get install git-svn subversion
    
  2. 内部のスイッチ PROJECT_FOLDER

    cd PROJECT_FOLDER
    
  3. Subversionサーバーでプロジェクトパスを作成します(残念ながら、現在のgit-svnプラグインにはTortoiseSVNと比較して欠陥があります)。ソースコードをに直接保存することはできませんPROJECT_FOLDER。代わりに、デフォルトで、すべてのコードがにアップロードされPROJECT_FOLDER/trunkます。

    svn mkdir --parents protocol:/// path / to / repo / PROJECT_FOLDER / trunk -m "creating git repo placeholder"

これは、trunkパスの最後に必須の場所です

  1. フォルダーgit-svn内のプラグインコンテキストを初期化する.git

    git svn init -s protocol:///path/to/repo/PROJECT_FOLDER
    

    これは、trunkパスの終わりに不要な場所です

  2. 空のSubversionリポジトリ情報を取得する

    git svn fetch
    

    このステップは、Subversionサーバーをgit-svnプラグインと同期するのに役立ちます。これは、git-svnプラグインがremotes/originパスを確立し、それをtrunkサーバー側のサブフォルダーに関連付ける瞬間です。

  3. git-svnプラグインがプロセスに関与する前に古いGitコミットをリベースしました(このステップはオプションです

    git rebase origin/trunk
    
  4. コミットする新しい/変更されたファイルを追加します(この手順はGitアクティビティでは通常行われ、オプションです

    git add .
    
  5. 新しく追加したファイルをローカルGitリポジトリにコミットします(この手順はオプションであり、手順7を使用した場合にのみ適用されます)。

    git commit -m "Importing Git repository"
    
  6. すべてのプロジェクト変更履歴をSubversionサーバーにプッシュします。

    git svn dcommit
    

1

新しいSVNリポジトリを作成できます。Gitプロジェクトをエクスポートします(.gitファイルを具体化)。それをSVNリポジトリーに追加します(これまでにGitで使用していた内容でリポジトリーを初期化します)。次に、新しいGitプロジェクトにSVNリポジトリをインポートするための手順を使用します。

しかし、これは以前のGit履歴を失います。



1

WordPressコミュニティで使用されているScatterというすばらしいツールを共有したいと思います

Git WordPressプラグインと少しの正気散布

これにより、ユーザーは自分のGitリポジトリをwordpress.org SVNに自動的に送信できるようになります。理論的には、このコードは任意のSVNリポジトリに適用できます。


リンクは事実上壊れているようです(「evansolomon.meのサーバーの応答に時間がかかりすぎています。」)。
Peter Mortensen

1

私は最近、いくつかのGitリポジトリをSVNに移行する必要があり、見つけたすべてのソリューションを試した後、最終的に機能したのはMercurial(はい、3つ目の VCS を使用)でした。このガイドを使用し、私は次のプロセスを思いつきました(Linuxでは、基本的な考え方はWindowsでも機能するはずです)。

  1. 必要なパッケージ:

    $ sudo apt-get install git subversion mercurial python-subversion
    
  2. Mercurialは、以下をに追加して構成する必要があります~/.hgrc

    [extensions]
    hgext.convert=
    
  3. 一時的な作業ディレクトリをいくつか作成します(移行するリポジトリがいくつかあったので、SVNバージョンとGitバージョンのディレクトリを作成して、それらを別々に保持します)。

    $ mkdir svn
    $ mkdir git
    
  4. 空のローカルSVNリポジトリを作成します。

    $ svnadmin create svn/project
    
  5. 既存のGitリポジトリのクローンを作成します。

    $ git clone server/path/project.git git/project
    
  6. Mercurialにその処理を任せます。

    $ hg convert --dest-type svn git/project svn/project
    
  7. これで、SVNリポジトリには完全なコミット履歴が含まれるはずですが、元のタイムスタンプは含まれません。これが問題でない場合は、次の部分をスキップしてステップ11に進みます。

  8. 少しの作業で、各コミットの日付と時刻を変更できます。私のリポジトリはかなり小さいので、手動で行うことは現実的でした。まず、pre-revprop-changeSVNリポジトリに次の内容のフックを作成し、必要なプロパティを変更できるようにします。

    #!/bin/bash
    exit 0;
    

    このスクリプトは実行可能にする必要があります:

    $ chmod +x svn/project/hooks/pre-revprop-change
    
  9. Mercurialはproject -wc という名前のSVNリポジトリの作業用コピーを作成したので、それに切り替えてコミット時間を編集します。

    $ cd project-wc
    $ svn propedit svn:date --revprop -r 1
    

    正しい日付と時刻を入力し(タイムゾーンに注意してください!)、保存します。「リビジョン1のプロパティsvn:dateに新しい値を設定してください」というメッセージが表示されます。
    次にすすぎ、他のすべてのリビジョンについて繰り返します。

  10. オプションで、コミット履歴をチェックして、すべてが正常に見えることを確認します。

    $ svn log -r 1:HEAD
    

    次に、1つ上のレベルに戻ります。

    $ cd ..
    
  11. リポジトリをダンプします。

    $ svnadmin dump svn/project > project.dump
    
  12. そして、Subversionサーバーにダンプをロードします。できた!

このプロセスはリモートリポジトリ間でも直接機能する可能性がありますが、ローカルリポジトリと連携する方が簡単だと思いました。コミット時間を修正するのは大変な作業でしたが、プロセス全体は、私が見つけた他のどの方法よりもはるかに簡単でした。


1

3つの方法があります:

  1. rebase:他の答えとして

  2. IDをコミット:SVNまず、最初のIDをコミットidとgitのコミット.git /情報/移植片の中に自分をエコー検索:echo "git_id svn_id}" > .git/info/graftsその後、git svn dcommit

  3. すべてのgitコミットをチェックアウトし、ファイルをsvn_repo、svn commitにコピーします

bashデモ: githubデモ

v1.x:リベースを使用してIDをコミット

v2.x:コピーファイルを使用してから、svn commit


0

私の場合、SVNからクリーンなプロジェクトを開始する必要がありました

$ Project> git svn init protocol://path/to/repo -s
$ Project> git svn fetch

すべてのプロジェクトソースを追加...

$ Project> git add .
$ Project> git commit -m "Importing project sources"
$ Project> git svn dcommit

0

私の経験の一部を、受け入れられた回答と共有したいだけです。私はすべての手順を実行しましたが、最後の手順を実行する前はすべて問題ありませんでした。

git svn dcommit

$ git svn dcommit

/usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm行101の置換(s ///)での初期化されていない値$ uの使用。

/usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm行101の連結(。)または文字列での初期化されていない値$ uの使用。refs / remotes / origin / HEAD: ' https://192.168.2.101/ svn / PROJECT_NAME 'が' 'に見つかりません

私はスレッドhttps://github.com/nirvdrum/svn2git/issues/50を見つけ、最後に101行目の次のファイルに適用したソリューション /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm

交換しました

$u =~ s!^\Q$url\E(/|$)!! or die

if (!$u) {
    $u = $pathname;
} 
else {
       $u =~ s!^\Q$url\E(/|$)!! or die
      "$refname: '$url' not found in '$u'\n";
}

これで問題が解決しました。


-1

Gitで行ったすべてのコミットをSVNリポジトリにコミットしたくない場合はどうしますか?パイプにコミットを選択的に送信したい場合はどうなりますか?まあ、私はより良い解決策を持っています。

私は1つのローカルGitリポジトリーを保持していますが、ここでは、SVNからフェッチしてマージするだけです。そうすれば、SVNと同じ変更をすべて確実に含めることができますが、コミット履歴はSVNから完全に分離されます。

次に、別のフォルダーにある別のSVNローカル作業コピーを保持します。それがSVNへのコミットを行うものであり、そのためにSVNコマンドラインユーティリティを使用するだけです。

ローカルGitリポジトリの状態をSVNにコミットする準備ができたら、ファイルの混乱全体をローカルSVN作業コピーにコピーし、GitではなくSVNを使用してそこからコミットします。

この方法では、リベースはフリーベースのようなものなので、リベースを行う必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.