Mercurial: Branch specific changes keep coming back after dummy merge

前端 未结 1 2071
不知归路
不知归路 2021-02-10 04:17

I have a mercurial repository with two permanent branches, default and UAT. Every once in a while, we deploy (promote) a new version of our application to the UAT environment an

相关标签:
1条回答
  • 2021-02-10 04:40

    I believe the problem is similar to the problem in this question: merging doesn't work the way you think it works. Merging is only a question of comparing file-states, it's not a matter of applying changes from one branch onto another.

    Your starting point is a history like this:

    UAT:      ... x --- y --- z
                               \
    default:  ..... a --- b --- c
    

    where x and y contain the config settings for UAT and b is the dummy merge with no config settings. So the files in b look like they did in a — they were dummy merged.

    If you now make a new change on default that you want to promote to UAT, you'll work with:

    UAT:      ... x --- y 
                         \
    default:  ..... a --- b --- c
    

    The merge is between y and c. It's a degenerate merge where the common ancestor is y itself. This means that all changes between b and c will "win" in the three-way merge. The table for how hunks are merged in a three-way merge is:

    ancestor  local  other -> merge
    old       old    old      old (nobody changed the hunk)
    old       old    new      new (they changed the hunk)
    old       new    old      new (you changed the hunk)
    old       new    new      new (hunk was cherry picked onto both branches)
    old       foo    bar      <!> (conflict, both changed hunk but differently)
    

    Note that the merge result doesn't depend on the "direction" of the merge: the table is symmetric with regard to the local and other columns. Here, both ancestor and local is y, and other is c. So the table becomes:

    ancestor  local  other -> merge
    old       old    new      new (they changed the hunk)
    

    You can see that the merge result always contains the new change that was made in c.

    It's not important that the merge was degenerate. Assuming you have a new commit on UAT and that this commit doesn't touch the config strings, then you'll get the same behavior when you merge (in either direction, merges are symmetric).

    The normal solution to this problem is to externalize the config strings. Put them somewhere outside of version control — environment variables, an unversioned config file, etc. If you can, then put a config file under version control as a template. You then create an unversioned config file for the UAT branch that includes the version controlled config file. You override settings as needed in this unversioned config file.

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