合并简单的上游更改时,Git子树合并报告会发生冲突

时间:2013-04-04 23:54:58

标签: git git-merge git-subtree

我开始在git 1.8.2中学习子树合并。我创建了一个简单的示例来测试对迁移到主项目的第三方仓库的更改。

我正在关注6.7 Git Tools - Subtree Merging示例。

'sub'项目作为'main'项目的子目录包含在内。

在我对'sub'项目进行更改后,当我尝试将更改合并到'main'项目时,git会报告冲突。

测试摘要

  1. 为项目'main'和'sub'(sub而不是rack)创建了repos
  2. 将远程命名的sub_remote添加到引用sub
  3. 的main
  4. 使用sub_branch跟踪sub_remote
  5. 在“子”项目中的文件中更改并提交一行
  6. 将更改从sub更改为main / sub_branch
  7. 将main / sub_branch合并到main / master。
  8. 合并因冲突而失败。 Merge对要保留的更改行的版本感到困惑。

    <<<<<<< HEAD
    main
    =======
    main upstream change
    >>>>>>> sub_branch
    main.git
    sub
    sub.git
    tm
    

    完成测试脚本

    #!/bin/sh
    
    # initialize empty repos
    for i in main sub
    do
      rm -rf $i{,.git}
      mkdir $i.git
      cd $i.git;
      git --bare init;
      cd ..;
      git clone $i.git
      cd $i
      echo $i > readme.md
      git add readme.md
      git commit -a -m "added readme.md"
      git push origin master
      cd ..
    done
    
    # add data to sub
    ls > sub/data
    cd sub
    git add data
    git commit -m "Added data"
    git push origin master
    cd ..
    
    # add sub as a sub-tree in main
    cd main
    git remote add sub_remote ../sub.git
    git fetch sub_remote
    git checkout -b sub_branch sub_remote/master
    git checkout master
    git read-tree --prefix=sub/ -u sub_branch
    git commit -m "Added sub"
    git push origin master
    cd ..
    
    # make change to sub
    cd sub
    sed -i -e 's/main$/main upstream change/' data
    git commit -a -m "upstream change made to data"
    git push origin master
    cd ..
    
    # merge sub change to main
    cd main
    git checkout sub_branch
    git pull
    
    #merge sub_branch changes into master
    git checkout master
    git merge -s subtree sub_branch
    cat sub/data
    

2 个答案:

答案 0 :(得分:6)

在这种情况下read-tree正在做的只是在当前树中添加另一棵树的内容。添加此内容就像创建和添加常规文件和目录一样,没有历史记录。所有这些文件都将被视为您创建它们。

当您尝试合并进程失败时,因为它看到sub_branch历史记录创建了data文件,并且目标目录还包含由您创建的不同data文件。

您正在使用的页面缺少使子树正常工作的非常重要的步骤,因此您实际上可以对其进行更新。

在这两个页面中都可以看到正确的示例: https://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html https://help.github.com/articles/working-with-subtree-merge

在您的案例中缺少的是在创建子树时正确链接历史记录:

# create the merge record but not change anything in your tree yet
git merge -s ours --no-commit sub_branch
# bring the changes and place them in the proper subdirectory
git read-tree --prefix=sub/ -u sub_branch

在此之后,您的main存储库将包含sub存储库的历史记录。调用失败的合并现在应该正常工作。调用git log --graph将让您了解如何合并不同的提交。

答案 1 :(得分:0)

问题在于Git 1.8.2.2(2013年3月)仅仅是引入了会影响git merge -s subtree的错误的版本。
Subtree Merging section提到的Tim Swast仍然存在问题,应该与Git 2.19(2018年第三季度)更好地配合。

git merge -s subtree”中的自动树匹配已于5年前中断,此后没有人注意到,现已修复。

请参见commit 2ec4150Jeff King (peff)(2018年8月2日)。
帮助者:René Scharfe (rscharfe)
(由Junio C Hamano -- gitster --commit 60858f3中合并,2018年8月17日)

  

score_trees():修复缺少条目的树上的迭代

     

score_trees()中,我们遍历两棵排序的树,以查找哪些条目缺失或两者之间内容不同。
  因此,如果我们有两棵树包含这些条目:

one   two
---   ---
a     a
b     c
c     d
     

我们希望循环能够完成:

     
      
  • 将“ a”与“ a”进行比较
  •   
  • 将“ b”与“ c”进行比较;因为这些是排序列表,所以我们知道第二棵树没有“ b”
  •   
  • 将“ c”与“ c”进行比较
  •   
  • 将“ d”与列表末尾进行比较;我们知道第一棵树没有“ d”
  •   
     

在有效的d8febde之前(match-trees:使用score_trees()(2013年3月24日,Git 1.8.2.2)简化tree_entry()
  但是在提交之后,即使每次仅处理一侧的条目,我们都会为每次循环迭代错误地增加树指针
  结果,我们最终这样做:

     
      
  • 将“ a”与“ a”进行比较
  •   
  • 将“ b”与“ c”进行比较;我们知道我们没有“ b”,但是我们仍然增加了两个树指针; 目前我们不同步,所有进一步的比较都是错误的
  •   
  • 将“ c”与“ d”进行比较,并错误地认为第二棵树没有“ c”
  •   
  • 退出循环,错误地没有意识到第一棵树没有“ d”
  •   
     

因此,与d8febde中的声明相反,我们确实需要手动使用update_tree_entry(),因为推进树指针取决于条目比较。

     

这意味着我们必须停止使用tree_entry()来访问每个条目,因为它会自动使指针前进。
  相反:

     
      
  • 我们将直接使用tree_desc.size来了解是否还有需要看的东西(这是tree_entry()在幕后所做的事情)
  •   
  • 我们可以直接访问e1的“ e2”字段,而不是对“ entry”和“ tree_desc”进行额外的结构分配。
  •