First of all, thanks for the response. > This is not what happens, because your proposition was that b is constructed from a via ln. So, a and b point to the same inode. In the second run, redo links a to $3. Now, a, b and $3 point to the same inode, regardless of whether redo mv's $3 to a afterwards or not. This is where the toolchain breaks, because it looks like a changed underneath, because all three point to the same inode. I disagree with this, maybe there is a misunderstanding. My setting is the following. I have two .do files: a.do with the line echo aaa # or whatever and b.do with the two lines redo-ifchange a ln a $3 Now I call "redo b". This gives me the following files with "stat --format="%n: inode=%i, mtime=%Y" a b": a: inode=646, mtime=1667292427 b: inode=646, mtime=1667292427 Now if I change a.do to echo bbb # or whatever and I "REDO_INODE_TRUST=mtime redo a" (ctime already complains because `ln` changes the ctime for "a"), I get the files a: inode=655, mtime=1667292495 b: inode=646, mtime=1667292427 So we can see that "b" is not changed, and "REDO_INODE_TRUST=mtime redo b" also works and the output is as expected a: inode=655, mtime=1667292495 b: inode=655, mtime=1667292495 However, if a.do is now changed to echo bbb # same output as before and we call "REDO_INODE_TRUST=mtime redo a", then the mtime for b is messed up: a: inode=655, mtime=1667292646 b: inode=655, mtime=1667292646 # wasn't redone, but changed If we now call "REDO_INODE_TRUST=mtime redo b", we get the warning warn b externally modified: not redoing which is due to "a" being touched (as the file hash is equal to $3). This does not happen if $3 was renamed to "a", as then "b" would point to the old inode. If the attached patch is applied to run.go (basically remove the block that touches the file when the hash matches), then this issue does not occur, as the file "a" will have a new inode number in the last example. I hope the example makes the point a bit more clear. Sorry that it got so long.