Freebsd-update from 8.3-RELEASE to 9.0-RELEASE: How to deal with dozens of diffs

freebsd

I am upgrading a FreeBSD 8.3-RELEASE system to FreeBSD 9.0-RELEASE using freebsd-update. This is my first time performing a major version upgrade in FreeBSD.

At one point in the process, freebsd-update performs a diff on files which are different then what is expected for the 9.0-RELEASE. It compares the current version on the system with the new changes added from 9.0-RELEASE. I have a modified a couple dozen files under /etc, and I am presented with this diff once per file.

Thus, I am presented with dozens and dozens of diffs which open in a vi window and look like this:

The following file could not be merged automatically: /etc/ntp.conf
Press Enter to edit this file in vi and resolve the conflicts
manually...

### vi window opens

<<<<<<< current version
driftfile /etc/ntp/drift
=======
#
# $FreeBSD: release/9.0.0/etc/ntp.conf 195652 2009-07-13 05:51:33Z dwmalone $
#
# Default NTP servers for the FreeBSD operating system.
#
# Don't forget to enable ntpd in /etc/rc.conf with:
# ntpd_enable="YES"
#
# The driftfile is by default /var/db/ntpd.drift, check
# /etc/defaults/rc.conf on how to change the location.
#
>>>>>>> 9.0-RELEASE

restrict default notrust nomodify ignore

And it complains about minor version numbers:

--- current version
+++ new version
@@ -1,6 +1,6 @@
-# $FreeBSD: src/gnu/usr.bin/man/manpath/manpath.config,v 1.25.28.1 2009/04/15 03:14:26 kensmith Exp $
+# $FreeBSD: src/gnu/usr.bin/man/manpath/manpath.config,v 1.25.32.1 2010/12/21 17:10:29 kensmith Exp $
 #
 # This file is read by manpath(1) to configure the mandatory manpath,
 # optional manpath and to map each path element to a manpath element.
 # The format is:
 #
Does this look reasonable (y/n)? y

And fact it complains about the RCS version string on dozens of files:

--- current version
+++ new version
@@ -1,4 +1,4 @@
-# $FreeBSD: src/etc/amd.map,v 1.10.8.1 2009/04/15 03:14:26 kensmith Exp $
+# $FreeBSD: release/9.0.0/etc/amd.map 164015 2006-11-06 01:42:11Z obrien $
 #
 /defaults       type:=host;fs:=${autodir}/${rhost}/host;rhost:=${key}
 *               opts:=rw,grpid,resvport,vers=3,proto=tcp,nosuid,nodev
Does this look reasonable (y/n)?

And even complains because I removed the FreeBSD version number from my local (custom) /etc/passwd file:

<<<<<<< current version
=======
# $FreeBSD: release/8.4.0/etc/master.passwd 243948 2012-12-06 11:54:25Z rwatson $
#
>>>>>>> 8.4-RELEASE
root:*:0:0:Charlie &:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin

And so on.

This requires that I manually edit each file and remove the strings like <<<<<<< current version >>>>>>> 9.0-RELEASE and =======, and manually merge these files. As I discovered afterwards, if I don't remove these strings, they end up in the file afterwards. There are dozens of files which differ between 8.3 and 9.0, and I have a dozen local modifications myself.

It appears that freebsd-update is using a diff, sdiff or mergemaster function of some sort, but I can't tell what it is doing exactly.

Processing these files is tedious. Is there a way that I can just say "Accept new version" or "keep old version" or "Your merge is correct"? There has got to be an easier way to deal with these files. I must be missing something.

This isn't a huge problem for one machine, but eventually I'll be doing this dozens of times and I want to find an easier way.

And I am not alone. At least one other admin out there has pointed out this problem. The author of Zytrax.com: FreeBSD Update Survival Guide: freebsd-update upgrading minor or major versions also talks about this situation:

Notes:

  1. When updating to a new release lots of stuff changes (much less so with a minor release). When scripts and configurations files are
    modified freebsd-update diffs them, loads them into vi and presents
    them for reconciliation. Since most of the changes are simple version
    number comment field changes this can be a serious pain (in our case
    well over 50 files were changed, over 40 were comment only changes).
    However, be warned – diligence is necessary (no :wq to every file
    without looking). Further, unless the file is visibly short all the
    diff marks (:/>>>/) need to be viewed and reconciled. Failure to do
    this will cause the resulting file to contain the diff indicators and
    many essential system files will simply croak when loaded (including
    the password file in our case) resulting in endless hours of fun
    looking for the files that were modified (guess how we found this
    out). While there is really no alternative to genuine file changes,
    having to undergo the edit reconciliation for comment only changes
    results in a serious shortcoming in the process. Better, perhaps, to
    move the replaced files into a special location and let the user
    manually reconcile those of interest. Just how often do you change
    /etc/periodic/weekly/310.locate?

Update:

Looks like these diffs are managed by merge(1), not mergemaster. From the merge(1) manpage:

   A conflict occurs if both file1 and file3 have changes in a common seg-
   ment of lines.  If a conflict is found, merge normally outputs a  warn-
   ing  and brackets the conflict with <<<<<<< and >>>>>>> lines.  A typi-
   cal conflict will look like this:

      <<<<<<< file A
      lines in file A
      =======
      lines in file B
      >>>>>>> file B

Best Answer

I wasn't getting much response here, so I asked at forums.freebsd.org.

The short answer is: No. There is no easy way to merge these changes using freebsd-update. freebsd-update uses merge(1) to perform the diffs and merging, and merge is not very friendly or flexible.

There are other options, such as sysutils/etcupdate as suggested by kworr. However, I don't see how that can be integrated with freebsd-update.

From what I read, freebsd-update is a convenient way to upgrade FreeBSD, but it fails in other ways. Many FreeBSD admins don't use freebsd-update at all, and prefer the manual way using using the source and mergemaster(8).

Related Topic