I think the big difference between redo and make is that make requires knowledge of dependencies up front, and this is sometimes tricky to get right.
"as you can see in default.o.do, you can declare a dependency after building the program. In C, you get your best dependency information by trying to actually build, since that's how you find out which headers you need. redo is based on the following simple insight: you don't actually care what the dependencies are before you build the target; if the target doesn't exist, you obviously need to build it. Then, the build script itself can provide the dependency information however it wants; unlike in make, you don't need a special dependency syntax at all. You can even declare some of your dependencies after building, which makes C-style autodependencies much simpler."
It's actually quite simple. You write a short shell script to produce the output you need and redo handles the dependencies.
For example, the shell script named "banana.x.do" is expected to produce the content for the file named "banana.x".
When you say
# redo banana.x
redo invokes banana.x.do with the command:
sh -x banana.x.do banana.x banana XXX > ZZZ
so banana.x.do is invoked with three arguments and its output is redirected to a file.
$1 denotes the target file
$2 denotes the target file without its extension
$3 is a temp file: XXX, in this case.
banana.x.do is expected to either produce output in $3 or write to stdout, but not both. If there are no failures redo will chose the correct one, rename the output to banana.x and update the dependency database.
If banana.x depends on grape.y, you add the line
redo-ifchange grape.y
to the banana.x.do, creating a dependency.
redo will rebuild grape.y (recursively) when necessary.
The only other commands I haven't mentioned are init and redo-ifcreate, which are obvious and rarely used, respectively.
"as you can see in default.o.do, you can declare a dependency after building the program. In C, you get your best dependency information by trying to actually build, since that's how you find out which headers you need. redo is based on the following simple insight: you don't actually care what the dependencies are before you build the target; if the target doesn't exist, you obviously need to build it. Then, the build script itself can provide the dependency information however it wants; unlike in make, you don't need a special dependency syntax at all. You can even declare some of your dependencies after building, which makes C-style autodependencies much simpler."
https://github.com/apenwarr/redo