我的git repo正在追踪一个SVN回购。我的一个git分支,我们称之为'latest_tag',指向源代码,因为它是最新的SVN标记。创建新的SVN标记时,我想合并'latest_tag'中的更改。当我尝试这样做时,git抱怨合并冲突,好像它不了解SVN历史。
SVN回购正在使用标准结构。
trunk/ tags/ - v1 branches/
我用通常的方式创建了我的git repo。
git svn clone --stdlayout url_to_svn_repo git_repo
我为每个SVN标签和'latest_tag'分支创建了git分支。
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 )
修改 我确认git似乎对两个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
答案 0 :(得分: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标记历史记录,并且不再存在合并冲突。
以下是与初始问题一起提供的最小脚本的“git-friendly”版本(即在标记创建之前使用svn update
)。
# 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 )