1

Consider the task of finding what has changed in two projects which were forked.

diff -r gets me close: it is capable of finding which files are missing in each target folder, and points out files which have changed by presenting their diffs.

I want to use a custom diff utility. I would like to not have to implement in my diff utility the recursive directory walking logic.

So, I basically just want a program that does what diff -r does, but which does not actually go ahead and run the diffs.

Does such a thing exist?

2
  • Your question isn't quite clear but are you looking for the -q option for diff? Commented Dec 17, 2013 at 6:07
  • 2
    @devnull as it turns out, yup! Commented Dec 17, 2013 at 6:43

2 Answers 2

1

I figured the output of diff -r is already plenty structured enough for me to "get clever" with it. Here's the gist of it.

diff -r proj1/src proj2/src | grep 'diff -r' | cut -d ' ' -f 3,4 | xargs -n 2 sift

where sift is my little command-line char-based diff util which runs circles around diff's diff output.

and using diff (GNU diffutils) 2.8.1

I am open to more elegant solutions as well!

Edit: Thanks @janos, the -q option makes it pretty optimal!

One last thing to mention is that this can be made quite powerful by piping into the opendiff program on a Mac's command line (specifying the corresponding file in the desired dir as target, which of course is already inside a Git repo, right?) to do the manual merging nice and quickly.

In fact setting up opendiff to be used by Git when it needs a human merge is probably the way to go.

It's just that I still have not encountered very many merge conflict situations across the same code repo, it is mainly when forking repos (and having separate repos for divergent projects that contain shared code) that I need to do this kind of merge to manually bring my "primary" projects up to date with the changes made in the trenches.

Sign up to request clarification or add additional context in comments.

2 Comments

You asked and answered this to get a hat, didn't ya ;-)
Ha, nope, I did my typical "type out question and arrive at answer" routine.
0

I think this is more elegant:

diff -rq dir1 dir2 | sed -ne 's/^Files \(.*\) and \(.*\) differ$/\1\n\2/p' | xargs -n 2 sift

The main trick is using -q flag, which will print the differences in brief format, for example:

Files dir1/x and dir2/x differ
Only in dir1: path/to/file
Only in dir2: path/to/another

And then how you parse the output is your matter of taste.

Finally, to correctly handle spaces in the file names:

diff -rq dir1 dir2 | sed -ne 's/^Files \(.*\) and \(.*\) differ$/sift "\1" "\2"/p' | sh

It probably makes sense to wrap this in a function:

xdiff() {
    diff=$1; shift
    dir1=$1; shift
    dir2=$1; shift
    diff -rq $dir1 $dir2 | sed -ne 's/^Files \(.*\) and \(.*\) differ$/'$diff' "\1" "\2"/p' | sh
}

So you can call it like this:

xdiff sift dir1 dir2

7 Comments

Nice, now diff's diffing isn't wasted. Also a nicer regex sieve for less false-positive erroneous matches
What's the p flag to sed s//?
It's not a flag, it's a command: "print". If a substitution is performed, the line will be printed. Due to the -n in sed -ne '...', nothing is printed by default. For lines that don't match the pattern, there will be no substitution, and they won't be printed.
I see that sed -n 's///p' is some sort of way of obtaining grep, i.e. print lines that match. Why not just grep? Edit: Oh. Okay, it's actually doing a substitution as well. Two birds one stone.
One thing that I like about my answer though, is that it automatically filters out binary files!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.