Recording, splitting and combining changes

When working on code in your repository, you might come to a point where you feel that the pijul log doesn’t look quite as nice as it could: Some changes don’t work on their own, or some change is changing unrelated pieces of code. So you’d like to re-arrange (split and / or combine) your changes so that other, well-cut changes result.

On this page, you can learn how to achieve pijul log nirvana with the tools at hand.

Recording a change

After editing the files in your repository, you want to make pijul aware of the changes. You already came across the command(s) to do that: pijul add any files that aren’t tracked yet (probably using the -r flag for directories), and then pijul record all changes.

pijul record opens an editor for you containing a view of the change as it will be recorded:

message = ''
timestamp = '2020-12-07T06:59:38.257226181Z'

[[authors]]
name = 'me'
full_name = My Name
email = 'me@gmail.com'

# Dependencies
[2] 5PI4BUI3SDD23P7V3NNCA3FR6NA7YCMF7PJRIJNMZH5TGDA7AGWQC
[3] H6EG7X443HN5LXRZ3TZLRQSIGW46NXGOMFXT2NP6KBGUKVDMF4RAC
[4]+NM32CQUCZLDJIE3H4SZJU35WJTWES6X2CAVWVZCPDEINQKHYAXTAC

# Changes

1. File addition: "file3.txt" in "/" 644
  up 1.0, new 0:11
+ ui
+ ae
+ nr
+ td

2. Edit in file2.txt:2 3.12
B:BD 3.22 -> 3.22:31/3
- uiaeuiae

3. Edit in file2.txt:3 3.12
  up 3.40, new 26:35
+ uiaexvlc

4. Edit in file.txt:4 4.11
  up 2.5, new 36:49
+ xvlcuiaexvlc

You can see the file is divided into three big blocks: the preamble with metadata about the change like message and author; one block describing the dependencies of this change; and one block containing a representation of all changes you made since recording the last change.

To finish recording, this file needs to be edited a bit and saved, and the editor window needs to be closed.

The message field has to be filled in, the fields under the [[author]] heading can be changed. Changes between # Dependenices and # Changes will not be regarded by pijul; the dependencies will be computed after you close the editor window. This part is purely informational.

The diff below # Changes, however, is where you can get creative with your change. The diff is composed of several small sections. Each section is introduced by an enumeration and a very short description of the diff (in the example you can see Edit in file and File addition) and what file the diff refers to.

You can remove any of these enumerated sections. This will leave the diff out of the recorded change, but your working copy will not be touched. This way, you can split up a big chunk of changes into several small ones or - if there were changes you didn’t want to keep in your repo - pijul reset whatever is left.

Amending

Suppose you (or someone else working in the same repository) have already recorded a large change, which you want to split into two separate changes (maybe because you’d like to be able to push just one):

$ pijul change 5HWYGVSSDKMEQP43H3JDSURPS7FJB4TXMAGMUAKSKWIFH6QRZN3QC
message = 'Big change, should be split up'
timestamp = '2020-12-05T15:34:38.416301967Z'

[[authors]]
name = 'me'
full_name = 'My Name'
email = 'me@gmail.com'

# Dependencies
[2] 5PI4BUI3SDD23P7V3NNCA3FR6NA7YCMF7PJRIJNMZH5TGDA7AGWQC
[3]+NM32CQUCZLDJIE3H4SZJU35WJTWES6X2CAVWVZCPDEINQKHYAXTAC

# Changes

1. File addition: "file2.txt" in "/" 644
  up 1.0, new 0:11
+ xvlcxvlc
+ uiaeuiae
+ nrtdnrtd

2. Edit in file.txt:4 3.11
  up 2.5, new 41:54
+ xvlcuiaexvlc

To edit the recorded change, you issue the command

$ pijul record --amend 5HWYGVSSDKMEQP43H3JDSURPS7FJB4TXMAGMUAKSKWIFH6QRZN3QC

An editor will open showing the change (see above, Recording a change). Now, you can remove all sections you don’t want to go into the first change. Whatever you remove, the files themselves will still look the same as before the amend, only the record will have changed.

From here, you can pijul record the next change, again removing any sections you don’t want to have in it. Repeat until done.

Splitting a change

Although amending a change should be enough in most, if not all, scenarios, you might be happy to know there’s an alternative:

