git-subtree拉合并冲突 [英] git-subtree pull merge conflict

查看:547
本文介绍了git-subtree拉合并冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我使用git-subtree在repoA的子目录中有各种repoB分支,就像这样

  git clone repoA 
cd repoA
//一些提交到repoA这里
git subtree add --prefix = src / dirA repoB branchA
  git subtree push  - 前缀= src / dirA repoB branchA 

过了一段时间,我提交了一些repoB / branchA从另一个repoC ,其中branchA也是使用git-subtree添加的。



现在,我尝试

  git subtree pull --prefix = src / dirA repoB branchA 

然而,因没有明显的原因而导致合并冲突。这些变化很简单,根本不会发生冲突 - 就像patch所证实的那样。

我不确定如何解决这个错误。我已经找到了两个四个处理相同/类似问题的其他线程:


  1. git-subtree拉动并发症

  2. git subtree pull -P whatever< repo> < REF>始终合并冲突

  3. 从中央回购中拉动git-subtree冲突


我不确定这是否与不同的SHA-1有关,因为我没有重定义我的提交,也没有对它们进行编辑;链接1至3.



我的问题更像链接4,其中git奇迹般地无法进行简单的合并。然而,链接3谈到了子树合并策略,特别是git-subtree,所以我不确定这是否适用于我的情况。



情况虽然看起来是相同的:

 <<<<<<<<<<<<<<<<<<<<<<<<<¥¥¥ HEAD 
=======
//从commit提交我尝试从repoB / branchA中提取
>>>>>>> {从commit提交SHA-1我尝试从repoB / branchA中提取}

所以我注意到BASE在三向合并窗口(kdiff3)中显然是错误的。但是,如果是这样的话,为什么git不会尝试应用自基础之后的所有早期提交?发行

  git log --oneline 

在合并失败之后但在合并/尝试合并之前,在违规提交之前显示没有重复的提交。
显示为BASE的文件的版本是我第一次发布时的文件

  git subtree add --prefix = src / dirA repoB branchA 

在repoA中。

那是怎么回事?这似乎是相关的,由于某种原因,git子树无法找到我的提交,但它不会尝试将提交从BASE应用到HEAD〜1,而只是我实际上缺少的提交,HEAD。



我怎样才能解决这个错误,而无需破坏版本库的历史记录?为什么不能git拉这个简单的提交,而是认为这是一个合并冲突?



任何洞察力将不胜感激。

解决方案

好的,所以我想通了。这是一个双管齐下的问题。首先,我的树看起来像这样:



我在我的树中提交了一个触及 src / dirA 的提交,但尚未推送 repoB / branchA 已经移动了。



我发现 git subtree pull 不会找到正确的基础,因为它正在寻找一个共同的祖先,因此它在我最后一次合并树时使用了版本,即当我调用<$ c $现在,为了解决共同的祖先问题,需要 git subtree split git subtree add --rejoin ,它执行敷衍合并,所以git再次找到正确的基础,即在从 repoA 推送到 repoB / branchA



然而,正如你在我的例子中看到的那样,一个 git subtree split - 重新加入然后是 git子树拉不能解决我的问题:





由于 git subtree split 会创建一个触及 src / dirA ,无论它们是否被推动,SHA-1总和都是分歧的。出于演示目的,我将合成历史记录拆分为自己的分支 split

git子树在 git subtree split --rejoin 之后,拉当然会成功。然而,下一个 git子树push 将会失败,因为 repoB 和合成树的历史在完成之后完全不同。

因此,我必须在违规的非推送提交之前回去,并将更改从那里拖到我的分支中。这很复杂,因为 git子树拉经由<$> git子树拆分--rejoin 仍然是必需的c $ c> git merge 仍然无法自行找出正确的基础。





所以我现在解决的方式我的问题是直接在违规的非推送 src / dirA 提交之前检出提交。然后我做了一个 git subtree split --rejoin ,后面跟着一个 git子树拉。这当然会在我的主树中添加两个合并,我无法弄清楚如何压缩到一个合并中,并且从我在源代码中读到的内容看来,似乎并没有解决这个问题的简单方法。



在成功完成 git子树拉之后,我将其余的提交从我的 master 分支到 master_fix 。现在SHA-1总共匹配 repoA / master_fix repoB / branchA 共享历史记录。



