Emacs and Subversion merge conflicts

Emacs has support for multiple version control systems and as such, for many version control operations. But there are operations I prefer to execute from the shell and one of those operations is branch merging. To be honest, I do not know whether that can be done from Emacs and for Subversion, which is still the main version control system at my workplace.

However, Emacs can support you when you have to resolve merge conflicts, thanks to the Smerge minor mode and Ediff. In this blog post I explain how that works. Before I do so, I start with some background information about Subversion merge conflicts.

Assume you execute the SVN command as follows:

svn merge -r <initial>:<final> <source URL> <working directory>

This command tries to automatically merge the changes from changeset revision "initial" up to and including those from changeset "final" of the repository at <source URL> to the code at the specified <working directory>.

When a merge leads to a conflict and you decide to postpone the conflict resolution, SVN creates three files for the file that has the conflict. For example when the conflict occurs in file setup.py, Subversion creates the following three files:

  • setup.py.merge-left.r<initial>
  • setup.py.merge-right.r<final>
  • setup.py.working

The merge-left file contains the first revision that has to be merged from the source URL and the merge-right file contains the last revision. The working file contains the current version of the file to which the changes in the source URL have to be applied.

Subversion also modifies setup.py as well as it can. In our case, not every change to setup.py could be automatically applied and the new setup.py contains an unresolved conflict like this:

<<<<<<< .working
version = '2.3dev'
=======
version = '1.79.1.3dev'
>>>>>>> .merge-right.r23929

As mentioned, Emacs can help you resolve each conflict in several ways. One way is through the vc-dir command, which gives me the version control state of all the files in a directory tree. In Emacs, this looks like this:

/images/vc-dir.png

Let us resolve the issue in the setup.py, When I open setup.py, Emacs automatically opens it in Smerge mode. This mode highlights conflicts, allows me to jump to the next (or previous) conflict etc.

/images/smerge-mode.png

For me, Smerge is not the ideal tool for conflict resolution. It provides me with a single pane view of the conflicts where I prefer a two-pane view such as the one Ediff provides. Furthermore, I cannot seem to memorize its key-bindings, which always make me grab the mouse.

Fortunately, Smerge can call Ediff to handle the conflict resolution. Press C-c ^ E and an Ediff session opens which allows me to perform the necessary actions in a two-pane view:

/images/ediff-merge.png

The top-left pane contains the setup.py in my working directory as it was before the merge, the top-right pane contains the final revision of setup.py at the source URL and the bottom pane contains the merged version.

The really nice thing is that as soon as I end the Ediff session, Emacs goes back to the conflicted file with all the changes done in the Ediff session applied. So if you have resolved all conflicts, the file is not in Smerge mode anymore. The only thing left to do is to save the file. After that, the state of the file as displayed in the vc-dir buffer changes from conflicted to edited.

Comments

Comments powered by Disqus