将项目从SVN迁移到Gitlab CE并努力工作流程和历史记录

时间:2018-03-30 14:47:44

标签: git gitlab

以前的SVN工作流程

  • svn cp $ PATH / trunk $ REPO / branches / feature_xxx
  • git checkout $ REPO / branches / feature_xxx
  • 开发人员致力于分支的工作副本,偶尔与主人合并,然后将分支标记为"准备合并"
  • 当功能准备就绪时,所有者做了svn merge --reintegrate $REPO/branches/feature_xxx,运行完整的测试套件,如果一切正常,那么``svn commit -m" merged feature_xxx"
  • 发布时已准备好svn cp $REPO/trunk $REPO/tags/vX.Y.Z并发布该标记。

svn trunk历史看起来很干净:

version 4.5.4
feature_xxx
bugfix_yyy
version 4.5.3
feature_zzz
version 4.5.3
bugfix_aaa

我们不关心内部提交,但如果我们想要,我们可以使用svn log -g将合并提交扩展到其内部提交(有用一两次)。 / p>

现在我们切换到Git和Gitlab,因为它的功能来评论合并请求和差异。但我们正在努力获得相同的清洁工作流程,这或多或少发生了什么:

策略1:尝试合并功能分支(通过git或Gitlab" Merge"按钮)

好的..这很容易!等等WTF是那些污染我主人日志的先前提交。

决议:没办法,这太乱了。

策略2:了解git merge --squash

好的..这就是我们想要的......现在我们有一个很好的历史,但是我们必须从命令行开始,因为Gitlab CE没有'允许它来自GUI(https://gitlab.com/gitlab-org/gitlab-ce/issues/34591)。没什么大不了的,我们是从命令行做的..哦等等,为什么没有Gitlab检测到我们关闭了合并请求..!?这是在之前自动发生的。

因此,我们了解到它无法检测到分支被合并。确定还有另一种方式(例如,使用提交消息关闭)。尚未实施的内容:https://gitlab.com/gitlab-org/gitlab-ce/issues/13268

解决方案:历史记录看起来不错,但我们需要手动关闭合并请求,这样我们就无法跟踪我们关闭的那些"不打算做什么"从"关闭但通过壁球手动合并"。当然必须有更好的方法..

策略3:了解git rebase ..

好的,所以当分支完成后,我们会git rebase origin/master然后git rebase -i XXXXX,其中XXXX是最古老的共同祖先,我们使用消息"实现feature_xxx"来平滑所有提交。然后我们只需通过cmd行或GUI与master合并。

解决方案:现在gitlab会检测哪些合并请求已合并..好。但是,对于长枝而言,变形可能是一个PITA,有时会失去时间,所以当事情变得毛茸茸时,我们只需回到merge --squash。此外,日志并不是那么干净,因为我们为每个分支机构提供了已实现的feature_xxx ,然后合并了feature_xxx 提交..它没有简单合并那么糟糕但仍然是噪音。

结论

所以现在我们正在使用最后一个策略..大部分时间尝试git rebase但是当事情变得毛茸茸时回到git merge --squash。但说实话,我们并不是百分之百满意,SVN的工作流程简洁明了。

我们错过了什么吗?感谢

1 个答案:

答案 0 :(得分:3)

从Subversion迁移到Git并不是一件容易的事,因为Git更强大,更复杂。但这绝对是一个富有成效的举动。这是一组相关的评论/建议/参考:

Atomic提交

  

我们不关心内部提交,但如果我们想要,我们可以使用svn log -g将合并的提交扩展到它的内部提交(有用一两次)。

即使您不希望所有时间都查看构成功能的内部提交,但使用Git时,最佳做法是尽早提交并经常提交#34;。这个想法是让每个提交变小,并实现(或修复)只有一件事。请参阅此博客文章atomic-commits。还有编写好的提交消息的最佳实践",请参阅this articlethat one

