ETCMERGE(1) General Commands Manual ETCMERGE(1)

merge updates to configuration files from etc.tgz

etcmerge [-q] [-S statedir] command [args ...]

The etcmerge utility assists merging updates to configuration files given the old and new upstream etc.tgz (or xetc.tgz) distribution sets.

The command

$ etcmerge auto old/etc.tgz new/etc.tgz
will try to merge all changes from old/etc.tgz to new/etc.tgz into any local changes from old/etc.tgz. For any file F with local changes that conflict with upstream changes, etcmerge will leave F intact and create new files:
the file F from old/etc.tgz
the file F from new/etc.tgz
merged file with diff3(1) conflict markers
The command etcmerge autoedit F will launch the editor on the .~merge~ file, and, if there are no conflict markers when it exits, move the .~merge~ file into place and delete the .~old~ and .~new~ files.

For an interactive three-way merge in a separate staging area, start by running:

$ etcmerge start old/etc.tgz new/etc.tgz
This will try to merge all changes into a staging area, and then print the status of each file modified locally and upstream.

Once the merge is started, the various subcommands etcmerge show, etcmerge diff, etcmerge edit, etcmerge resolved, and so on display and edit state of the merge operation:

$ etcmerge show /etc/ssh/sshd_config
$ etcmerge diff -l -u /etc/ssh/sshd_config
$ etcmerge diff -n -u /etc/ssh/sshd_config
$ etcmerge edit /etc/ssh/sshd_config
$ etcmerge resolved /etc/ssh/sshd_config

When done, run either etcmerge commit to apply the changes outside the staging area, or etcmerge abort to give up on the merge and discard all changes.

Only one merge at a time can be in progress, unless you specify an alternate state directory with -S. etcmerge start will refuse to start a new merge until an ongoing one is aborted or committed.

Quiet. Suppress informative messages to standard error identifying stages in the merge process.
Use statedir to hold etcmerge state, instead of the default /var/etcmerge.

Abort any pending merge operation and discard all changes in the staging area.
[-Cdns] [-c resolution] [-R rootdir] old.tgz new.tgz
Merge upstream changes into local files, rooted at rootdir if specified, and leave .~old~, .~new~, and .~merge~ files for any files with local changes that conflict with upstream changes, unless overridden by the -c option. You can use etcmerge autoedit to edit the .~merge~ files to resolve conflicts.

Note: This does not use a separate staging area. etcmerge auto is an abbreviation for: etcmerge start -A -c suffix

You should make sure to resolve all the conflicts (and delete these extra files manually if you don't use etcmerge autoedit) before the next update; etcmerge auto will refuse to overwrite an existing .~old~, .~new~, or .~merge~ file in order to avoid clobbering incomplete merges.

path ...
For each of the paths, if there is a .~merge~ file, open an editor on that file. When the editor exits, if there are no conflict markers left (<<<<<<<, |||||||, =======, or >>>>>>>), then rename it to the permanent name without .~merge~ and delete the corresponding .~old~ and .~new~ files.

Meant for use after etcmerge auto; this does not use a separate staging area.

Verify there are no more unresolved conflicts and commit the pending merge operation.

This moves all files from the staging area into their final places in the file system (relative to any rootdir specified in etcmerge start), and runs post-merge actions, including MAKEDEV(8) if /dev/MAKEDEV or /dev/MAKEDEV.local changed, newaliases(8) if /etc/mail/aliases changed, pwd_mkdb(8) if /etc/master.passwd changed, and services_mkdb(8) if /etc/services changed. (XXX The post-merge actions are not yet implemented.)

With the -d option, delete files that have been deleted upstream. (XXX This is not yet correctly implemented — it doesn't track local versus upstream deletions.)

[path ...]
Discard any changes in the staging area to the given paths and recreate the three-way merge with conflict markers.
[-clmnpru] [path ...]
Show the diff between two versions of each file.

Either -l (local) or -n (new) must be specified to choose which versions. With -m, diff from whichever version is selected to the current file in the staging area. Without -m, diff from the old (upstream) version to whichever version is selected.


show context diff
use local file
use merged file
use new (upstream) file
show function context in diff
compare directories recursively
show unified diff
[path ...]
Open an editor on each of the paths in the staging area. The editor is specified by the EDITOR environment variable.

If the files have unresolved conflicts, etcmerge will continue to consider them unresolved; if you have resolved them, use etcmerge resolved to mark them as resolved.

[path ...]
Discard any merge and select the local version of each file. If the file had merge conflicts, this marks them as resolved like etcmerge resolved.
path ...
Mark each path as resolved in the staging area after editing, e.g. with etcmerge edit.

Note: If the file still has merge conflict markers, then after etcmerge resolved they will remain in the file if committed with etcmerge commit.

command [args ...]
Run a command in the staging area.
[args ...]
Start a shell in the staging area. The shell is specified by the SHELL environment variable.
[-c] path
Show the current state of a file in the staging area.

With the -c option, ignore the current state and instead display the automatic merge of the file, with conflict markers.

[-ACdns] [-c resolution] [-R rootdir] old.tgz new.tgz
Start a merge operation to incorporate changes from old.tgz to new.tgz into the files in the file system. Display a summary of an automatic merge outcome and then set up state for other etcmerge subcommands.


Autocommit if the merge is clean. etcmerge will not create conflict markers, although it may yield nonsensical results if diff3(1) gets confused. This may be combined with the -C option to autocommit only if all upstream changes are to files unmodified locally.
Abort if upstream made any changes to files that have local changes, even if they can be cleanly merged.
Automatically apply resolution to files with conflicts:
Abort the merge in case of conflicts.
Take the local version of any file with conflicts.
Take the local version of any file with conflicts, but create .~old~, .~new~, and .~merge~ files alongside it, or abort if these files already exist.
Take the upstream version of any file with conflicts.
If specified with -A, in the event of a successful merge, delete files that were deleted upstream. (XXX This is not yet correctly implemented — it doesn't track local versus upstream deletions.)
Dry run. Just display a summary of the automatic merge outcome without actually starting a merge operation.
Use rootdir instead of / to find and merge files.
Silent. Suppress the summary of the automatic merge outcome.
Display a summary of the merge so far. For every file in old.tgz or new.tgz with either local or upstream changes, displays a line with a letter and the file name to indicate what state the file is in:
unresolved conflicting changes
local changes only
both changed but clean merge
resolved conflicts
upstream changes only
Try to undo the immediately preceding etcmerge auto or etcmerge commit operation. All files in the file system outside the staging area listed in old.tgz or new.tgz are restored to the state they were in before etcmerge start.

There is only one level of undo. etcmerge undo is a convenience, not a substitute for backups — make sure to keep good backups.

(XXX This doesn't do anything about deletions.)

[path ...]
Discard any merge and select the new upstream version of each file. If the file had merge conflicts, this marks them as resolved like etcmerge resolved.

Editor for etcmerge edit.
mtree(1) command.
pax(1) command.
Shell for etcmerge shell.

State directory. Overridden by the -S option.

diff3(1), mtree(1), pax(1), tar(1), postinstall(8)

etcmerge is new and likely buggy, and may find your files tasty with a bit of mustard. Take backups.

etcmerge is not a substitute for a revision control system — it only assists with an individual merge operation. Consider keeping important configuration files under git(1) or hg(1) or rcs(5).

etcmerge must be run as root. It would be nice if it could run unprivileged and use mtree(1) to record permissions on files it handles, and create a tar archive for the resulting merge outcome.
January 6, 2021 NetBSD 9.1_STABLE