By doing pijul unrecord, directly followed by pijul record, and then opening a few instances of your favourite text editor to cut and paste the result into multiple temporary text files, you can pipe them into pijul apply. The whole procedure would look something like this:

Suppose we started with the change from above, and already did pijul unrecord to strip the record of the change, but not the content of the change itself. When you issue pijul record, you will be presented with the following in your editor:

message = ''
timestamp = '2020-12-07T06:59:38.257226181Z'

[[authors]]
name = 'me'
full_name = My Name
email = 'me@gmail.com'

# Dependencies
[2] 5PI4BUI3SDD23P7V3NNCA3FR6NA7YCMF7PJRIJNMZH5TGDA7AGWQC
[3] H6EG7X443HN5LXRZ3TZLRQSIGW46NXGOMFXT2NP6KBGUKVDMF4RAC
[4]+NM32CQUCZLDJIE3H4SZJU35WJTWES6X2CAVWVZCPDEINQKHYAXTAC

# Changes

1. File addition: "file3.txt" in "/" 644
  up 1.0, new 0:11
+ ui
+ ae
+ nr
+ td

2. Edit in file2.txt:2 3.12
B:BD 3.22 -> 3.22:31/3
- uiaeuiae

3. Edit in file2.txt:3 3.12
  up 3.40, new 26:35
+ uiaexvlc

4. Edit in file.txt:4 4.11
  up 2.5, new 36:49
+ xvlcuiaexvlc

Now, you can split this text up into several files as you like, remembering to copy over the preamble of the original, resulting in something like this:

In file1:

message = 'First change'
timestamp = '2020-12-07T06:59:38.257226181Z'

[[authors]]
name = 'me'
full_name = My Name
email = 'me@gmail.com'

# Dependencies
[2] 5PI4BUI3SDD23P7V3NNCA3FR6NA7YCMF7PJRIJNMZH5TGDA7AGWQC
[3] H6EG7X443HN5LXRZ3TZLRQSIGW46NXGOMFXT2NP6KBGUKVDMF4RAC
[4]+NM32CQUCZLDJIE3H4SZJU35WJTWES6X2CAVWVZCPDEINQKHYAXTAC

# Changes

1. File addition: "file3.txt" in "/" 644
  up 1.0, new 0:11
+ ui
+ ae
+ nr
+ td

2. Edit in file2.txt:2 3.12
B:BD 3.22 -> 3.22:31/3
- uiaeuiae

In file2:

message = 'Second change'
timestamp = '2020-12-07T06:59:38.257226181Z'

[[authors]]
name = 'me'
full_name = My Name
email = 'me@gmail.com'

# Dependencies
[2] 5PI4BUI3SDD23P7V3NNCA3FR6NA7YCMF7PJRIJNMZH5TGDA7AGWQC
[3] H6EG7X443HN5LXRZ3TZLRQSIGW46NXGOMFXT2NP6KBGUKVDMF4RAC
[4]+NM32CQUCZLDJIE3H4SZJU35WJTWES6X2CAVWVZCPDEINQKHYAXTAC

# Changes

3. Edit in file2.txt:3 3.12
  up 3.40, new 26:35
+ uiaexvlc

And in file3:

message = 'Third change'
timestamp = '2020-12-07T06:59:38.257226181Z'

[[authors]]
name = 'me'
full_name = My Name
email = 'me@gmail.com'

# Dependencies
[2] 5PI4BUI3SDD23P7V3NNCA3FR6NA7YCMF7PJRIJNMZH5TGDA7AGWQC
[3] H6EG7X443HN5LXRZ3TZLRQSIGW46NXGOMFXT2NP6KBGUKVDMF4RAC
[4]+NM32CQUCZLDJIE3H4SZJU35WJTWES6X2CAVWVZCPDEINQKHYAXTAC

# Changes

4. Edit in file.txt:4 4.11
  up 2.5, new 36:49
+ xvlcuiaexvlc

You don’t need to worry about the # Dependencies block, it just needs to be there. The dependencies themselves will be re-computed by pijul when you record the change.

Now that your 3 files are saved, back out of the original pijul record by closing the editor without a message for your change.

Finish the task by doing

$ pijul apply <file1
$ pijul apply <file2
$ pijul apply <file3

or, if you have a real lot of files, you can do some clever shell script like

$ for file in file*; do pijul apply <$file; done

Combining changes

To combine multiple changes into one, there currently is no better way than running pijul unrecord on all changes you want to combine, and then again pijul record them as described above.