Handy bash function for merge conflicts

I have been merging packages from debian unstable to ubuntu karmic lately and every so often I need to look at a merge conflict.

Sometimes it’s not so obvious why a conflict occurred at all. Here’s an example conflict from the libsepol package:

  1 <<<<<<< libsepol-2.0.32-1ubuntu1 (ubuntu)
  3     /* Get the scope info for this boolean to see if this is the declaration,
  4      * if so set the state */
  5     scope = hashtab_search(state->cur->policy->p_bools_scope.table, id);
  6     if (!scope)
  7         return SEPOL_ERR;
  8     if (scope->scope == SCOPE_DECL)
  9         base_bool->state = booldatum->state;
 10 
 11 =======
 13     /* Get the scope info for this boolean to see if this is the declaration,
 14      * if so set the state */
 15     scope = hashtab_search(state->cur->policy->p_bools_scope.table, id);
 16     if (!scope)
 17         return SEPOL_ERR;
 18     if (scope->scope == SCOPE_DECL)
 19         base_bool->state = booldatum->state;
 20 
 21 >>>>>>> libsepol-2.0.36-1 (debian)

In order to avoid staring at the screen until my eyes start to bleed :) I came up with the following bash function:

  1 function dsec() {
  2     xclip -selection clipboard -o > /tmp/patch-seg-to-diff.txt
  3     rm -f /tmp/ubuntu-snippet.txt /tmp/debian-snippet.txt
  4     ed /tmp/patch-seg-to-diff.txt > /dev/null 2>&1 <<-EOUBUNTU
  5         1 d
  6         /^===/,$ d
  7         wq /tmp/ubuntu-snippet.txt
  8 EOUBUNTU
  9     ed /tmp/patch-seg-to-diff.txt > /dev/null 2>&1 <<-EODEBIAN
 10         1,/^===/d
 11         $ d
 12         wq /tmp/debian-snippet.txt
 13 EODEBIAN
 14     echo 'diff -Nru /tmp/ubuntu-snippet.txt /tmp/debian-snippet.txt | colordiff | less'
 15     diff -Nru /tmp/ubuntu-snippet.txt /tmp/debian-snippet.txt | colordiff | less
 16 }

I can now use my favourite editor to copy the conflicting code to the clipboard. When invoked on the command line the dsec function reads the clipboard content and chops it apart (using the ed utility) into a debian and an ubuntu snippet respectively. Subsequently it invokes the diff utility on the two snippets showing me how they differ.

 1 --- /tmp/ubuntu-snippet.txt 2009-06-26 12:42:04.000000000 +0200
 2 +++ /tmp/debian-snippet.txt 2009-06-26 12:42:04.000000000 +0200
 3 @@ -1,5 +1,5 @@
 4     /* Get the scope info for this boolean to see if this is the declaration,
 5 -    * if so set the state */
 6 +    * if so set the state */
 7     scope = hashtab_search(state->cur->policy->p_bools_scope.table, id);
 8     if (!scope)
 9         return SEPOL_ERR;

Hmm .. this looks like a white space issue. Since the dsec function printed the actual diff command to the terminal, I can copy and paste that to the command line and add the -b parameter so that the diff utility ignores changes in the amount of white space and ..

 1 $ diff -Nrub /tmp/ubuntu-snippet.txt /tmp/debian-snippet.txt
 2 $ echo $?
 3 0

.. voila! the diff output this time around is empty.

In order for this to work the utilities used must be installed, so e.g. on a ubuntu system run:

sudo apt-get install xclip colordiff

And .. don’t forget to have fun :)