Branch as in version control system is a history, composed of a time series of snapshots of software. Branch evolves: It emerges, changes, develops, and dies. These are the internal dynamics of branch. A branch emerges when it is “magically” created from either nothing or an existing branch. It dies when it is closed or “magically” disappears. The number of snapshots in a branch normally increases monotonically. If we calculate its rate as a function of time, we may find a Gaussion-like curve that demonstrates a low rate when the branch is emerging, followed by a high rate, and then a low rate again when the branch is dying. Of course, it is likely an oversimplified view, and the characteristics of the function may have a strong dependency on the purpose of the branch and other factors.
Most of time, a new branch is created from an existing one. Such operations are called branching. By branching, we diverge the development (but not necessarily the goal of development), and different new features or bug fixes can possibly be developed in different branches. A dedicated branch provides a relatively static code environment. This means (1) that all changes in the branch are relevant to the task, (2) that works on different tasks do not interfere with each other, and (3) developments for different tasks can evolve independently in parallel.
The counter-operation of branching is merging, which combines codes together from two or more source branches. The merged (i.e., combined) code, with potential conflicts resolved, is saved into a single branch, usually one of the source branches. The other branches can be closed then. It is worth noting that merging merges code, not necessarily development. This is in contrast to branching, which indeed diverges development. Merging itself can be thought as development because it results in code changes. If committing is considered as evolution of code in an incremental fashion, merging is evolution in a leapfrog fashion. This again differ from branching, which doesn’t cause any code change by itself. So merging is not totally in mirror symmetry to branching.
Branching and merging are the most common interactions of branches. There is a less common interaction – rebasing. Rebasing slides the origin of a branch downstream, which means that the rebased branch will import some changes from the source branch. Rebasing is another way of combining code from different branches. The imported code will serve as the base of the code developed in the rebased branch. This is where it differs from merging.
How branches interacts with each other and how they evolve are the topics of the external dynamics of branches, or in short branching dynamics. The principles that rule the interactions of branches and thus basically determines the dynamics is called branching model.