home  |  search  |  contact  
 
     

Advanced Operations


After getting started you can get into more advanced operations.

Resolving Conflicts

A conflict is when two or more people have changed information in different repositories and then try to update. Conflicts need to be resolved before the repositories can be synchronized. In some cases, conflicts that occur during a pull can be auto-merged. In other cases, manual merging must be done. This chapter outlines the manual merge process.

When is a Resolve is Needed?

Upon a pull if there are conflicts that must be auto-merged, the pull will not succeed. The incoming data will be saved in a directory called RESYNC.

Conflicts can occur because:

  • file content changes overlap
  • permissions changes overlap
  • file name changes overlap
  • file flags changes overlap
  • tag changes overlap

When possible, these changes are auto-merged. If BitKeeper could not merge all conflicts, you will have to do a manual resolution.

Resolve

When a pull does not succeed due to conflicts, to resolve those conflicts, run:

bk resolve

You will be prompted for each type of conflict for each file. For each type of conflict there are available actions you can take, to see a list of available actions hit:

enter

For file content conflicts use the file merge tool by hitting:

F

Resolve all the conflicts in the file merge tool and save.

You will be back at the resolver prompt. If there are more files to merge, do those. If there aren't any more files to merge, commit the merges to a changeset by hitting:

C

While it is OK to quit out of resolve without finishing, the repository will be locked and remain locked until you return to resolve and finish up the merge process.

Merging Content Conflicts

In the file merge tool, the upper windows are the files to be merged. The lower left window is the merged file and the lower right window contains helpful hints. Whatever can be auto-merged will be auto-merged and displayed in the merge window. Unmerged conflicts will be indicated in the merge window and also will be indicated by a red bar above the hints window. You may scroll through unresolved conflicts with the "{" and "}" keys, previous unresolved conflict and next unresolved conflict, respectively. Scroll through all conflicts using "[" and "]", previous unresolved conflict and next unresolved conflict, respectively.

Specifying Older Revisions

One of the advantages of BitKeeper is the ability to ``go backward'' to any previous version of a file or release. There are many ways to do this and it's possible to specify a previous version of a file, a changeset, or a tagged release. This section explains how to specify older revisions at all of these levels.

File level

Sometimes it is necessary to resurrect an old version of a file. To do this it is necessary to

  • know the version of the file you want to get - found browsing with revtool
  • Get the file as of that revision

    bk revtool file_name
    bk get -p -r
    rev file_name > file_name.tmp

ChangeSet level

To revert a repository to a state as of a previous changeset, it is necessary to

  • Know the ChangeSet revision - found browsing with revtool
  • Clone the repository as of that ChangeSet

    bk revtool
    bk clone -r
    rev source_repo dest_repo

Tag level

Resurrecting the repository as of the state of a tag is similar to that for ChangeSets in that it is necessary to

  • Know the tag name
  • Clone the repository as of that tag

    bk tags # if needed, this will list all tagged changesets
    bk clone -r
    tag_name source_repo dest_repo

Note that if a repository is tagged by the same name more than once, the most recent instantiation of that tag name will be will be assumed to be the wanted tag.

Tags

A tag is a symbolic marker that provides a way to save the state of a repository as it was at time T and continue development in that repository while maintaining the ability to go back to how it was as of time T if the need arises. One of BitKeeper's strengths is ease of reproducibility, and tags, while not necessary for reproducibility, make it even easier. Tags are useful when saving stages of stability or when releasing beta versions when development is still occurring in the repositories. People tend to find it much easier to identify a release when it has a name that can be used to refer to it.

This chapter will cover why tags are useful, how to create and delete tags, and how to use tags to re-create a tree as of a certain moment in time.

Creating a Tag

A tag may be created at any time. NOTE: Make sure that the repository has no modified or pending files; use bk status to verify. In the following examples, ``Done'' is the name used when tagging the repository. Any name will do, though using a name that holds meaning is recommended, such as Alpha, Beta, 1.0-release, etc.

If the repository is ready to be tagged with the name ``Done'', type:

bk tag Done

If it is discovered that a changeset should have been tagged after more changesets have been added to the repository, the -r option may be used to select the proper changeset. If the rev to tag is unknown, run bk changes to list all ChangeSets with comments, look through this list to find the revision to tag. Once the revision to tag has been found, type:

bk tag -rrev Done

At Commit Time

A tag may be set when committing a changeset using bk commit:

bk commit -SDone

At this time citool does not permit tagging upon commit. This is a bug and will be fixed.

Updating a Tag

A frequent problem is that a changeset will be tagged with "Done" and then it is discovered that it isn't done. The tag may be updated to the later changeset by running the

bk tag Done

command again. If there are multiple tags with the same name, BitKeeper assumes the most recently applied tag is the "real" tag.

When browsing through a repository's history, you may notice two identical tags. To ensure proper reproducibility, tags are never removed, but rather are updated. To see all tagged changesets, type a ``t'' while in the bottom window of revtool. Use the text search window to find multiple instances of a tag.

