git-subtree pull merge conflict

后端 未结 1 393
时光取名叫无心
时光取名叫无心 2021-02-04 02:34

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 a         


        
1条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-04 03:28

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

    Status Quo

    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:

    Broken History after git subtree pull.

    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.

    Final solution to my problem

    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.

    0 讨论(0)
提交回复
热议问题