The sound distributed version control system

#342 [Feature request] Tools to deal with spurious dependencies.

Opened by unidual on February 20, 2021 Feature request
unidual on February 20, 2021

Context: I wanted to pijul apply a patch in a channel, regarding uniquely file A. It ended up pulling far more than expected, and modifying file B unwillingly.

I suspect it is because while working on file A, I corrected a typo in file B, and the unrelated changes went on the same record. Now I have 5 problems, 2 of which concerning pijul:

  • I didn’t found any easy way to undo the apply.
    • I tried to unrecord the ‘oldest’ patch I didn’t want, but was blocked since other patches depended on it. I wished there were a flag to unrecord all the dependents.
    • I resorted to unrecord --show-changes (I perfectly understood the ‘do not delete the hashes you want to be unrecorded’ approach, yet found it error-prone).
  • Fixing the initial problem seems quite difficult. I don’t see an easy way to locate the infringing record (the one containing 2 unrelated changes). Even if I did, the splitting solution wouldn’t work since I cannot unrecord (due to dependents).

I have some suggestions, not sure about the fitness of the approaches:

  • Add --dry-run option to apply to see which patches will be applied and which files will be impacted.
  • Be able to filter changes. E.g. apply changes only for one particular file or directory. That means we would actually apply sub-patches, with potentially less dependencies.
  • Even more crude, be able to update a file from another channel. If it can be done by applying patches (i.e they don’t touch other files), let it be so, otherwise just update the file in the working directory.
  • At record time, warn if there is more than 1 dependency.

The patch dependency system is powerful, but I guess that power can play against distracted people like me.

unidual on February 21, 2021

Another exemple of false dependencies:

  • Refactoring a whole codebase (e.g. reformat, s/master/main, s/slave/jean_louis, #include clean-up, …).

It will touch many files, possibly all of them. Hence create many unwanted dependencies, despite the changes being independent (well in case of reformat or clean-up, for renaming, that’s a bit tougher).

So the notion of sub-patches (the intersection of a patch and a path) would be really helpful. Now the problem becomes: how to indicate that hunks in a record are independent, so we can dispatch the dependencies on a per hunk basis to prevent following them all.

unidual on February 21, 2021

(I perfectly understood the ‘do not delete the hashes you want to be unrecorded’ approach, yet found it error-prone).

Actually my brain was kind of confused by: Delete the hashes you want to keep.
But I realised there is another option: just prefix them!
Maybe I could update the doc:

# Please select the changes to unrecord. The lines that contain just a
# valid hash, and no other character (except possibly a newline), will
# be unrecorded.
# In particular, it means that if you delete a hash or prefix it by K, 
# Keep, "Please don't touch" or + (your preference really), the change will be kept.

Oh, and also:

# Delete the whole file before exiting to cancel.

Which can be a bit perturbing. So maybe the opposite approach should be preferred: “Prefix the hash by u: to unrecord it”.

unidual on February 21, 2021

how to indicate that hunks in a record are independent, so we can dispatch the dependencies on a per hunk basis to prevent following them all.

One way might be to give the user the possibility to flag this change as a new “base” (e.g. --milestone or --freeze) , so that the dependencies aren’t followed past that (except for the files to modify at this point).

This status could be also used to discard this change from pijul credit (e.g. we want to skip the reformatting, which otherwise would pollute most of the annotation). Or perhaps this should be an independent feature!

pmeunier added tag Feature request on December 7, 2021