Revert to a tree as of Tag

It is frequently helpful to look at a repository as of the state of a tag. To recover the repository as of a tag, use:

bk clone -rDone source_repo dest_repo

Branching

Branching is a means for continuing separate development of one body of code in two or more trees. In BitKeeper, this is accomplished by cloning a new repository. This chapter will explain when to create a clone, how to create the branch, or clone, and work flow between clones.

When to Create a Clone

Branching, should be done when development in a tree starts diverging. Suppose, for example, there is a main line repository called stable. When stable reaches a frozen state near release, only proven code that fixes bugs may be incorporated to that tree, but development must be allowed to continue for both the required bug fixes and for development of the next version of the software. The solution is to create three different repositories for work:

  • stable-1.0: The main line repository for the 1.0 release, where only approved bug fixes are incorporated.
  • bugfixes-1.0: The repository for developers to work on bug fixes that will, when approved, be incorporated to the stable-1.0 release.
  • dev-1.1: The repository to continue development that will become a part of the 1.1 release.

Work Flow
It's fairly common for a software project to branch into stable and bug fixes branches, and the flow of work goes only one way -- work flows to new development branches, but does not travel back from new development branches to old trees. The flow of work for the example above is as follows:

  • bugfixes-1.0: Work will be propagated to stable-1.0 and dev-1.1.
  • stable-1.0: Work, if any, will be propagated to dev-1.1. Normally, once a release has gone into a frozen state, development would occur in bugfixes rather than stable, and then only scrutinized code would be propagated to stable.
  • dev-1.1: Work will never back flow to stable-1.0 nor bugfixes-1.0.

How to Enforce Work Flow

Branching is accomplished in BitKeeper by cloning a repository to another repository and using ``levels''. Levels are arbitrary numbers assigned to the repository that are used to control the flow of changesets between repositories.

To enforce the flow of work, the bk level command is used to set the level of a repository. Setting the level of a repository tells BitKeeper whether or not to allow changes into that repository from another repository with a different level. A repository with no level setting defaults to level 1. The level is automatically set when a repository is cloned to the level of the parent repository.

If the level of repository A is lower than the level of repository B, work may flow from A into B, but not from B into A. If the level of repository A is equal to the level of repository B, work may flow in both directions from A to B and B to A.

In the example above, the level for stable-1.0 is N. The stable-1.0 repository was cloned to bugfixes-1.0 which takes on the level of its parent which is N. The level of dev-1.1, however, should be manually set to N+1 after it has been cloned from stable-1.0 to prevent new development work back flowing to stable-1.0 or bugfixes-1.0.

To check the level of a repository:

cd repository
bk level

To set the level of a repository:

cd repository
bk level
num

Branching and Merging

Once the repository levels are set appropriately, to propagate changes, use the the bk pull command. For example, to incorporate work from stable-1.0 to dev-1.1:

cd dev-1.1
bk pull ../stable-1.0

NOTE: It will most likely be necessary to merge files when propagating changes between branches. See the section on Resolving Conflicts.

Revision Ranges

Many commands can take ranges of deltas as an argument. A range is a continuous sequence of deltas, such as 1.1, 1.2, 1.3, and 1.4. Deltas may be specified by their revision number (1.2), or a symbol (alpha1), or a date (99/07/25).

Specifying by Revisions

Some BitKeeper commands have options that allow the user to specify a revision or range of revisions by revision number (generally, the -r option).


To specify most recent revision:	-r+
To specify a single revision:		-r1.10
To specify a range of revisions:	-r1.2..1.5

Specifying by Dates

Some BitKeeper commands have options that allow the user to specify a date, rather than a revision, as the range. Typically, the -c option is that which allows the date to be specified. If there is only one date specified, without a revision, then a very useful form of the date is to specify a recent period of time.


In the last year:       -c-1Y (or -1y)
In the last month:      -c-1M
In the last week:       -c-1W (or -1w)
In the last day:        -c-1D (or -1d)
In the last hour:       -c-1h
In the last minute:     -c-1m
In the last second:     -c-1s
If you leave off the multiplier, 1 is assumed.

Revision and Date

If there are two dates, or there is a date and a revision, then the date format is [+\-]YYMMDDHHMMSS with missing fields either rounded up or rounded down. Rounding is explicit if there is a "+" (rounds up) or a "-" (rounds down) prefix on the date. If there is no prefix, then the rounding is context sensitive. If the date is the first date i.e., the starting point, then the date is rounded down. If it is the second date in the range, then it is rounded up. So 98..98 is the same as 980101000000 .. 981231235959.

Remote repositories

Since BitKeeper is designed as a distributed system, there are multiple ways to exchange data between remote repositories. There is a BitKeeper daemon, bkd, which can be used via rsh, ssh, or as a stand-alone daemon, all described below. It is also possible to send and receive BitKeeper repository information via email, which is useful for people with low bandwidth connections or working from a disconnected laptop.

