我现在已经使用git很长一段时间了,主要是git-svn。现在我想说服我的同事从svn切换到git。但不幸的是,前提条件是svn存储库保持相当长的一段时间。所以我搜索了一个解决方案并提出了这本书:
Jon Loeliger的“使用Git进行版本控制”。我买了它,它真的很好,但我不完全理解设置git svn看门人回购的指南。
在第16章中,他描述了一个 有一种情况 Subversion存储库,至少一个 几个想要使用的用户 Git的。他提出了一个单一的 “看门人”git仓库是哪个 颠覆的唯一接口。 在git svn克隆了subversion之后 repo(带--prefix = svn /),全部 然后分支被推到一个裸露的地方 存储库(git push ../svn-bare.git '参/遥控器/ SVN / :参考文献/头/ SVN / ', 和其他git用户被告知克隆 这个回购,现在包含本地 所有svn遥控器的分支。
这部分有效,我想我完全理解它。但我没有得到下一部分:
如果一个克隆裸存储库的开发人员将更改从他的repo推回到裸存储库,然后我在裸存储库中将其提交给svn,那么用户推送的提交由于被替换的提交git而丢失了。 svn创造。还是我错了?这是如何运作的?
这本书说
然后,合并回subversion,in 看门人回购,你做
git checkout svn / trunk(或其他 分支 - 这是检查出来的 分离头作为svn / trunk是一个 远程) git merge --no-ff new-feature git svn dcommit
如何在裸存储库中签出分支?我认为这不起作用
这会导致合并提交 分离头,然后修改 commit(在git-svn-id行之后) 添加)放在真正的svn / trunk上 科。
真正的svn / trunk是什么意思?
分离的提交 头是“比冗余更糟糕。使用 最终还有其他任何东西 导致冲突。所以,别忘了 关于那个提交。如果你还没有放 它首先在一个分支上, 这更容易忘记“(乔恩 Loeliger)。
我有点困惑。有人为创建一个git svn网守回购有更好的解释吗?我搜索过网站和这个网站,但我找不到任何适合我的内容。
在与同事合作时,我已经厌倦了浪费这么多时间与svn分支和合并。
答案 0 :(得分:6)
如何在裸存储库中签出分支?我认为这不起作用
是的确如此:您只需在本地克隆bare repo,在此过程中制作非裸仓库,您可以在此处签出/创建(再次本地)尽可能多的分支想。
需要一个裸仓库作为上游仓库去哪里。 (参见“git push
only for bare repositories?”)
但是为了向它推送任何东西,即其他开发人员将他们在非svn分支中的更改推回到网守仓库,说其他开发人员必须首先克隆该裸仓库,对所有相关修改本地副本,并推回到裸仓库 另外,您可以在裸仓库上设置一些挂钩以验证您的推送:请参阅“Hooks for git-svn”。
然后到dcommit
,看门人还会克隆该网守回购,他/她将从中回复:
svn
'是远程仓库的名称),例如“svn/trunk
”git-svn dcommit
所以回顾一下:
答案 1 :(得分:3)
我试图自动化Jon Loeliger描述的gatekeeper setup并使其正常运行。他开始非常详细地介绍了要执行的步骤,但“合并回Subversion”部分相当简短。我已尝试使用git-svn进行不同的设置,也遵循Thomas Ferris Nicolaisen提供的优秀presentations/examples并使用他的示例项目(带有修改)来测试“网守设置”:
@echo 1. Clone Subversion repo
cd %WDIR%\devs\adm
call git svn clone -s --prefix=svn/ http://localhost/svn-repos/company-repo/websites -- username adm
cd %WDIR%\devs\adm\websites
call git reset --hard svn/trunk
@echo ----------------------------------
@echo 2. Create bare repo
cd %WDIR%\devs\adm
mkdir websites.git
cd websites.git
call git init --bare
@echo ----------------------------------
@echo 3. Populate bare with content from gatekeeper
cd %WDIR%\devs\adm\websites
call git push --all ../websites.git
call git push ../websites.git "refs/remotes/svn/*:refs/heads/svn/*"
@echo ----------------------------------
@echo 4. Setup bare as a remote in gatekeeper and fetch branches
call git remote add bare_repo ../websites.git
call git fetch bare_repo
Jon Loeliger没有描述第4步,但我想这就是他所说的。
当合并回到颠覆时,请执行:
C:\tmp\devs\adm\websites>git fetch bare_repo
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From ../websites
e53fba9..2ac281c svn/trunk -> bare_repo/svn/trunk
现在我们可以按照书中的步骤进行操作:
C:\tmp\devs\adm\websites>git checkout svn/trunk
Note: checking out 'svn/trunk'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at e53fba9... [maven-release-plugin] prepare release kaksi
C:\tmp\devs\adm\websites>git merge --no-ff remotes/bare_repo/svn/trunk
Merge made by the 'recursive' strategy.
0 files changed
create mode 100644 web/howto.txt
create mode 100644 web/readme.txt
C:\tmp\devs\adm\websites>git svn dcommit
Committing to http://localhost/svn-repos/company-repo/websites/trunk ...
A web/howto.txt
A web/readme.txt
Committed r8
A web/readme.txt
A web/howto.txt
r8 = 28da267255ae56022bd4ed3c0f4886da1ac04944 (refs/remotes/svn/trunk)
No changes between current HEAD and refs/remotes/svn/trunk
Resetting to the latest refs/remotes/svn/trunk
我对此设置的问题(我们在本书前面已经提出警告)是历史被压扁了:
C:\tmp\devs\adm\svn\websites>svn log
------------------------------------------------------------------------
r8 | adm | 2012-05-12 23:21:11 +0200 (lø, 12 mai 2012) | 1 line
Merge remote-tracking branch 'remotes/bare_repo/svn/trunk' into HEAD
------------------------------------------------------------------------
现在考虑将这种替代方法合并回subversion:
C:\tmp\devs\adm\websites>git checkout -t svn/trunk
Branch trunk set up to track local ref refs/remotes/svn/trunk.
Switched to a new branch 'trunk'
C:\tmp\devs\adm\websites>git fetch bare_repo
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From ../websites
c188a72..b1b4237 svn/trunk -> bare_repo/svn/trunk
C:\tmp\devs\adm\websites>git rebase remotes/bare_repo/svn/trunk
First, rewinding head to replay your work on top of it...
Fast-forwarded trunk to remotes/bare_repo/svn/trunk.
C:\tmp\devs\adm\websites>git svn reset 2147483647
r7 = c188a72da6df2966e563e9e575b626d5b449400f (refs/remotes/svn/trunk)
C:\tmp\devs\adm\websites>git svn rebase
Current branch trunk is up to date.
C:\tmp\devs\adm\websites>git svn dcommit
Committing to http://localhost/svn-repos/company-repo/websites/trunk ...
A web/howto.txt
A web/readme.txt
Committed r8
A web/readme.txt
A web/howto.txt
r8 = 18b7c7b4693cc8e55098bd716c9259ed5570acf0 (refs/remotes/svn/trunk)
No changes between current HEAD and refs/remotes/svn/trunk
Resetting to the latest refs/remotes/svn/trunk
现在提交历史记录完好无损:
C:\tmp\devs\adm\svn\websites>svn log
------------------------------------------------------------------------
r8 | adm | 2012-05-12 23:51:48 +0200 (lø, 12 mai 2012) | 1 line
'ola added [readme.txt, howto.txt] on svn/trunk'
为了使这个设置工作,我们需要使用'git svn reset'命令,否则dcommit将第二次失败,因为git-svn对当前版本感到困惑,并且落后于(同一版本)就像我们创建裸回购时一样)。这可能是因为我们使用了rebase,这反过来又是在subversion中获得一个漂亮的线性历史所必需的。
最大的问题是:'git svn reset'真的有什么用呢? 在这种情况下,“正向重置”是否合法使用'git svn reset'?
答案 2 :(得分:2)
我认为您不应该将更改推回到裸仓库。我在这里有一个示例设置你可以尝试:
http://blog.tfnico.com/2010/10/gitsvn-5-centralized-git-svn-mirror.html
在我的设置中(我已经使用了3-4个月而没有任何问题),更改应始终“流动”通过SVN存储库。我真的不明白这个看门人技术..