Reputation: 551
I'd like to see the complete output of 2 merged files where each difference is marked in the same way as git marks conflicts in the files. The use case is to merge 2 similar configuration files, inspect the merged file and and have visual hints to make evident all differences between the files so that it becomes easy to decide which one to pick.
I have already tried with diff and diff3, but I could only get the differences (with diff) or a fully merged file where only conflicts are marked (with diff3 -m -A file1 file1 file2
). I've used git diff and related tools, but they all merge unconflicting changes, instead of marking them as differences.
The running environment would be a bash shell script, therefore it'd be nice to reach the desired output with common linux tools.
Example:
Contents of file1:
environment:
base_branch: master
branch: this_is_the_same_for_both_files
Contents of file2:
environment:
base_branch: a_different_base_branch
branch: this_is_the_same_for_both_files
a_new_key: the_new_key_value
Desired output:
environment:
<<<<< file1
base_branch: master
=====
base_branch: a_different_base_branch
>>>>> file2
branch: this_is_the_same_for_both_files
<<<<< file1
=====
a_new_key: the_new_key_value
>>>>> file2
Upvotes: 2
Views: 865
Reputation: 551
Following the suggestions from the comments, I came up with this one liner which seems to solve my issue.
I would have liked to use constants for the markers in the sed
substitutions, but apparently it's not straightforward to use variables containing \n
with sed
for mac os.
This code seems to work correctly even in docker alpine:3.8 using diffutils. Other options (brew gnu-sed and similar) might not be easily portable.
diff -D AAAAAAA "${path}" <(echo -n "$decrypted") | \
sed -e $'s/#ifndef AAAAAAA/<<<<<<< file-on-disk/g' | \
sed -e $'s/#endif \/\* ! AAAAAAA \*\//=======\\\n>>>>>>> file-from-secret/g' | \
sed -e $'s/#else \/\* AAAAAAA \*\//=======/g' | \
sed -e $'s/#ifdef AAAAAAA/<<<<<<< file-on-disk\\\n=======/g' | \
sed -e $'s/#endif \/\* AAAAAAA \*\//>>>>>>> file-from-secret/g';
Explanation:
diff -D AAAAAAA "${path}" <(echo -n "$decrypted")
: outputs a merged text with '#ifdef NAME' diffs. I'm using AAAAAAA as marker name. Diff uses #ifndef AAAAAAA
and #endif /* ! AAAAAAA */
to surround text only present in the first file and /#ifdef AAAAAAA
and #endif /* AAAAAAA */
to surround text only present in the second. Note the n
in the first #ifndef
and the !
in the first #endif
comment. As all markers are different, it becomes easy to perform substitutions.
sed -e $'s/#endif \/\* ! AAAAAAA \*\//=======\\\n>>>>>>> file-from-secret/g'
: substitutes the marker with
=======
>>>>>>> file-from-secret
As there is a \n
, the substitution string is enclosed with $''
which interprets correctly the new line character. However, the \
needs to be double-escaped.
Upvotes: 2