Announcement

Collapse
No announcement yet.

Merging a branch back to the trunk

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Merging a branch back to the trunk

    Here is the scenario:

    A create a branch from a trunk
    I then add a file to the trunk
    I merge this revision to the branch
    I merge all branch revisions back to the trunk

    And I get a tree conflict with the file that was added.

    I believe this should not happen, or I am missing something ?
    (the same process with a change to a file instead of a new file correctly merges back without any conflict, in fact it properly ignores the changes since they've are actually originating from the trunk)

    Thanks

    Blaise

  • #2
    You shouldn't merge changes from the branch to the trunk if they are already in the trunk. The proper way to merge a branch back into trunk is to perform a re-integration merge with the svn merge --reintegrate command

    For example, let's create a repository with the standard trunk and branches directories:

    Code:
    [mbooth@boothbox ~]$ svnadmin create test_repo
    [mbooth@boothbox ~]$ svn mkdir file:///home/mbooth/test_repo/trunk -m "create trunk"
    Committed revision 1.
    [mbooth@boothbox ~]$ svn mkdir file:///home/mbooth/test_repo/branches -m "create branches"
    Committed revision 2.
    Check out the trunk and add a file to play with:

    Code:
    [mbooth@boothbox ~]$ svn co file:///home/mbooth/test_repo/trunk wc
    Checked out revision 2.
    [mbooth@boothbox ~]$ cd wc/
    [mbooth@boothbox wc]$ echo "test file" > file.txt
    [mbooth@boothbox wc]$ svn add file.txt
    A         file.txt
    [mbooth@boothbox wc]$ svn ci -m "added a file"
    Adding         file.txt
    Transmitting file data .
    Committed revision 3.
    Create a branch to play with:

    Code:
    [mbooth@boothbox wc]$ svn copy file:///home/mbooth/test_repo/trunk file:///home/mbooth/test_repo/branches/branch_A -m "create branch"
    Committed revision 4.
    Now we are ready to try your situation. Let's add another file to the trunk and modify the existing file in separate commits, so we have two example revisions to merge into the branch:

    Code:
    [mbooth@boothbox wc]$ echo "another file on the trunk" > file2.txt
    [mbooth@boothbox wc]$ svn add file2.txt 
    A         file2.txt
    [mbooth@boothbox wc]$ svn ci -m "added a second file"
    Adding         file2.txt
    Transmitting file data .
    Committed revision 5.
    [mbooth@boothbox wc]$ echo "extra text in the old file" >> file.txt
    [mbooth@boothbox wc]$ svn ci -m "edited the first file"
    Sending        file.txt
    Transmitting file data .
    Committed revision 6.
    So revision 5 added a file and revision 6 modified a file. Now we need to to merge these changes into the branch in order to keep our branch up to date. Let's switch to the branch and merge all changes made to the trunk since we created the branch:

    Code:
    [mbooth@boothbox wc]$ svn switch file:///home/mbooth/test_repo/branches/branch_A
    D    file2.txt
    U    file.txt
    Updated to revision 6.
    [mbooth@boothbox wc]$ svn merge file:///home/mbooth/test_repo/trunk@HEAD
    --- Merging r4 through r6 into '.':
    A    file2.txt
    U    file.txt
    [mbooth@boothbox wc]$ svn ci -m "update the branch to latest from the trunk"
    Sending        .
    Sending        file.txt
    Adding         file2.txt
    Transmitting file data .
    Committed revision 7.
    So revision 7 on the branch contains the same changes as revisions 5 and 6 on the trunk. You might be able to see at this point that you obviously do not want revision 7 being applied to the trunk because the same changes appear in revisions 5 and 6. This is where the re-integrate merge comes in, because it reads the merge-info properties to cleverly know which revisions don't need to applied to the trunk. Let's switch back to the trunk and give that a try:

    Code:
    [mbooth@boothbox wc]$ svn switch file:///home/mbooth/test_repo/trunk
     U   .
    Updated to revision 7.
    [mbooth@boothbox wc]$ svn merge --reintegrate file:///home/mbooth/test_repo/branches/branch_A@HEAD
    [mbooth@boothbox wc]$ svn status
     M      .
    No tree conflicts! In fact, it initially appears as it nothing happened at all because there was no output, but looking at the status shows that some properties changed. The re-integrate merge has merely marked the trunk as containing all the revisions the branch contains for the benefit of future merges and re-integrations:

    Code:
    [mbooth@boothbox wc]$ svn propget svn:mergeinfo .
    /branches/branch_A:4-7
    [mbooth@boothbox wc]$ svn ci -m "re-integrate branch"
    Sending        .
    Committed revision 8.
    If there had been some changes on the branch that were not in the trunk then the svn merge --reintegrate command would have merged them in, again without conflict.

    Sorry for the long reply. Hope this helps.

    Comment


    • #3
      First, thanks for taking the time to reply with such a detailed response.

      Re-integrating, as far as I understand, works well with feature branches, where the branch is kept in sync with the trunk at regular intervals. Moreover, I think that _all_ revisions from the trunk need to have been merged to the branch before we can re-integrate it.

      The problem I'm having is with release branches, where the branch is made, and then only _some_ changes from the trunk are ported to the branch, while some other fixes are made directly in the branch.
      What I want to make sure, however, is that all fixes that are made in the branch are properly ported to the trunk, that's why I want to merge all revisions of the branch back to the trunk, and I expected svn to be smart enough to ignore both the changes that have already been merged back to the trunk or the changes that come from the trunk.

      Does it make sense ?

      Thanks

      Blaise

      Comment


      • #4
        Ok so let's say we make a trunk-only change and a branch only change:

        Code:
        [mbooth@boothbox wc]$ svn switch file:///home/mbooth/test_repo/trunk
        At revision 8.
        [mbooth@boothbox wc]$ echo "trunk only fix" > file2.txt 
        [mbooth@boothbox wc]$ svn ci -m "trunk only fix"
        Sending        file2.txt
        Transmitting file data .
        Committed revision 9.
        [mbooth@boothbox wc]$ svn switch file:///home/mbooth/test_repo/branches/branch_A
        U    file2.txt
         U   .
        Updated to revision 9.
        [mbooth@boothbox wc]$ echo "branch only fix" >> file.txt 
        [mbooth@boothbox wc]$ svn ci -m "branch only fix"
        Sending        file.txt
        Transmitting file data .
        Committed revision 10.
        We can see which changes have been made to the branch that don't exist in the trunk by using the mergeinfo command:

        Code:
        [mbooth@boothbox wc]$ svn switch file:///home/mbooth/test_repo/trunk
        U    file.txt
        U    file2.txt
         U   .
        Updated to revision 10.
        [mbooth@boothbox wc]$ svn mergeinfo --show-revs eligible file:///home/mbooth/test_repo/branches/branch_A@HEAD
        r10
        Does that help? Then you can cherry pick those revisions with a normal merge command.

        Comment

        Working...
        X