bkd

The BitKeeper daemon, bkd, is used to get information about a repository from a remote machine. A new instance of the daemon is created each time a remote repository is accessed. It is created in one of several ways:

  • via rsh/ssh, i.e., "rsh remote host bk bkd -e",
  • via ssh as a login shell, and/or
  • as a stand-alone daemon, i.e., "bk bkd -d".

BitMover recommends using ssh, since ssh provides a secure channel. The stand-alone daemon method has no security, other than the ability to run in read-only mode. If security is a requirement, use ssh to get to the daemon. The method used is determined by how the remote repository is referenced, as follows:

  • host:pathname
    Uses ssh (by default) to access host, and starts a temporary bkd. If $BK_RSH is set, then bkd uses that to talk to the host (allows proxying). If no ssh is found then rsh is used.
  • bk://host
    Connects to an existing bkd on the default bkd port. The bkd must be at the root of the repository.
  • bk::/host/pathname
    Connects to an existing bkd on the default bkd port, changes to pathname, then runs command.
  • bk://host:port
    Connects to an existing bkd on the specified port. The bkd must be at the root of the repository.
  • bk://host:port/pathname
    Connects to an existing bkd on the specified port, changes to pathname, then runs the command.
  • bk://user@host
    Connects to host using ssh, and assumes that bkd is the login shell. The home directory of user must be the root of the repository.
  • bk://user@host/pathname
    Connects to host using ssh, and assumes that bkd is the login shell. Changes directories to the specified pathname, which may be relative to the home directory or an absolute pathname.

Anonymous Access

The most common use of the stand-alone daemon is for anonymous access to a repository. To provide read-only, anonymous access, you can run:

bk bkd -d -xpush

This will allow anyone to read (but not write) all repositories on the system running the daemon.

If you want to export a single repository, pick a port number, and do this:

cd /u/linux
bk bkd -d -p5555 -xcd -xpush

This says to run in daemon mode, bind to port 5555, and disallow the "cd" and "push" commands. By disallowing the "cd" command, the daemon at port 5555 is tied to the repository in the current working directory (bkd needs to be run at the root of the repository). By disallowing the "push" command, the repository is protected from updates.

Clients would then get to this repository by using the BitKeeper URL of:

bk://host.domain:5555

i.e.,

$ bk clone bk://host.domain:5555 my_tree

If you want to have a repository which allows the world to read it, but restricts write access to a select few, you would use bkd to give out read only access, and tell people the BitKeeper URL for the foo project is:

bk://someplace.com:5000

For both read and write access that you want to give to a few trusted people, you would give them ssh access to a machine with a clone into which you allow pushes. Suppose your bk://someplace.com:5000 is really someplace.com:/home/bk/foo. You would then give your trusted friends a login on someplace.com and tell them the bk URL they want to use is someplace.com:/home/bk/foo, that is, they would say:

bk clone someplace.com:/home/bk/foo foo

When they then push back to that location, they will be prompted for an ssh password that allows them to push.

Please see bk helptool bkd and bk helptool Howto-bkd for more information and bkd examples.

Sending Changes via Email

The bk send command is used in lieu of bk push when the only connection to a remote machine is through email. To send a complete repository, use:

$ bk send user@host.com

BitKeeper then generates a very large patch and mails it to user@host.com. To keep the size of the patch to a minimum, if you know a specific change you want to send (and you know that the other repository has the changes leading up to the change you want to send), you can do this:

$ bk send -rbeta.. user@host.com

or

$ bk send -r1.10.. user@host.com

Send remembers the changesets it has sent in BitKeeper/log/sendlog-address where address is like user@host.com. When you don't specify a list of changesets to send, bk send will look in the log file and send only the new changesets. The easiest thing to do is to always use the same email address and just say:

$ bk send user@host.com

If you lose the log file and you want to send it with the changes you know have been sent, the command to do that is:

$ cd package-root
$ bk prs -h -r
revs -d:KEY: ChangeSet > BitKeeper/log/send-user@host.com

You can wrap patches so that they do not get corrupted by mailers. BitKeeper currently supports wrapping with uuencode. The following (contrived) command sends a wrapped patch and applies it in /tmp/foo (which must exist):

$ bk send -wuu -r..1.5 | bk receive /tmp/foo

Receiving Changes via Email

The bk receive command is used to apply a BitKeeper patch that was received via email. If you receive an email message that is a BitKeeper patch, save the message and feed it to the receive command as follows:

$ bk receive ~/mypackage < patch

Headers and footers are automatically stripped from the message. Note that if you don't yet have a repository created for this patch, you must use the -i option to bk receive in order to create a new repository.

Specifying the repository is optional; if it is unspecified, receive tries to use the current working directory.


Home    Company    Products    How to Buy    Downloads    Contact Us    Documentation    Support    Site Map

© 1997-2005, BitMover, Inc.