0

私の git リポジトリは SVN リポジトリを追跡しています。私の git ブランチの 1 つは、'latest_tag' と呼びましょう。これは、最新の SVN タグにあるソース コードを指しています。新しい SVN タグが作成されたら、'latest_tag' の変更をマージしたいと考えています。これを行おうとすると、git は、まるで SVN の履歴を理解していないかのように、マージの競合について不平を言います。

SVN リポジトリは標準構造を使用しています。

トランク/
タグ/
 - v1
支店/

通常の方法で git リポジトリを作成しました。

git svn clone --stdlayout url_to_svn_repo git_repo

SVN タグごとに git ブランチと、「latest_tag」ブランチを作成しました。

git branch v1 tags/v1
git branch latest_tag v1

新しいタグが SVN リポジトリ (v2 など) に追加されると、それを git リポジトリにインポートできます。

git svn fetch
git branch v2 tags/v2

しかし、'latest_tag' ブランチを v1 から v2 に早送りしようとすると、エラーが発生します。

$ git checkout latest_tag
$ git merge v2
Auto-merging source.py
CONFLICT (add/add): Merge conflict in source.py
Automatic merge failed; fix conflicts and then commit the result.

競合を見ると、git は v1 と v2 の間のすべての変更を無関係と見なしているように見えますが、それらには共通の歴史があります。

問題を再現する最小限のスクリプトを次に示します。

# Create the svn repo and its first tag.
svnadmin create svn_repo/
svn checkout "file:///${PWD}/svn_repo/" svn_working_copy
( cd svn_working_copy ; mkdir -p trunk tags branches ; svn add * ; svn commit -m 'Initialize SVN repo' ; cd trunk ; echo "print 'Hello v1'" >source.py ; svn add * ; svn commit -m 'Development for v1' ; cd .. ; svn cp trunk/ tags/v1 ; svn commit -m 'Tag v1' ; sed --in-place 's/v1/v2/' trunk/* ; svn commit -m 'Development for v2' ; )

# Create a git repo from the svn repo.
git svn clone --stdlayout "file://${PWD}/svn_repo/" git_repo
( cd git_repo ; git branch v1 tags/v1 ; git branch latest_tag v1 )

# Create tag v2 in svn.
( cd svn_working_copy ; svn cp trunk/ tags/v2 ; svn commit -m 'Tag v2' )

# Merge or rebase 'latest_tag' git branch on svn tag v2.
( cd git_repo ; git svn fetch ; git branch v2 tags/v2 ; git checkout latest_tag ; git merge v2 )

EDIT git は、2 つの SVN タグ間の共通の歴史を認識していないようです。

$ git log --oneline master
bd050cd Development for v2
373f808 Development for v1
3b92703 Initialize SVN repo
$ git log --oneline remotes/tags/v1
31f9fff Tag v1
3b92703 Initialize SVN repo
$ git log --oneline remotes/tags/v2
b717759 Tag v2
3b92703 Initialize SVN repo

git が SVN の履歴を理解していれば、これを出力します。

$ git log --oneline remotes/tags/v1
31f9fff Tag v1
373f808 Development for v1
3b92703 Initialize SVN repo
$ git log --oneline remotes/tags/v2
b717759 Tag v2
bd050cd Development for v2
373f808 Development for v1
3b92703 Initialize SVN repo
4

1 に答える 1

1

git が svn の履歴を認識していないように見える理由がわかりました。答えは、svn タグの作成方法によって異なります。

svn 履歴を見ると、svn タグは、特定のリビジョンのスナップショットとして作成されるのではなく、さまざまなリビジョンからのファイルの構成として作成されたことがわかりました。

$ svn log -v
------------------------------------------------------------------------
r3 | lacton | 2013-07-27 18:15:20 | 1 line
Changed paths:
   A /tags/v1 (from /trunk:1)
   A /tags/v1/source.py (from /trunk/source.py:2)

Tag v1
------------------------------------------------------------------------

svn はこれで完全に満足しているように見えますが、git-svn はこれで混乱します。

svn updateタグの作成を行う前に を追加すると、この問題が修正されます。

$ svn up
At revision 2.
$ svn cp trunk/ tags/v1
A         tags/v1
$ svn commit -m 'Tag v1'
Adding         tags/v1

Committed revision 3
$ svn up
At revision 3.
$ svn log -v -r HEAD
------------------------------------------------------------------------
r3 | lacton | 2013-07-27 18:20:26 | 1 line
Changed paths:
   A /tags/v1 (from /trunk:2)

Tag v1
------------------------------------------------------------------------

この修正により、git-svn は svn タグの履歴を正しく解釈し、マージの競合はなくなりました。

svn updateこれは、最初の質問で提供された最小限のスクリプトの「git に適した」バージョン (つまり、タグ作成前のもの) です。

# Create the svn repo and its first tag.
svnadmin create svn_repo/
svn checkout "file:///${PWD}/svn_repo/" svn_working_copy
( cd svn_working_copy ; mkdir -p trunk tags branches ; svn add * ; svn commit -m 'Initialize SVN repo' ; cd trunk ; echo "print 'Hello v1'" >source.py ; svn add * ; svn commit -m 'Development for v1' ; cd .. ; svn up ; svn cp trunk/ tags/v1 ; svn commit -m 'Tag v1' ; sed --in-place 's/v1/v2/' trunk/* ; svn commit -m 'Development for v2' ; )

# Create a git repo from the svn repo.
git svn clone --stdlayout "file://${PWD}/svn_repo/" git_repo
( cd git_repo ; git branch v1 tags/v1 ; git branch latest_tag v1 )

# Create tag v2 in svn.
( cd svn_working_copy ; svn up ; svn cp trunk/ tags/v2 ; svn commit -m 'Tag v2' )

# Merge or rebase 'latest_tag' git branch on svn tag v2.
( cd git_repo ; git svn fetch ; git branch v2 tags/v2 ; git checkout latest_tag ; git merge v2 )
于 2013-07-28T11:34:56.500 に答える