Skip to main content

28.1.11 Version Control Branches

One use of version control is to support multiple independent lines of development, which are called branches. Amongst other things, branches can be used for maintaining separate stable and development versions of a program, and for developing unrelated features in isolation from one another.

VC’s support for branch operations is currently fairly limited. For decentralized version control systems, it provides commands for updating one branch with the contents of another, and for merging the changes made to two different branches (see Merging). For centralized version control systems, it supports checking out different branches and committing into new or different branches.

Switching Branches  How to get to another existing branch.
Pulling / Pushing  Receiving/sending changes from/to elsewhere.
Merging  Transferring changes between branches.
Creating Branches  How to start a new branch.

28.1.11.1 Switching between Branches

The various version control systems differ in how branches are implemented, and these differences cannot be entirely concealed by VC.

On some decentralized version control systems, including Bazaar and Mercurial in its normal mode of operation, each branch has its own working directory tree, so switching between branches just involves switching directories. On Git, branches are normally co-located in the same directory, and switching between branches is done using the git checkout command, which changes the contents of the working tree to match the branch you switch to. Bazaar also supports co-located branches, in which case the bzr switch command will switch branches in the current directory. With Subversion, you switch to another branch using the svn switch command. With Mercurial, command hg update is used to switch to another branch.

The VC command to switch to another branch in the current directory is C-x v r branch-name RET (vc-retrieve-tag).

On centralized version control systems, you can also switch between branches by typing C-u C-x v v in an up-to-date work file (see Advanced C-x v v), and entering the revision ID for a revision on another branch. On CVS, for instance, revisions on the trunk (the main line of development) normally have IDs of the form 1.1, 1.2, 1.3, …, while the first branch created from (say) revision 1.2 has revision IDs 1.2.1.1, 1.2.1.2, …, the second branch created from revision 1.2 has revision IDs 1.2.2.1, 1.2.2.2, …, and so forth. You can also specify the branch ID, which is a branch revision ID omitting its final component (e.g., 1.2.1), to switch to the latest revision on that branch.

On a locking-based system, switching to a different branch also unlocks (write-protects) the working tree.

Once you have switched to a branch, VC commands will apply to that branch until you switch away; for instance, any VC filesets that you commit will be committed to that specific branch.

28.1.11.2 Pulling/Pushing Changes into/from a Branch

C-x v P

On a decentralized version control system, update another location with changes from the current branch (a.k.a. “push" changes). This concept does not exist for centralized version control systems

C-x v +

On a decentralized version control system, update the current branch by “pulling in" changes from another location.

On a centralized version control system, update the current VC fileset.

On a decentralized version control system, the command C-x v P (vc-push) updates another location with changes from the current branch. With a prefix argument, it prompts for the exact version control command to run, which lets you specify where to push changes; the default is bzr push with Bazaar, git push with Git, and hg push with Mercurial. The default commands always push to a default location determined by the version control system from your branch configuration.

Prior to pushing, you can use C-x v O (vc-log-outgoing) to view a log buffer of the changes to be sent. See VC Change Log.

This command is currently supported only by Bazaar, Git, and Mercurial. The concept of “pushing" does not exist for centralized version control systems, where this operation is a part of committing a changeset, so invoking this command on a centralized VCS signals an error. This command also signals an error when attempted in a Bazaar bound branch, where committing a changeset automatically pushes the changes to the remote repository to which the local branch is bound.

On a decentralized version control system, the command C-x v + (vc-pull) updates the current branch and working tree. It is typically used to update a copy of a remote branch. If you supply a prefix argument, the command prompts for the exact version control command to use, which lets you specify where to pull changes from. Otherwise, it pulls from a default location determined by the version control system.

Amongst decentralized version control systems, C-x v + is currently supported only by Bazaar, Git, and Mercurial. With Bazaar, it calls bzr pull for ordinary branches (to pull from a master branch into a mirroring branch), and bzr update for a bound branch (to pull from a central repository). With Git, it calls git pull to fetch changes from a remote repository and merge it into the current branch. With Mercurial, it calls hg pull -u to fetch changesets from the default remote repository and update the working directory.

Prior to pulling, you can use C-x v I (vc-log-incoming) to view a log buffer of the changes to be applied. See VC Change Log.

On a centralized version control system like CVS, C-x v + updates the current VC fileset from the repository.

28.1.11.3 Merging Branches

C-x v m

On a decentralized version control system, merge changes from another branch into the current one.

On a centralized version control system, merge changes from another branch into the current VC fileset.

While developing a branch, you may sometimes need to merge in changes that have already been made in another branch. This is not a trivial operation, as overlapping changes may have been made to the two branches.

On a decentralized version control system, merging is done with the command C-x v m (vc-merge). On Bazaar, this prompts for the exact arguments to pass to bzr merge, offering a sensible default if possible. On Git, this prompts for the name of a branch to merge from, with completion (based on the branch names known to the current repository). With Mercurial, this prompts for argument to pass to hg merge. The output from running the merge command is shown in a separate buffer.

On a centralized version control system like CVS, C-x v m prompts for a branch ID, or a pair of revision IDs (see Switching Branches); then it finds the changes from that branch, or the changes between the two revisions you specified, and merges those changes into the current VC fileset. If you just type RET, Emacs simply merges any changes that were made on the same branch since you checked the file out.

Immediately after performing a merge, only the working tree is modified, and you can review the changes produced by the merge with C-x v D and related commands (see Old Revisions). If the two branches contained overlapping changes, merging produces a conflict; a warning appears in the output of the merge command, and conflict markers are inserted into each affected work file, surrounding the two sets of conflicting changes. You must then resolve the conflict by editing the conflicted files. Once you are done, the modified files must be committed in the usual way for the merge to take effect (see Basic VC Editing).

28.1.11.4 Creating New Branches

On centralized version control systems like CVS, Emacs supports creating new branches as part of a commit operation. When committing a modified VC fileset, type C-u C-x v v (vc-next-action with a prefix argument; see Advanced C-x v v). Then Emacs prompts for a revision ID for the new revision. You should specify a suitable branch ID for a branch starting at the current revision. For example, if the current revision is 2.5, the branch ID should be 2.5.1, 2.5.2, and so on, depending on the number of existing branches at that point.

To create a new branch at an older revision (one that is no longer the head of a branch), first select that revision (see Switching Branches). Your procedure will then differ depending on whether you are using a locking or merging-based VCS.

On a locking VCS, you will need to lock the old revision branch with C-x v v. You’ll be asked to confirm, when you lock the old revision, that you really mean to create a new branch—if you say no, you’ll be offered a chance to lock the latest revision instead. On a merging-based VCS you will skip this step.

Then make your changes and type C-x v v again to commit a new revision. This creates a new branch starting from the selected revision.

After the branch is created, subsequent commits create new revisions on that branch. To leave the branch, you must explicitly select a different revision with C-u C-x v v.