这当然有一个通常的缺点:如果有人正在处理 master ,他们的历史将被 git branch -m master_fix master


So I used git-subtree to have various branches of repoB in sub-directories of repoA, like so

git clone repoA
cd repoA
// some commits to repoA here
git subtree add --prefix=src/dirA repoB branchA

I did a few commits in repoA using

git subtree push --prefix=src/dirA repoB branchA

Some time later, I committed something to repoB/branchA from another repoC, where branchA was added using git-subtree, too.

Now, I try

git subtree pull --prefix=src/dirA repoB branchA

However, I'm getting a merge conflict for no apparent reason. The changes are simple and don't conflict at all -- as confirmed by patch.

I'm unsure how to fix this error. I already found two four other threads that deal with the same/similar issue:

  1. git-subtree pull complications
  2. git subtree pull -P whatever <repo> <ref> always merge conflict
  3. git-subtree conflict when pulling from central repo
  4. Git Subtree Merging reports conflict when merging a simple upstream change (this one is about subtree merge strategy though, see below)

I'm not sure this is related to different SHA-1s as I did not rebase my commits nor did I edit them; links 1 thru 3.

My problem is more like link 4, where git magically fails to do a simple merge. However, link 3 talks about the subtree merge strategy, not git-subtree in particular, so I'm not sure if this is applicable at all in my situation.

Situation looks to be the same though:

<<<<<<< HEAD
=======
// changes from commit I try to pull from repoB/branchA
>>>>>>> {commit SHA-1 from commit I try to pull from repoB/branchA}

So I noticed that BASE is blatantly wrong in a three-way merge window (kdiff3). However, if that's the case, why doesn't git try to apply all earlier commits since base? Issuing

git log --oneline

after the failed merge but before merging/trying to merge shows no duplicated commits prior to the offending commit. The version of the file that's shown as BASE is the file as it was when I first issued

git subtree add --prefix=src/dirA repoB branchA

inside repoA.

So what's going on? It seems to be related that git subtree cannot find my commits for some reason, yet it does not try to apply the commit from BASE to HEAD~1, but only the commit I'm actually missing, HEAD.

How can I fix this error without screwing up either repository's history? Why can't git pull this simple commit and instead thinks it's a merge conflict?

Any insight will be much appreciated.

解决方案

Ok, so I figured this out. It was a two-pronged problem. First of all, my tree actually looked like this:

I had a commit in my tree that touched src/dirA, but was not yet pushed when repoB/branchA had already moved on.

I discovered that git subtree pull would not find the right base, because it is looking for a common ancestor, hence it used the version when I had last merged the trees, i.e. when I called git subtree add initially.

Now, to resolve the common ancestor problem, one has to git subtree split --rejoin, which performs a perfunctory merge, so git finds the right base again, i.e. after the commits pushed from repoA to repoB/branchA.

However, as you can see in my case, a git subtree split --rejoin followed by a git subtree pull does not solve my problems:

Due to the fact that git subtree split creates a synthetic history of all commit that touch src/dirA irrespective of the fact whether or not they were pushed, the SHA-1 sums diverge. I split the synthetic history into its own branch split for demonstration purposes.

git subtree pull will of course succeed after git subtree split --rejoin. However, the next git subtree push will fail, because the histories of repoB and the synthetic tree are completely different after that.

Therefore, I had to go back before the offending non-pushed commit and pull the changes into my branch from there. This is complicated by the fact that git subtree split --rejoin is still necessary, because git subtree pull via git merge can still not figure out the correct base on its own.

So the way I currently resolved my issue was by checking out the commit directly before the offending non-pushed src/dirA commit. Then I did a git subtree split --rejoin followed by a git subtree pull. This of course adds two merges into my main tree, which I could not figure out how to squash into one merge, and from what I read in source code, there doesn't seem to be an easy solution to that problem.

After the successful git subtree pull, I rebased the remaining commits from my master branch onto master_fix. Now the SHA-1 sums match throughout the shared history of repoA/master_fix and repoB/branchA.

This of course has the usual drawbacks of a rebase: if somebody else was working on master, their history will be ruined by git branch -m master_fix master.

这篇关于git-subtree拉合并冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