Source-control clients
Most Windows source-control clients have a setting along the lines of "external diff tool" and "external merge tool", where you give a program and an argument template with placeholders for the file names. pb-diff is designed to drop into that slot. For the PowerBuilder IDE's own Diff Viewer, see From the PowerBuilder IDE: see what you changed; for TortoiseGit and TortoiseSVN, Tools ▸ Set up TortoiseGit and Tools ▸ Set up TortoiseSVN write the settings below for you, as Source-control setup describes.
The shapes
Two-way compare, one comparison in its own session, which ends when the user closes it:
pb-diff.exe -SDI -Mode TwoWay -File1 %1 -File2 %2
Three-way merge, with the merged output going where the client expects it:
pb-diff.exe -SDI -Mode ThreeWay -File1 %1 -Base %2 -File2 %3 -Save %4
Quote the placeholders if paths may contain spaces, which on Windows they will:
pb-diff.exe -SDI -Mode TwoWay -File1 "%1" -File2 "%2"
-File1 is the Old side and -File2 is the
New side, so map the client's "base/left/theirs" placeholders
accordingly. The switches may be given in any order, and file names on
the command line never override files already chosen in the application.
Every switch is described in The desktop
command line.
Clients that mangle file names
Many clients give the tool temporary copies with names such as
svn-a1b2c3.tmp, w_main.srw.r412 or
d_customer.srd.tmp. Most of these need no switch at
all. pb-diff first tries to determine the type from the
extension. Extensions such as .tmp and .r412,
or a missing extension, provide no type information, so pb-diff reads
the $PBExportHeader$ line on every parse. All three
examples above therefore parse as the objects they contain.
The fallback does not apply when pb-diff recognises an extension but
that extension names the wrong type. A copy called
d_customer.xml is read as XML and never reaches the header,
because the file name has already supplied a type. Use
-Detect for that case, or whenever you do not want to
depend on the fallback:
| Switch | Rule | Use when |
|---|---|---|
-Detect F |
Take the type from the first extension in the name:
d_customer.srd.tmp → DataWindow export. |
The client appends a suffix to the real name. |
-Detect H |
Take the type from the $PBExportHeader$ line
inside the file, before the name is consulted at all. A
PowerBuilder 2025 Solution source has no such line, so for one
H reads how the file opens instead. |
The name carries a misleading extension, as in
d_customer.xml. A name with no useful extension, like
3f9a2c.tmp, already works without it. |
Add it to the command line and leave the rest alone:
pb-diff.exe -SDI -Mode TwoWay -Detect F -File1 "%1" -File2 "%2"
pb-diff.exe -SDI -Mode TwoWay -Detect H -File1 "%1" -File2 "%2"
-Detect H is the safer default when you do not know what
the client does: it reads the file rather than trusting its name.
-Detect F is cheaper and is right when the client's suffix
pattern is known. For PowerBuilder 2025 Solution sources, H
recognises almost every object from its content, but not one inherited
from another object of your application, such as
w_sheet from w_basesheet: nothing in that file says it is a
window. Keep the extension in the name or use -Detect F
there.
Worked configurations
These follow each client's documented placeholder syntax. Placeholder
names and quoting rules vary between versions, so check the
configuration dialog of the client in front of you and adjust the
placeholders. The pb-diff half of the line does not change. Substitute
the real installation path for
C:\Program Files\pb-diff\pb-diff.exe.
A generic external diff or merge tool
An "external diff tool" field with two placeholders, old file then new file:
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode TwoWay -Detect H -File1 "%1" -File2 "%2"
The diff field is not only for exports. Register .pbl
and .pbd with it as well: pb-diff compares two libraries
directly, entry by entry, even though they are binary files, so a
changed library in the client's history opens as a Compare Summary
rather than as "binary files differ". Leave out -Detect H
for the two library extensions, because it is a source-header rule and a
container has no export header:
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode TwoWay -File1 "%1" -File2 "%2"
An "external merge tool" field with mine, base, theirs and output:
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode ThreeWay -Detect H -File1 "%1" -Base "%2" -File2 "%3" -Save "%4"
TortoiseGit
Open TortoiseGit Settings, choose Diff Viewer, then Advanced, and add each PowerBuilder export extension that the repository uses:
.sra .srd .srf .srm .srp .srj .srq .srs .sru .srw
and each of the build files it keeps - workspaces, targets, Solutions, projects, resource files and PowerGen projects:
.pbw .pbt .pbsln .pbproj .pbr .gen
Paste this as the external diff command for each extension:
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode TwoWay -Detect H -File1 "%base" -File2 "%mine"
Then return to Settings, choose Merge Tool, then Advanced, add the same extensions, and paste this as the external merge command for each one:
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode ThreeWay -Detect H -File1 "%mine" -Base "%base" -File2 "%theirs" -Save "%merged"
TortoiseGit's %base, %mine,
%theirs and %merged placeholders have the
meanings used above. Configure TortoiseGit to wait for the external
merge tool, but do not let it infer that a conflict was resolved from
pb-diff's process exit code: close pb-diff and answer TortoiseGit's
resolution prompt instead. The GUI exit code reports how the application
ended, not whether the merge was resolved.
Add .pbl and .pbd on the Diff Viewer page
too, so that a changed library compares entry by entry instead of being
reported as a binary difference. Their temporary names keep the library
extension, so use the command without -Detect H, which is a
source-header rule and does not apply to a binary container:
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode TwoWay -File1 "%base" -File2 "%mine"
Do not add .pbl or .pbd on the Merge Tool
page: pb-diff never writes a PowerBuilder library. Do not associate
generic extensions such as .xml, .html or
.js unless pb-diff should replace the diff tool for every
such file, not just files related to PowerBuilder.
TortoiseSVN
On the Diff Viewer and Merge Tool pages of TortoiseSVN's Settings, which use the same named placeholders:
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode TwoWay -Detect H -File1 "%base" -File2 "%mine"
"C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode ThreeWay -Detect H -File1 "%mine" -Base "%base" -File2 "%theirs" -Save "%merged"
Git
In .gitconfig. Git passes the file names as
$LOCAL, $REMOTE, $BASE and
$MERGED, and hands the diff tool temporary files with no
useful extension, so -Detect H is not optional here:
[diff]
tool = pb-diff
[difftool "pb-diff"]
cmd = \"C:/Program Files/pb-diff/pb-diff.exe\" -SDI -Mode TwoWay -Detect H -File1 \"$LOCAL\" -File2 \"$REMOTE\"
[difftool]
prompt = false
[merge]
tool = pb-diff
[mergetool "pb-diff"]
cmd = \"C:/Program Files/pb-diff/pb-diff.exe\" -SDI -Mode ThreeWay -Detect H -File1 \"$LOCAL\" -Base \"$BASE\" -File2 \"$REMOTE\" -Save \"$MERGED\"
trustExitCode = false
[mergetool]
keepBackup = false
With -Detect H, a workspace, a target, a Solution, a
project and a PowerGen project are recognised by their content too,
whatever Git calls the temporary file. A resource file has nothing in
its content to say what it is, and is compared as text there.
trustExitCode = false matters: pb-diff's GUI exit code
reports how the application ended, not whether you resolved the merge,
so let Git ask.
The same diff tool compares a whole change set at once.
git difftool --dir-diff copies the changed files of each
side into a temporary folder and hands pb-diff the two folders, which
open as one Compare Summary: every changed object is a row, and a
double-click opens it. Git waits for the window to close before it
removes the folders.
git difftool --dir-diff release-1.4 HEAD
git difftool --dir-diff release-1.4 HEAD -- src/orders.pbl/
The files in those folders keep their real names, so
-Detect H has nothing to correct there; it applies to the
files a command line names, not to the objects a folder holds.
Other visual Git clients
Sourcetree, Git Extensions and other clients have external diff and
merge settings of their own. Configure pb-diff.exe there
using the client's documented placeholders for old and new files, or for
mine, base, theirs and output, with the command shapes above. Generic
%1/%2 examples are not universal placeholder
spellings; do not copy Tortoise's %base/%mine
template into another client without checking. If the client has no
external-tool facility, use its own viewer or open exported files in
pb-diff.
Do not assume that a Git GUI reads .gitconfig difftool
and mergetool settings. The Git example above configures
git difftool and git mergetool; it applies to
a GUI only if that GUI documents that behaviour. Neither those Git
settings nor another GUI's settings replace PowerBuilder's Diff
Viewer selection.
When the configuration field will not take the line
Some clients allow one program and a handful of placeholders, and nothing longer. Put the fixed arguments in a command file and pass the file:
"C:\Program Files\pb-diff\pb-diff.exe" @pb-diff-args.txt -File1 "%1" -File2 "%2"
# pb-diff-args.txt
-SDI -Mode TwoWay -Detect H
See Command files. A
line that pb-diff cannot act on, such as -Mode ThreeWay
without -Base, is refused with a message and exit code 2
rather than opening an empty window; a switch pb-diff does not know,
which some clients add, is ignored.
After a merge
After saving a merged export in pb-diff, close the comparison and confirm resolution in the client rather than inferring it from the GUI exit code. Refresh and compile the object in PowerBuilder, then mark the conflict resolved before committing. Saving an export does not update an object already loaded in a PBL.
Migrating a ProDiff command line
The GUI argument spellings were chosen so an existing ProDiff
integration can usually migrate by changing its program path to
pb-diff.exe while retaining the arguments. pb-diff does not
provide an executable-name shim; this compatibility concerns
command-line arguments only.