Official Reporitories and Official History

Thinking about tickets:

https://nest.pijul.com/pijul_org/pijul/discussions/77
https://nest.pijul.com/pijul_org/pijul/discussions/76

I think this is a more simple idea than these tickets. The idea is to define each branch as 2 components: the history and the patchset

  • The patchset is the set of patches currently included in the branch. Without “official” order.
  • The history is the sorted sequence of actions executed in the branch. Valid actions are:
  1. Add a patch to the patchset of the branch by recording or pulling/pushing it.
  2. Remove a patch from the patchset of the branch by unrecording or pulling/pushing it.
  • Every action realized in the branch is recorded in him history.

The benefits of having a history are:

  • The user can recover the exact patchset used in any time in the branch by position in the history. Then, by positions in the branch, in the official repository, we can identify any historical and official “snapshot” of source code.
  • Pulling and pushing can be implemented with complexity linear to the number of new changes in history (added/removed patches from the patchset) in the ideal case.
  • In the nest, when i wish to see the recent changes in any repository, i can see the recent changes in the history, that always is lineal, with immutable past. Without lost the flexibility in the patchset, that have no order.
1 Like

I edited the text, for more clarity. Sorry my English.

The order in which patches are applied is already recorded, and will be used to make patchset fetching faster.

One tricky thing is that when you pull, you might have a different history, and have some of the patches, so different users with the same repository could have different histories (that’s a feature).

We don’t have official tags at the moment, but when we have them, you could make every patch a tag to share history (that’s the equivalent of a “commit” in git, except that patches behave better wrt merging).

1 Like

We already had this discussion before, but I really think there are two things to consider when we talk about patch ordering:

  1. Pulling only a subset of patches, then pulling the rest
  2. Pulling a set of patches

In 1. I agree it shall result in a different history and pijul effectively deals with this pretty good. In 2., however, I personaly expect pijul to keep the same patch order as the remote. Similary, there is actually an issue in the nest right now which made me think there were no activity since begining of June.

The nest think might be specific to the nest and not pijul, but I know that when you clone a repo, you may get a different history order and I feel it is both confusing and unconvenient. I would love to help “fixing this issue” if we agree this is effectively an issue.

1 Like

I agree with you @lthms

But, i really would like if i can select a revision with a simple number in the history of the branch. That revision number identify the patchset used in that revision in that branch, in other branch can identify other patchset.

It looks like @pmeunier has done some work about that. Thanks a lot for that!

1 Like

Alright, now patches should be in order again. The order on the Nest is still a bit weird because of old bugs in libpijul. These bugs are hopefully now fixed. I still have to clone all those repositories on the Nest to restore a consistent order for applied patches.

1 Like

Cool, i really like that. I question: can pijul have a history as a first class concept or that goes against the principles of pijul? The history doesn’t have to be inmutable really. Each revision represents changes to the patchset not to the files directly.

The history can use nested numbers in the revisions. Bazaar implements something similar. When i merge two branch, that results in a nested history, where i can see the remote history embedded in my own main history.

Example of nested histories in bazaar:

fmccann$ bzr log -n0

------------------------------------------------------------
revno: 2 [merge]
committer: Fred McCann <fred@bzrinit.com>
branch nick: recipe
timestamp: Thu 2015-12-19 19:50:47 -0500
message:
Initial recipe based on a cookbook method
------------------------------------------------------------
    revno: 1.1.2
    committer: Fred McCann <fred@bzrinit.com>
    branch nick: cookbook
    timestamp: Thu 2015-12-19 19:28:08 -0500
    message:
      Needs more cocoa
------------------------------------------------------------
    revno: 1.1.1
    committer: Fred McCann <fred@bzrinit.com>
    branch nick: cookbook
    timestamp: Thu 2015-12-19 16:08:52 -0500
    message:
      First version of cake recipe 'borrowed' from a cookbook
------------------------------------------------------------
revno: 1
committer: Fred McCann <fred@bzrinit.com>
branch nick: recipe
timestamp: Thu 2015-12-19 15:06:17 -0500
message:
Started cake project

You can see more information in https://bzrinit.com/02.html searching by “Hierarchical Logs”.

The question is: can pijul in principle have a history as a first-class concept or is it ruled out?

Would “history as a first-class concept” be different from the following:

As I understand, yes. In the following:

  1. The history as first class concept is “active” all the time for all branches. Any branch has his own history always. Each revision in history specify what patches are added and removed from the patchset.
    1.1 People can use the revision numbers when bisecting, and as easy identifier for a patchset.
  2. If i make a tag for every patch to share history, i have these questions (maybe i understand it wrong, and with “make every patch a tag” you are telling what i understand as revisions):
    2.1. How we represent that i remove a patch from the patchset of the branch? What type of tag can we use, if the tags are associated to patches and not revisions in a history?
    2.2. The patch’s tag represent the patchset with that patch and his dependencies only or all patches ?
  3. If pijul use nested histories (as nested logs in bazaar), we are sure that when we push to “master” branch, exists a revision with the exact same patchset we use in our development branch. There is another revision that combines the changes of the development branch and the master. The two revisions are different and both have a easy identifier, not a difficult hash as identifier.
  4. Developers are already familiar with the concept of history. And having a history doesn’t need to limit pijul in any form, because revision are about patches and not files or lines directly.

