how to use patch and diff to merge two files and automatically resolve conflicts

You don't need patch for this; it's for extracting changes and sending them on without the unchanged part of the file.

The tool for merging two versions of a file is merge, but as @vonbrand wrote, you need the "base" file from which your two versions diverged. To do a merge without it, use diff like this:

diff -DVERSION1 file1.xml file2.xml > merged.xml

It will enclose each set of changes in C-style #ifdef/#ifndef "preprocessor" commands, like this:

#ifdef VERSION1
<stuff added to file1.xml>
#endif
...
#ifndef VERSION1
<stuff added to file2.xml>
#endif

If a line or region differs between the two files, you'll get a "conflict", which looks like this:

#ifndef VERSION1
<version 1>
#else /* VERSION1 */
<version 2>
#endif /* VERSION1 */

So save the output in a file, and open it in an editor. Search for any places where #else comes up, and resolve them manually. Then save the file and run it through grep -v to get rid of the remaining #if(n)def and #endif lines:

grep -v '^#if' merged.xml | grep -v '^#endif' > clean.xml

In the future, save the original version of the file. merge can give you much better results with the help of the extra information. (But be careful: merge edits one of the files in-place, unless you use -p. Read the manual).


sdiff (1) - side-by-side merge of file differences

Use the --output option, this will interactively merge any two files. You use simple commands to select a change or edit a change.

You should make sure that the EDITOR environment variable is set. The default editor for commands like "eb" is usually ed, a line editor.

EDITOR=nano sdiff -o merged.txt file1.txt file2.txt

merge(1) is probably nearer to what you want, but that requires a common ancestor to your two files.

A (dirty!) way of doing it is:

  1. Get rid of the first and last lines, use grep(1) to exclude them
  2. Smash the results together
  3. sort -u leaves a sorted list, eliminates duplicates
  4. Replace first/last line

Humm... something along the lines:

echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'

might do.