Fossil Book

Documentation
Login

Forks and branches

Introduction

This chapter will cover forking and branching in Fossil. Forking is where you unintentially create two places to check into a repository. Branching is where you intentially do this because you want to maintain two or more versions of the code in the same repository. We illustrated forking and it's solutions in Section [sub:Complications]. If, instead of fixing (merging) the file then doing the commit, we forced the commit, Fossil would fork the repository.

Forking is something to avoid because it creates two checkin paths for the code. Thus different users will be on different paths and can check in contradictory changes. Branches on the other hand are forks that you desire. These occur when you want to have two different versions of the code base in development at the same time. This was described in [versioning] where you have a production verison of code under maintenance and a development version both served from the same repository. In this case development changes should only be checked into the development branch. Maintanence changes might have to be checked into both.

Instead of using the book repository for these examples we will use a JSON[JSON]parser program that has a number of files and documentation. This will make it simpler to illustrate branching and tagging.

There is a good discussion of these topics on the Fossil Web site http://www.fossil-scm.org/index.html/doc/tip/www/branching.wiki.

Forks, branch and merge

In this case the JSON code has just been placed in Fossil and two developers check out copies to work on. Jim wants to fix a number of compiler warnings that appear and Marilyn wants to fix the documentation. In both cases they proceeed as shown in Chapter [sec:Multiple-Users]. The JSON code has been placed in a distributed location, each of them clones the repository, and opens a working copy of the code.

Marilyn's actions

She looks through the documentation and finds a number of problems and fixes them (the documentation uses LyX and PDF's). When she is satisfied with what she has done, she checks the current version of the documentation in:

Jim's actions

At the same time, Jim gets a working copy of version [6edbaf5fa8] of the code, puts in a ticket [d23bf4bbbb] as shown in Figure [fig:Marilyn's-work]. After fixing the warnings, Jim is done and goes to commit. He does this AFTER Marilyn has done her commit.

551 jsonp> fossil commit -m "[d23bf4bbbb] Remove warnings"

At this point Fossil recognizes that Marilyn has changed the repository (she updated the documentation) but Jim does not have these changes because he checked out an earlier version of the code. Jim says he must get his changes in so he does a FORCE to force fossil to accept the commit.

552 jsonp> fossil{} commit -m "[d23bf4bbbb] Remove warnings" -f

Looking at the timeline Jim sees this:

Not good, there are two Leaf's and Marilyn would commit code to her fork and Jim would be commiting code to his. So Jim must fix this by merging the code. Jim wants to merge versions [b72e96832e] of Marilyn and his [1beab85441].

Fixing the fork

So Jim who's checked out code is from Leaf [1beab85441] does a merge with Marilyn's leaf [b72e96832e] like so:

556 jsonp> fossil merge b72e96832e

As shown the two documentation files are updated, there are no merge conflicts as Jim didn't touch these files and Marilyn didn't touch the code files.

Next Jim does a commit to make this new merged set of files the new trunk. Remember doing the merge shown in Figure [fig:Merge-Operation] just updates your checked out code and does not change the repository till you check it in.

558 jsonp> fossil commit -m "after-merging-in-changes"

When we look at the timeline we have a single leaf for future code commits.

The only other thing remaining is that Marilyn does an Update before proceeding so her checked out code matches the repository.

WhiteBook:jsonp marilyn$ fossil update

Commands used

Merge without fork

In this case I will show how to merge in code changes from multiple users without causing a fork. In this case Marilyn has put in a BSD license text into all the code files while Jim is adding a help function to the code. In this case both of them put in tickets saying what they are doing but acting independently.

Check in attempt

Marilyn finished first and checks in her changes. Jim builds, tests and tries to check in his code and gets:

502 jsonp> make

Update

The next action Jim takes is to do the update but without doing changes, using the -n flag which tells it to just show what's going to happen without making any file changes.

507 jsonp> fossil update -n

This shows some files will be updated, i.e. be replaced by new text from the repository. The main.c file will be merged with the version from the repository. That is text from the repository will be mixed with the text from Jim's modified file. Note that it says MERGE meaning the two sets of text are a disjoint set. This means the merge can all be done by Fossil with no human intervention.

Jim can just do the update for real then commit the merged files to make a new leaf. So now we have Marilyn's and Jim changes combined in the lastest version.

Commands used

– UPDATE Implies file will be replaced by repository file

– MERGE Implies file will be mixed text from repository and check out

Branching

Introduction

We have discussed this before but branching is the intential splitting of the code in the repository into multiple paths. This will usually be done with production code where we have maintenance branch and a development branch. The maintenance branch is in use and would get bug fixes based on experience. The development branch would get those changes if applicable plus be modified to add features.

The JSON code parser has been tested and works so will be released to general use. Also we wish to modify it to add support for UTF-8 characters so it matches the JSON standard. The current version just works with ASCII 7 bit characters which is not standard. We wish to split the code into a VER-1.0 branch which is the current code in use and VER-2.0 branch which will add UTF-8 character support.

Branch the repository

Before proceeding we will make sure we have the current trunk code in our check out.

[Pandora-2:jschimpf/Public/jsonp] jim% fossil status

Seeing that matches the latest leaf in the time line we can proceed to branch the code.

[Pandora-2:jschimpf/Public/jsonp] jim% fossil branch new VER-1.0 trunk -bgcolor 0xFFC0FF

What was just done. We used the Fossil branch command to create two branches VER-1.0 and VER-2.0 and assigned each of them a color. We can see the timeline is now:

Color setup

As you see above the two branches have different colors in the timeline. This was due to the -bgcolor option added when we created each branch. (See Figure [fig:Branch-commands]). But we want this color to appear on subsequent checkins of each of these branches. To make that happen we have to set the options using the UI and picking a particular leaf on the timeline.

Under the Background Color section I have checked Propagate color to descendants so future checkins will have the same color.

Check out the branches

Now the the repository is branched we can check out the two sets of code into different directories. We create jsonp1 and jsonp2 and proceed to open the different branches into them.

[Pandora-2:jschimpf/Public/jsonp1] jim% fossil open ../FOSSIL/jsonp.fossil VER-1.0

Checking out VER-2.0 in the same way

[Pandora-2:jschimpf/Public/jsonp2] jim% fossil open ../FOSSIL/jsonp.fossil VER-2.0

Notice on both of these the tags show which branch we are attached to.

Correcting errors in both

After doing this work I found that the main.c file had a warning about an unused variable. I wanted to correct this in both branches. At this point all the files in both branches are the same so correcting the file in either branch and copying it to the other is possible. I put in a ticket for the change and edit main.c. I copy it to both checkouts for the both branches and then check both in.

[Pandora-2:jschimpf/Public/jsonp1] jim% fossil commit -m "[2795e6c74d] Fix unused variable"

Now the timeline looks like this:

Commands used