将具有多个活动分支的SVN存储库转换为GIT

时间:2016-08-09 13:12:08

标签: git svn version-control git-svn git-merge

我试图将我的SVN存储库转换为GIT存储库。 这个问题是,在SVN中有几个活动分支 不同的软件版本并行维护。 所以SVN设置看起来像这样:

SVN ROOT
|- trunk
|- branches
|  |- v1
|  |- v2
|  |- v3
|- tags
|  |- v1
|  |  |- 0
|  |  |- 1
|  |- v2
...

现在我想创建一个GIT存储库,其中包含每个分支的分支 SVN。创建存储库和移植标记根本不是问题。 我正在做一个

git svn init -s --tags=tags/v1 --tags=tags/v2 <REPO_URL>
# modified .git/config to use tags/v1/* for the tags of the different versions
git svn fetch

在此之后,我根据需要获得了分支机构,并且我可以使用

查看不同的软件版本
git checkout -b v1 origin/v1

问题是SVN存储库是旧的,不同的分支都从 trunk 分支出来。但是我的开发需要我修复一个bug v1 ,将其合并到 v2 ,然后 dcommit 将所有内容反馈回SVN。

所以我的问题是什么是获得干净(可合并/可重组)GIT分支的最佳方式?那么工作流程应该如何呢? 我应该为GIT中的每个版本添加一个新分支,让我们说 svn_v1 ,将 v1 重新绑定到此,然后 dcommit 那里?或者什么是将提交返回SVN的最佳方式?

修改

我已经尝试根据合并上游来修改不同的分支(例如,将 v2 重新定位到 v1 trunk v2 )但这搞砸了 我的历史记录,在尝试 dcommit 时,它想要提交我在当前历史记录之上重新提交的所有提交。这会使SVN历史变得混乱,因为这些提交已经在Repo中。

EDIT2:

使问题更加清晰。想象如下历史:

        D--E--F v1  K--L--M v2
       /           /
A--B--C--G--H--I--J--N trunk
   ^
   |
   introduced a bug

由于提交B引入了错误,所有分支v1v2trunk都会受到影响。我的公司的政策现在(在SVN中)在受影响最小的分支(在这种情况下为v1)中解决此问题,然后通过 分支到trunk。 工作流如何在GIT中执行相同的操作,以便在SVN中v1中的提交被标记为合并到v2

2 个答案:

答案 0 :(得分:2)

听起来你想在v1中做你的错误修正,然后在提交两者之前在v2中挑选它。这不是git术语中的合并或rebase操作。如果您要在v1中进行更改,然后将其合并到master,然后将其合并或重新绑定到v2

我承认,在你的描述之后,我不太确定问题出在哪里。这听起来更像是一个工作流问题,然后给我一个git-svn问题?如果你的svn分支很好(即,不是一团糟),那么git init应该以一种你可以像往常一样使用它们的方式转移它们。如果他们已经在svn方面已经退化很多,那么它真的无法“修复”这个混乱。

编辑:回复你的第二次编辑:你描述的内容(在所有分支上分发修补程序/补丁)在git中被称为“cherry-picking”,而不是合并。 git不会(也不需要)跟踪你是否做了樱桃挑选的东西;你只是这样做并完成它。您绝对不希望在您的方案中进行任何合并或重组。

所以,这是你可以做的:

  1. 你的情况

            D--E--F v1  K--L--M v2
           /           /
    A--B--C--G--H--I--J--N trunk
       ^
       |
       introduced a bug
    
  2. 如果这是您的政策,请修复您的错误并提交v1

    git checkout v1
    # fix bug
    git add ; git commit
    # note the commit hash you just created, let's call it a1b2c3d4
    
  3. 分发给其他分支机构

    git checkout v2
    git cherry-pick a1b2c3d4
    
    git checkout trunk
    git cherry-pick a1b2c3d4
    
  4. 新情况

            D--E--F--a1b2c3d4 v1    K--L--M--abcde123 v2
           /                      /
    A--B--C--G--H-------------I--J--N--bca123123 trunk
       ^
       |
       introduced a bug
    
  5. 就是这样。 git cherry-pick将自动获取该单个提交的diff / patch,将其应用于当前的HEAD,并创建新的提交。 (按设计)“后台”没有任何进展,这是一个非常简单的程序。可能会像往常一样发生冲突,您可能需要手动修复,但git会告诉您要做的更多或更少。

    如果您以后继续常规工作,并合并/重新组合这些分支,git不需要知道挑选樱桃。这些东西都在你的文件中,它会看到(或没有看到)文本上的差异,运气好的话一切都会好的。

答案 1 :(得分:0)

好的,我终于设法自己解决了这个问题。 我已经分两步解决了这个问题:首先,由于v1v2的代码库很好(构建和工作,两者都修复了已知的错误),因此我可以使用v1v2。我们在v2中记录了trunk分支到svn分支和gitgit-svn的合并。 现在我可以合并git config svn.pushmergeinfo true 中的分支。然后我在dcommit文档中找到了这段话:

  

config key:svn.pushmergeinfo

     

此选项将导致git-svn尝试在可能的情况下自动填充SVN存储库中的svn:mergeinfo属性。目前,这只能在提交非快进合并时才能完成,其中除第一个之外的所有父级已经被推入SVN。

所以我已启用此配置值

svn

现在,如果发现新的错误,我会将其修复到出现此错误的最低版本,--no-ff将其修复为dcommit,然后将其合并到下一个版本中使用svn选项。如果我现在package vindue; import javax.swing.*; /** * * @author BE56df */ public class Vindue { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here paneler panel = new paneler(); JFrame vindue = new JFrame("NEZ - Evolution Simulator v0.1"); vindue.add(panel); vindue.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); vindue.setResizable(false); vindue.pack(); vindue.setVisible(true); } } package vindue; import java.awt.*; import javax.swing.*; /** * * @author BE56df */ public class paneler extends javax.swing.JPanel { /** * Creates new form paneler */ public paneler() { initComponents(); } public void paintComponent(Graphics g){ super.paintComponent(g); g.drawLine(0, 0, 750, 550); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { EvoPanel = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); jSeparator1 = new javax.swing.JSeparator(); jToggleButton1 = new javax.swing.JToggleButton(); setMaximumSize(new java.awt.Dimension(750, 550)); setMinimumSize(new java.awt.Dimension(750, 550)); setPreferredSize(new java.awt.Dimension(750, 550)); EvoPanel.setBackground(new java.awt.Color(200, 200, 200)); EvoPanel.setMaximumSize(new java.awt.Dimension(550, 550)); EvoPanel.setMinimumSize(new java.awt.Dimension(550, 550)); javax.swing.GroupLayout EvoPanelLayout = new javax.swing.GroupLayout(EvoPanel); EvoPanel.setLayout(EvoPanelLayout); EvoPanelLayout.setHorizontalGroup( EvoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 550, Short.MAX_VALUE) ); EvoPanelLayout.setVerticalGroup( EvoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 550, Short.MAX_VALUE) ); jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N jLabel1.setText("Control panel"); jLabel1.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM); jLabel1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToggleButton1.setText("Auto play"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(EvoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addGap(63, 63, 63) .addComponent(jLabel1) .addGap(0, 58, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 190, Short.MAX_VALUE) .addComponent(jToggleButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(EvoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jToggleButton1)) ); }// </editor-fold> // Variables declaration - do not modify private javax.swing.JPanel EvoPanel; private javax.swing.JLabel jLabel1; private javax.swing.JSeparator jSeparator1; private javax.swing.JToggleButton jToggleButton1; // End of variables declaration } 中的mergeinfos会更新,一切正常。