web-dev-qa-db-ja.com

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

私はすべての作業をGitで行い、GitHubにプッシュしています。私はソフトウェアとサイトの両方に非常に満足しており、この時点で仕事のやり方を変えたいとは思いません。

私の博士課程のアドバイザーは、すべての学生に、大学でホストされているSVNリポジトリに作業を保管するように依頼しています。既存のSVNリポジトリをGitにプルダウンすることについてのドキュメントやチュートリアルはたくさんありますが、Gitリポジトリを新しいSVNリポジトリにプッシュすることについては何もありません。 git-svnと新しいブランチ、リベース、およびこれらすべてのすばらしい用語の組み合わせでこれを行う方法があるはずだと思いますが、私はGit初心者であり、それらのいずれにも自信を持っていません。

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

SVNにコミットするのは、これが違いを生む場合、私だけです。

381
cflewis

私もこれが必要でしたが、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を実行すると、might競合が発生します。状態が「unmerged」のファイルを追加し、リベースを再開して、これらを解決します。最終的には、完了です。その後、dcommitを使用して、SVNリポジトリに同期します。それで全部です。

リポジトリの同期を保つ

次のコマンドを使用して、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を台無しにした場合

間違ったURLで誤ってgit svn initを実行し、作業のバックアップを取るのに十分でなかった場合(尋ねないでください...)、同じコマンドを再度実行することはできません。ただし、以下を発行することにより、変更を取り消すことができます。

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

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

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

399
troelskn

これがどのように機能したかを示します。

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

.git/configを開き、以下を追加します(fromGitリポジトリの読み取り専用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

注:後でそのフォルダーを破棄します。

29
Alex Rouillard

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"のようなリモートトラッキングブランチを提供します。これは、ローカルブランチを単に "trunk"と呼ぶ場合にあいまいな名前を取得しないため、ニースです。 -sは、標準のtrunk/tags/branchesレイアウトのショートカットです。

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をmasterブランチが基づいている最初のコミットとして表示するはずです。

グラフトを永続的にします。

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

グラフトをドロップします。

rm .git/info/grafts

gitkはmasterの祖先にsvn/trunkを表示する必要があります。

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

git svn rebase

そして今、「git svn dcommit -n」は、トランクにコミットすることを通知するはずです。

git svn dcommit
27
Dardo Sordi

プロジェクトの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、完了です。ただし、コミット日は真剣に混乱します。

8
Bombe

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

Gitプロジェクトがあり、それをSVNに移動する必要がありました。これが、コミット履歴全体を保持する方法です。失われるのは、libSVNがgit svn dcommitを実行するときにローカル時間を設定するため、元のコミット時間だけです。

Howto:

  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リポジトリのmasterブランチから現在のリポジトリに情報を取得します。

    git fetch old-git master
    
  5. Old-git remoteのmasterブランチを、現在のリポジトリ内のoldという新しいブランチにチェックアウトします。

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

    git rebase master
    
  7. マスターブランチに戻ります:

    git checkout master
    

    また、クリーンなコミット履歴があることがわかります。これがSVNにプッシュしたいものです。

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

    git svn dcommit
    

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

7
codingdave

SubGit を使用して、4つのコマンドで非常に短い命令を提案します。詳細については、こちらをご覧ください post .

4
Dmitry Pavlenko

既存の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プロパティを使用する必要がありました。

3
Jay Linski

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

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

2
sth

特定のSVNを使用する必要がなく、GitHubを使用している場合は、SVNコネクタを使用できます。

詳細はこちら:SubversionとGitHubでのコラボレーション

1
elMarioFredo

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

Git WordPressプラグインと少しの健全性の分散

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

1
r109

最近、いくつかのGitリポジトリをSVNに移行する必要がありました。すべての解決策を試した後、最終的に機能したのは Mercurial (はい、thirdVCS)。 このガイド を使用して、次のプロセスを思い付きました(Linuxでは基本的な考え方はWindowsでも機能するはずです)。

  1. 必要なパッケージ:

    $ Sudo apt-get install git Subversion Mercurial python-Subversion
    
  2. 以下を~/.hgrcに追加してMercurialを設定する必要があります。

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

    #!/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サーバーにダンプをロードします。できた!

このプロセスはおそらくリモートリポジトリ間でも直接機能しますが、ローカルリポジトリで作業する方が簡単だと感じました。コミット時間を修正するのは大変な作業でしたが、全体としては、私が見つけた他のどの方法よりもずっと簡単なプロセスでした。

0
Indrek

動作したさらに別のシーケンス(各ステップにいくつかのコメント付き):

  1. git-svnおよびSubversionツールキットをインストールします。

    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 "gitリポジトリプレースホルダーの作成"

これは、パスの末尾の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
    
0
Oleg Kokorin

新しいSVNリポジトリを作成できます。 Gitプロジェクトをエクスポートします(.gitファイルをフラッシュします)。 SVNリポジトリに追加します(これまでGitで行っていたものでリポジトリを初期化します)。次に、新しいGitプロジェクトでSVNリポジトリをインポートする手順を使用します。

ただし、これにより以前のGit履歴が失われます。

0
Vasil

3つの方法があります:

  1. rebase:その他の回答として

  2. コミットID:svnの最初のコミットIDとgitの最初のコミットIDを見つけ、それらを.git/info/grafts:echo "git_id svn_id}" > .git/info/graftsにエコーしてからgit svn dcommit

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

bashデモ: github demo

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

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

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/5 そして最後に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";
}

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

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
dangt85