borg diff
*********

   borg [common options] diff [options] REPO::ARCHIVE1 ARCHIVE2 [PATH...]


Description
===========

This command finds differences (file contents, user/group/mode)
between archives.

A repository location and an archive name must be specified for
REPO::ARCHIVE1. ARCHIVE2 is just another archive name in the same
repository (no repository location allowed).


What is compared
----------------

For each matching item in both archives, Borg reports:

* Content changes: total added/removed bytes within files. If chunker
  parameters are comparable, Borg compares chunk IDs quickly;
  otherwise, it compares the content.

* Metadata changes: user, group, mode, and other metadata shown inline
  like "[old_mode -> new_mode]" for mode changes. Use "--content-only"
  to suppress metadata changes.

* Added/removed items: printed as "added SIZE path" or "removed SIZE
  path".


Output formats
--------------

The default (text) output shows one line per changed path, e.g.:

   +135 B    -252 B [ -rw-r--r-- -> -rwxr-xr-x ] path/to/file

JSON Lines output ("--json-lines") prints one JSON object per changed
path, e.g.:

   {"path": "PATH", "changes": [
       {"type": "modified", "added": BYTES, "removed": BYTES},
       {"type": "mode", "old_mode": "-rw-r--r--", "new_mode": "-rwxr-xr-x"},
       {"type": "added", "size": SIZE},
       {"type": "removed", "size": SIZE}
   ]}

Only actual changes are included in the "changes" list. For example, a
modified entry with added=0 and removed=0 is omitted.


Sorting
-------

Use "--sort-by FIELDS" where FIELDS is a comma-separated list of
fields. Sorts are applied stably from last to first in the given list.
Prepend ">" for descending, "<" (or no prefix) for ascending, for
example "--sort-by=">size_added,path"". Supported fields include:

* path: the item path

* size_added: total bytes added for the item content

* size_removed: total bytes removed for the item content

* size_diff: size_added - size_removed (net content change)

* size: size of the item as stored in ARCHIVE2 (0 for removed items)

* user, group, uid, gid, ctime, mtime: taken from the item state in
  ARCHIVE2 when present

* ctime_diff, mtime_diff: timestamp difference (archive2 - archive1)

The "--sort" option is deprecated and only sorts by path.


Performance considerations
--------------------------

For archives created with Borg 1.1 or newer, diff automatically
detects whether the archives were created with the same chunker
parameters. If so, only chunk IDs are compared, which is very fast.

For archives prior to Borg 1.1, chunk contents are compared by
default. If you did not create the archives with different chunker
parameters, pass "--same-chunker-params". Note that the chunker
parameters changed from Borg 0.xx to 1.0.

For more help on include/exclude patterns, see the borg help patterns
command output.


Examples
========

   $ borg init -e=none testrepo
   $ mkdir testdir
   $ cd testdir
   $ echo asdf > file1
   $ dd if=/dev/urandom bs=1M count=4 > file2
   $ touch file3
   $ borg create ../testrepo::archive1 .

   $ chmod a+x file1
   $ echo "something" >> file2
   $ borg create ../testrepo::archive2 .

   $ echo "testing 123" >> file1
   $ rm file3
   $ touch file4
   $ borg create ../testrepo::archive3 .

   $ cd ..
   $ borg diff testrepo::archive1 archive2
   [-rw-r--r-- -> -rwxr-xr-x] file1
      +135 B    -252 B file2

   $ borg diff testrepo::archive2 archive3
       +17 B      -5 B file1
   added           0 B file4
   removed         0 B file3

   $ borg diff testrepo::archive1 archive3
       +17 B      -5 B [-rw-r--r-- -> -rwxr-xr-x] file1
      +135 B    -252 B file2
   added           0 B file4
   removed         0 B file3

   $ borg diff --json-lines testrepo::archive1 archive3
   {"path": "file1", "changes": [{"type": "modified", "added": 17, "removed": 5}, {"type": "mode", "old_mode": "-rw-r--r--", "new_mode": "-rwxr-xr-x"}]}
   {"path": "file2", "changes": [{"type": "modified", "added": 135, "removed": 252}]}
   {"path": "file4", "changes": [{"type": "added", "size": 0}]}
   {"path": "file3", "changes": [{"type": "removed", "size": 0}]}

   # Use --sort-by with a comma-separated list; sorts apply stably from last to first.
   # Here: primary by net size change descending, tie-breaker by path ascending
   $ borg diff --sort-by=">size_diff,path" testrepo::archive1 archive3
       +17 B      -5 B [-rw-r--r-- -> -rwxr-xr-x] file1
   removed         0 B file3
   added           0 B file4
      +135 B    -252 B file2
