The sound distributed version control system

#128 `git rebase` function-a-like?

Opened by cole-h on November 27, 2020 Feature request
cole-h on November 27, 2020

I sometimes find myself wanting to modify a sequence of changes. With git, I’d use git rebase -i HEAD~[# of commits to change]. It would be very useful to have similar functionality to make changing a series of records easier. As it stands, my workflow is the following:

  1. Dump the contents of the changes that depend on the change I want to modify to a file with pijul change HASH > #.diff
  2. pijul unrec all those changes
  3. Make note of the current change’s hash and pijul rec --amend it
  4. Modify all references to the “current change”’s hash to point to the new hash after amending it.
  5. pijul apply < #.diff, make note of the new hash for this change
  6. Change the old hash of that change in all dependents to the new hash
  7. Repeat steps 3 to 6 until done

I’d hope that, with a git rebase function-a-like, the steps would simplify down to:

  1. pijul rebase -i some-shorthand-for-number-of-changes-to-go-back-in-history
  2. Somehow communicate that I want to edit change e.g. AJSKLDJ, then save and quit the editor

At this point, I should be able to only see the chosen change in my pijul log (and all prior changes).

  1. Make necessary changes, pijul rec --amend AJSKLDJ, save and quit
  2. pijul rebase --continue, which would re-apply all following changes

I imagine this will be more involved than I make it seem because of the change format containing all the dependencies…


Sorry for all these drive-by suggestions, but I think some / most of them (especially this one) are necessary for improved ergonomics.

pmeunier on November 28, 2020

I don’t quite understand what you’re trying to do.

Your really need to know what you’re doing before you start changing arbitrary things in a change in text format. The only thing safe is to delete numbered items (if your change can still be parsed).

If a change depends on another one it is usually for a good reason, not just to annoy the user! You can’t just change the hashes like that in the text format and hope everything works.

pmeunier on November 28, 2020

Just an extra note: in the text format, Pijul ignores all lines starting with -. Lines starting with a + are parsed as blocks of bytes. All the other lines are super important and can’t be touched arbitrarily.

cole-h on November 28, 2020

Sorry, I think I was unclear.

What I want is to be able to do the various actions git rebase -i supports, such as rewording a change message, editing the change itself, or squashing a change into a previous change. That’s the kind of feature I’m looking for,

My above example is closely related to #127 – if I want to simply change the message of a specific change, I have to unrecord all dependencies before I can --amend that change.

Ideally, I’d want to be able to say “Hey, this change message is wrong, let me fix it.” without needing to manually unrecord changes, or say “These changes are all related but were pushed separately for ease-of-review. I’d like to meld them all together now.”

Is that a little clearer? These things can be done manually, but they’re immensely tedious.

pmeunier on November 28, 2020

Oh, alright. This is absolutely clear. I often need to squash changes, and I also don’t like the way it’s done currently. Concatenating them could work, but would yield a super ugly change, probably losing a lot of the “actions” metadata (“this is a replacement, a conflict resolution…”).

levi on December 13, 2020

Patches in Pijul commute. This whole rebase thing should by far simpler than in git. I see this roughly like that, to split changes (as an example):

pijul split HASH

Text editor opens up, and what I would like to extract and move to a new record should be preceded by a symbol, let’s say $.

Scenario 1

$Readme.md
+ Here is 
-        Some 
+    Code I want to split
+ Unimportant_file.rs
+ Some code

Would move all changes from this record and related only to this file(or files) to the new record.

Scenario 2

Readme.md
+ Here is 
$+        Some 
-    Code I want to split
File.rs
$+ Some more 
$-  code

Changes from Readme.md, File.rs would be moved to the new record.

Scenario 3

Readme.md
$+ Here is 
$$+        Some 
-    Code I want to split
 File.rs
$+ Some more 
$$$-  code

Let’s say I want to split one record to three. The idea is to precede every line by one or more $ creating one or more change groups. So one $ would split record in two. Two $$ would create another group. Three $$$ would create third group, and so on

Then, for every extracted group, Pijul should ask us to provide new message for every new record associated with those group . And do this in order groups were introduced. Maybe its not very intuitive but fast, when we want to split on big change for every file, group of functions or classes.

Eventually enclose new split in a block like ${...}, $${...}, $$${...} Not sure how that would be “code editor friendly” but I can’t come up with anything better. It seems simple and corresponds well with existing margin markers like “+” and “-” also should be fast and easy to parse for other tools, like VSCode plugins or other GUI tools. Of course the $ split tags should only be temporary, dropped after editing and not be saved explicitly anywhere to not pollute the changeset.

Just rough idea. Maybe someone will refine it, or be inspired by it.

PS. I have just played with the idea in text editor to see how this feels. It’s better than I originally thought, and not so obvious to brake things. If pijul split would not allow to break the changeset and reject anything but split prefix $ or split range ${....} I think this idea is worth considering.

pmeunier added tag Feature request on December 7, 2021
joyously on February 23, 2022

What would be the expected result of a squash on the history? Before a squash, you could list all the changes. After a squash, those would not be known anymore? I was thinking of it in terms of putting all the designated changes into a channel and then squashing the channel into a single change. But I don’t know if the command would be expected to affect the original or not.

coconut on February 28, 2022

Someone mentioned the implementation of topics that Mercurial has. It might come in handy in terms of metadata and whatnot. We could keep a history of records under particular topics and denote whether or not they have been “squashed” or “merged” or whatever. We could do this without topics, too, I think. You can easily draw it using ASCII as well, although you really do have to make sure people realize that we are talking about hashes that no longer exist, because they have been squashed into another. This would make pijul use more space, and probably would affect performance to a certain extent; not sure by how much.