I hope my english is not vey bad.

Maybe I wasn’t clear about what a tag is. A tag in Pijul would be a patch that does not necessarily introduce new changes (although it might), but is marked as depending on all patches on the branch. It is equivalent to a “revision”, I guess.

You can’t at the same time want to be able to change history and to recover the “true” history. In the solution we want in Pijul, if you want to edit history, you would have to first unrecord the “tag patch”, and then take patches out.

I honestly don’t believe so, but that might be because I’m not sure what that concept is. I believe I understand it pretty well in the case of people who, at the same time:

  • always work alone, or work with others but on totally disjoint parts of a project (never edit anything they didn’t write in the first place).
  • never use automated tools (such as 3-way merge) to change their source code in any way
  • and moreover never need to revert their mistakes (or never make mistakes to begin with), but just want to be able to revert their last edit.

I don’t know if Pijul is the right tool to handle such workflows.

I think i understand. Sorry if I insist but as i see history, we are not losing the adventages of patch-theory. Imagine this situation:

  1. Alice starts an empty branch B. Alice records a patch P1 in B. The history is:

::::b::::

  1. Added patch P1

The patchset is: {P1}


  1. Alice records a patch P2 in B. The history is:

::::b::::

  1. Added patch P1
  2. Added patch P2

Patchset: {P1, P2}


  1. Alice unrecords P1. The history is:

::::b::::

  1. Added patch P1
  2. Added patch P2
  3. Removed patch P1

Patchset: {P2}


  1. Alice records P1 again. The history is:

::::b::::

  1. Added patch P1
  2. Added patch P2
  3. Removed patch P1
  4. Added patch P1

Patchset: {P2, P1}


The “true” history is recoverable and we can use automated tools, revert mistakes, etc. Apart from history, the patchset can be seen as the “effective” history. When i want to see the “true” history of chages to the branch, i see the history. When i want to see the history of changes over files, i see the “effective” history in the patchset. Maybe that sounds complicated for the final users, but i’m not inclined to think so.

Well, patches are already ordered in Pijul, even though a few bugs in the Nest prevent the actual ordering from being displayed correctly.

Patch “removal” (unrecord) cannot be recorded, because this is the only mechanism to “edit history”. However, patches can be inverted in Pijul, even though the commands for that are not yet implemented. When you invert a patch, you create another patch (which will be applied in a particular order).

We could of course add a “log file” somewhere to keep track of that.

That said, your example is still about a single person working alone. Sharing history of the repository doesn’t always make sense.

As in Bazaar this “true” history can always made sense only relative to its own branch. In other branches, the same patchset can be obtained with very diferent histories. Pijul have the adventaje that for push/pull can use the patchset and not the history. The history can be used only as optimization and if is equivalent to use the patchset. The histories in Bazaar can be nested. I imagined the mixing of those ideas. Imagine we have Alice with the branch BranchAlice and Beto with branch BranchBeto and Alice and Beto do the following:

  1. Alice records the patch A1 in BranchAlice.

BranchAlice: {A1}

1. Added A1

BranchBeto: {}


  1. Beto records patch B1 in BranchBeto.

BranchAlice: {A1}

1. Added A1

BranchBeto: {B1}

1. Added B1

  1. Beto pull from BranchAlice to BranchBeto.

BranchAlice: {A1}

1. Added A1

BranchBeto: {B1, A1}

1. Added B1
1.1.1 Added A1
2. Merge from revs 1 and 1.1.1

  1. Beto records patch B2 in BranchBeto.

BranchAlice: {A1}

1. Added A1

BranchBeto: {B1, A1, B2}

1. Added B1
1.1.1 Added A1
2. Merge from revs 1 and 1.1.1
3. Added B2

  1. Alice pull from BranchBeto to BranchAlice

BranchAlice: {A1, B1, B2}

1. Added A1
1.1.1 Added B1
1.1.2 Added B2
2. Merge from revs 1 and 1.1.2

BranchBeto: {B1, A1, B2}

1. Added B1
1.1.1 Added A1
2. Merge from revs 1 and 1.1.1
3. Added B2

This way, the history of branches BranchAlice an BranchBeto is very different, but:

  1. In each branch, the history made sense.
  2. In each branch, i can name a patchset by his rev number. Many rev numbers can match the same pathcset.
  3. Bisecting is easy with the history.
  4. In step 5, if Alice want to see the exact same patch set that BranchBeto has before the merge, Alice can use the rev number 1.1.2 in its own history.
  5. the final patchset in both branches is the same.

If pijul use a history of patches (not of files), the unrecord of a patch can be recorded (added to the history).

I see.

That exact situation is already possible in Pijul with the “all patches are tags” mode (not yet implemented, but easy to do).

But from your previous comments, I believe you have something more subtle in mind. Could you please describe the more complex situation where after all that, Beto removes patch B1, and Alice pulls?

How does Alice’s history look like?

I can see a problem with that, where i put the new revision removing the patch?, bellow what revision? I need to think more about that and to review if is possible to adapt what bazaar does in this case. I’ll write here when i have a satisfactory response.

Little Question: how do you envision bisecting works with the “all patches are tags” model?

Could you tell me what you think that model is? What would be the problem with bisecting?