The sound distributed version control system

#89 It would be nice to have a "staging area" for changes

Opened by cole-h on November 17, 2020
cole-h on November 17, 2020

I don’t know how adverse this is to Pijul’s philosophy, but it would be very nice to have a staging area for changes. This may just be me longing for git functionality, but too many times now have I forgotten to remove some unrelated changes from the pijul rec window, only to notice after I’ve pushed. While pijul add already exists, a pijul restore (or similarly named command) would be a good companion.

pmeunier on November 17, 2020

I agree the staging area in Git is nice, but I wonder whether we could do that with just pijul rec --amend. Have you tried that command?

cole-h on November 17, 2020

I have indeed used pijul rec --amend to drop unrelated changes in the past, but when those changes are in Cargo.lock and multiple other files, it quickly becomes a hassle to track down which files I actually wanted in that record. I probably just need to use pijul more and stop comparing everything to how git does things.

robx on November 22, 2020

Some thing to try first maybe is to make pijul rec a bit more friendly to recording partial changes. E.g. some interactive version like what git add -p does, where you can pick changes one-by-one or by file.

Or allowing to record multiple changes from one pijul rec editing session, by grouping them under different change header sections.

Or instead of staging changes, there could be some support for marking certain changes as “irrelevant”? Along the lines of pijul rec --ignore Cargo.lock which creates a change that is somehow tagged as “ignored”, and thus wouldn’t be pushed by default. Maybe along with something like pijul unrecord --ignored which would drop all these irrelevant changes.

pmeunier on November 22, 2020

I agree with all those comments. First, a general note (not an answer): any line starting with # is ignored in the change format.

I can think of multiple options:

  • Editor modes. I started to work at some on a VSCode mode for Pijul to try and think about what would be needed to do that. Even though I don’t use it myself, VSCode is by far the most popular text editor nowadays. See my attempt there: I believe this sort of stuff could make editing changes easier.

  • Extra commands in change and record, for example pijul record --amend HASH --drop-files Cargo.lock. Can we think of a complete set of useful commands?

  • @robx: I was thinking of a more convoluted thing where “parked” changes would be kept on a separate channel, but this is super Git-like, your idea is way better. I guess these could be kept in the .pijul/config and editable both manually and with the commands, what do you think?

dnaq on December 3, 2020

When using amend to drop changes from a patch we can’t really drop the dependencies from the changes (since we as a user don’t know them). So as it stands now it’s pretty easy to remove changes from a patch, but the patch will still depend on things that it shouldn’t.

Skia on December 8, 2020

There are plenty of good things to be said for Git stage. I am just going to bring up one pit fall with it as implemented in Git. To be clear, I do use stage changes when working with Git despite the potential issues I am going to describe. If there is a demand for staging changes, implementing such a feature would still be worth while even if these problems cannot be avoided. Plenty of developers likely never use hooks, which the issue I am bringing up revolve around.

When a file is staged in Git, it is copied to a staging area. This copy is the version that will be committed if only staged changes are committed. The problem comes when you are using hooks to check files for correctness before committing.

Say you have a hook apply some formatting rules (Pijul uses rust-fmt to do this). What if the staged file is not correctly formatted, but the working copy is correctly formatted for some reason? The hook would need to know to run the formatting program on the staged copy.

Also problematic for a naive formatting hook that runs against the working copy would be if the working copy is incorrectly formatted. And the working copy has additional changes not in the staged copy. If the formatting hook is actually fixing the files before the commit / record, if it then stages the properly formatted version overwriting the intended changes.

Finally, hooks that work on individual files can be made to run on the staged versions. But what if a hook does some action that involves additional dependencies? Such as running a code linter. If a staged file depends on another that has no staged changes, but the working copy has been altered how would this be resolved?

Never mind if there is something going of with files that are non-versioned in the the repository (say the contents of the node_modules folder in a NodeJS project that impacts the hook.

I cannot really see a good way to implement staging of changes that meets all the following:

  • convenient to use for the user
  • reasonable in terms of complexity to implement and maintain the code
  • avoids possible pit falls in relation to hooks

There is maybe one way to do it all, but it would only be “convenient to use for the user” when working through a graphical interface, which would put it more of a feature for a plugin for a code editor / IDE than something to add to the main CLI tool.

Basically, it would be less staging changes and then recording them and more stash the changes, reset the working directory, and then reapplying parts of the change set at a time and recording the partial changes. It is reapplying parts of a larger change set that would be hard to make convenient to use for a CLI program.

pmeunier on January 13, 2021

I moved a bit on this:

  • One of the things in Git that allows staging to work is that there are no files in Git, just blobs and trees. The index can therefore be just an extra tree. In Pijul, because we want filesystem changes to commute with other changes, we can’t do that.

  • Another thing is, since there is no patch editing in Git, Git can delete the entire contents of the index, whereas we might want more flexibility.

  • In order to move forward anyway, I implemented something to allow implementing a staging area independently from Pijul itself, by adding two options to pijul record: one is --working-copy, which allows one to specify a different working copy (such as .pijul/index), and the other one is --ignore-missing, which doesn’t record file deletions.