我记得在Git中,每个提交都有很多元数据(作者姓名+电子邮件+时间戳;提交者名称+电子邮件+时间戳;以及SHA1签名),与SVN相反,{{1仅在本地执行操作,因此您需要执行git commit将更改发布到远程存储库。所有这些元数据都可以通过GUI工具显示,例如gitk

功能分支

在你提到的3个策略中,第一个肯定是最好的策略:为每个功能创建一个功能分支,然后"合并"他们在主人。但是这个策略有几个变体,我将在下面的工作流程部分详细说明。

  

策略1:尝试合并功能分支(通过git或Gitlab" Merge"按钮)   解决方法:没办法,这太乱了。

了解合并的一个关键概念是fast-forward mergenon fast-forward merge or true merge的概念。

如果两种类型的合并都是可能的,则CLI命令git push将执行快进合并,如果功能分支仅包含一个提交,则可以接受。否则,最好通过执行git checkout master && git merge feature强制执行非快进合并。但是,如果你不使用命令行,而是点击" Merge" GitHub或GitLab的按钮,它将执行非快进合并。

非快进合并(=真正合并)的优点是您的历史看起来像一棵树(与SVN的典型线性历史不同),它允许人们轻松跟踪提交的子集属于该功能。

例如,参见 gitk 的屏幕截图,其中包含可能包含2个分支的主历史记录:
enter image description here

  

好的..这很容易!等等WTF是那些污染我主人日志的先前提交。

这不是一个真正的问题,但仅供参考,git merge --no-ff featuregit log的功能允许隐藏"内部提交"一个此类历史记录中的功能分支(假设功能分支已与gitk模式合并):--first-parent选项。

以下是与--no-ff相同的示例的截图:
enter image description here

工作流

分支和合并在Git中非常强大,因此有很多可能的方法来开发和集成master中的更改。但是,最好在一个开发团队中遵循系统工作流程,两个不同的工作流程非常受欢迎,并且已被证明非常有效:

我只是在主要参考文献中提供了这两个工作流程的链接,但您可以在网上找到许多其他参考资料,例如scripts to facilitate the application of the Git flow

总结两者之间的区别:Git流有两个主要分支gitk --first-parentdevelop,具有发布的特定约定,而GitHub流更简单(没有master分支并且更适应持续交付的情况。

衍合

你在帖子中提到了一些develop命令,所以我猜你熟悉这个命令及其相关含义,但这里只是一个自给自足的备注:

重新定位(git rebase)基本上意味着"在另一个分支上重放当前分支的提交",因此变基是历史重写"的一种形式,并重写提交暗示其SHA1已更改。因此,这里的主要规则是您不应该使用git rebase another-branch来修改已发布的更改

请注意,Git流和GitHub流都使用git push,但不使用git merge

实际上,在推送之前重写一个本地历史记录是好的做法,以确保提交是原子的或具有合理的提交消息等。为了这个目的,可以使用git rebasegit commit --amend

  

所以现在我们正在使用最后一个策略..尝试git rebase大部分时间但是恢复到git merge - 当事情变得毛茸茸的时候。但说实话,我们并不是百分之百满意,SVN的工作流程简洁明了。

你提到的策略2和3确实可以从命令行的角度来保持线性历史记录,但是这样做你实际上是在遵循使用Git的SVN工作流程,而它更常见在Git中拥有非线性历史并利用其功能分支设施...

  

好的..这就是我们想要的......现在我们有一个很好的历史,但是我们必须从命令行开始,因为Gitlab CE没有'从GUI

允许它

实际上我猜GitLab CE并不容易让你这么做,因为它首先被设计为支持Git工作流程(通常意味着进行真正的合并等等)。

额外参考

这是一篇很长的文章,但值得一读,由GitLab撰写,主题为:https://docs.gitlab.com/ee/workflow/gitlab_flow.html

另一个有用的参考是https://git.github.io/git-reference/,它提供了主要Git命令的摘要,包括我在帖子中没有提到的git tag但是使用Git流程非常重要