Changes between Initial Version and Version 7 of Ticket #138

01/11/09 05:39:27 (8 years ago)

Replying to coke:

For those of us who aren't git users, seeing an example of how branches will be both sharable (as they are now) and more easily mergable would definitely help sway the undecideds. (Presuming our new hosting overlords can even accomodate this request.)

Sure, examples are easy. (Note that I'm not actually a git expert, so there may be better examples than the ones I explain here.)

Take for example jq's Language::Befunge project, . In this project are several long-lived branches, one per contributor. (This isn't necessarily the recommended form of branch usage, the organization is more or less arbitrary.) The "master" branch is the trunk, for all intents and purposes.

When changes from one branch are merged into another, their history is preserved. This happens more literally than it does in svn; a branch merge in svn results in a single commit, whereas in git, the full list of changes from one branch are copied to the target branch, directly. See for example the latest changes in my branch,;h=refs/heads/mark-stable . Those changes were merged back into master (trunk) back in july, as you can see most of the way down the page here:;h=refs/heads/master .

Taken by itself, this semantic allows fine-grained management of conflicts. If a conflict occurs, it only affects a single commit, and thus it is easier (during manual review) to see the scope and intent of the commit.

Next, when you resolve a conflict, the changes you make become a (specially marked) commit of their own. That means, you can keep your branch up to date with respect to trunk, and in fact by doing so, you are guaranteeing that the changes in your branch will apply cleanly to trunk. If (by comparison) you do this with svn, you are in fact making merging *harder* later on, by making the branch topology complex (non-linear).

In an earlier post, I alluded vaguely to the bcanno branch. It makes a good example, so I will detail here. The branch was created in r33279, had various local changes applied, had the meantime changes from trunk merged into it (r34985), spent 3 subsequent commits cleaning up the fallout from that merge (r34986, r34987, r34988), made some more local changes, merged trunk changes into the branch again (r35024), made the final touches, and then had trunk changes synced in one final time in preparation for merging it back to trunk (r35048). Jonathan mentioned having some problems with that, and this was the state I found the branch in when I volunteered to do the merge.

So I innocently made a fresh trunk checkout and tried to do "svn merge". I had a sufficiently recent version of svn, so my syntax was accepted. As the various conflicts came up, I elected to (p)ostpone them. so they would show up in "svn st" as C and let me fix them up later. It chewed on it for a while, and eventually kicked out an obscure error message and exited. (I can't be more specific because I can't reproduce this any more, as the bcanno branch has been removed.)

With git, this simply wouldn't have happened. This is because Jonathan had already *done* the merge (r35048). When merging bcanno into trunk, git would have realized this fact (from the existence of the specially marked merge commit) and just made trunk's commit history identical to that of bcanno's, so no more actual "merging" was required.

Now, svn's branch merging support is slowly improving. But it didn't work in this case, so I was forced to resort to extreme measures (take a checkout of r35048 of the bcanno branch and trunk, remove all the ".svn" files from bcanno, "cp -a" all of the files into the trunk branch, then "svn update", clean up any additional conflicts and commit it) which didn't preserve change histories, and for me, removes a lot of confidence in the tool.

For the curious, I think svn's problematic behavior could be reproduced by recreating the same branch tree topology.



  • Ticket #138 – description

    initial v7