LD2OZ7CID2SF7HSK5FT5OKSPWICRCR6JYBKNEUNWOU6USPNO7EBQC
Pijul has a number of features that allow it to scale to very large repositories and fast-paced workflows. In particular, **change commutation** means that changes written independently can be applied in any order, without changing the result. This property simplifies workflows, allowing Pijul to:
Pijul has a number of features that allow it to scale to very large repositories and fast-paced workflows. In particular, **change commutation** means that changes written independently can be applied in any order, without changing the result. This property simplifies workflows, allowing Pijul to **clone sub-parts of repositories**, to **solve conflicts reliably**, to **easily combine different versions**.
- **clone sub-parts of repositories**
- **solve conflicts reliably**
- **easily combine different versions**.
- **[Use case: early stage of a project]** Change commutation makes Pijul a
highly forgiving system, as you can "unapply" (or "unrecord")
changes made in the past, without having to change the identity of
new changes. A reader familiar with Git will understand "rebasing", in git terms).
- **[Use case: In the early stage of a project]** Change commutation
makes Pijul a highly forgiving system, as you can "unapply"
(or "unrecord") changes made in the past, without having to change
the identity of new changes. A reader familiar with Git will
understand "rebasing".
changes they are interested in. Those changes *do not* change when
imported, which means that pulling new changes in will work just as
changes they are interested in. Pulled changes *do not* change when
imported, which means that pulling new changes it will work just as
In Pijul, change application is an *associative* operation, meaning
that applying some change A, and then a set of changes (BC) at once,
yields the same result as applying (AB) first, and then C.
In Pijul, change application is an associative operation, meaning
that applying some change A and then a set of changes (BC) at once
yields the same result as applying (AB) first and then C.
The second scenario would look like the following, with Bob creating
commit A, and then pulling B. At that moment, Bob has both A and B on
his branch, and wants to pull C from Alice.
The second scenario would look like the following: Bob creating
commit A and then pulling B. At that moment, Bob has both A and B on
his branch and wants to pull C from Alice.
sound like nitpicking, because intuition suggests that it should
always be the case. However, **Git doesn't guarantee that property**,
sound like nitpicking because intuition suggests it should always be
true. However, **Git doesn't guarantee associative change property**,
Concretely, this means that Git (and relatives) can **sometimes shuffle lines around**, because these systems *only* track versions, rather than the changes that happen between the versions. And even though one can reconstruct one from the other, the following example (taken from [here](https://tahoe-lafs.org/~zooko/badmerge/simple.html)) shows that tracking versions only does not yield the expected result.
Specifically, Git (and relatives) can **sometimes shuffle lines around**,
because these systems *only* track versions rather than the changes that
happen between the versions. And even though one can reconstruct one from
the other, the following example
(taken from [here](https://tahoe-lafs.org/~zooko/badmerge/simple.html))
shows that tracking versions only does not yield the expected result.
In this diagram, Alice and Bob start from a common file with the lines A and B. Alice adds G above everything, and then another instance of A and B above that (her new lines are shown in green). Meanwhile, Bob adds a line X between the original A and B.
In this diagram, Alice and Bob start from an identical file with lines A and B.
Alice adds G above everything and then another instance of A and B above that
(her new lines show green). Meanwhile, Bob adds a line X between the original A
and B.
This example will be merged by Git, SVN, Mercurial… into the file shown on the left, with the relative positions of G and X swapped, where as Pijul (and Darcs) yield the file on the right, preserving the order between the lines. Note that this example **has nothing to do with a conflict**, since the edits happen in different parts of the file. And in fact neither Git nor Pijul will report a conflict in this case.
Git, SVN, and Mercurial will merge this example… into the file shown on the
left, with the relative positions of G and X swapped, whereas Pijul
(and Darcs) yield the file on the right, preserving the order between the
lines. Note that this example **has nothing to do with a conflict** since the
edits happen in different file parts. Furthermore, neither Git nor Pijul will
report a conflict in this case.
The reason for the counter-intuitive behaviour in Git is that Git runs a heuristic algorithm called *three-way merge* or *diff3*, which extends *diff* to two "new" versions instead of one. Note, however, that *diff* has multiple optimal solutions, and the same change can be described equivalently by different diffs. While this is fine for *diff* (since the patch resulting from *diff* has a unique interpretation), it is ambiguous in the case of *diff3* and might lead to arbitrary reshuffling of files.
The reason for the counter-intuitive behavior in Git is that Git runs
a heuristic algorithm called three-way merge or diff3. Diff3 extends diff to
two "new" versions instead of one. Note, however, that diff has multiple
optimal solutions, and a single change can be described equivalently by
different diffs. While this is fine for diff (since the patch resulting from
diff has aunique interpretation), it is ambiguous in the case of diff3 and
might lead to an arbitrary reshuffling of files.
Obviously, this **does not mean that the merge will have the intended semantics**: code should be still reviewed and tests should still be run. But at least a **review of the change will not be made useless** by a reshuffling of lines by the version control tool.
It is prudent to note that change associativity
**does guarantee the result will have intended semantics**, because languages
have context-specific rules. Every change should be tested and go through code
review. However, **the code review won't be made pointless** by reshuffling
lines by the version control tool.
Conflicts are a normal thing in the internal representation of a Pijul
repository. Actually, after applying new changes, we even have to do extra work to find where the conflicts are.
Conflicts are a regular thing in the internal representation of a Pijul
repository. After applying new changes, we have to do extra work to find where
the conflicts are.
In particular, changes editing sides of a conflict can be applied
without resolving the conflict. This guarantees that no information
ever gets lost.
In particular, edits from both sides of a conflict get applied without
resolving the conflict. This guarantees no information ever gets lost.
- In Git, conflicts are not really handled after they are output to
files. For instance, if one commits just after a conflict occurs,
git will commit the entire conflict (including markers).
- Git writes conflicts into the working directory and refuses to
commit any changes to the repository until conflicts get manually
resolved.
according to formal axioms that guarantee correctness in 100% of
cases, whereas commits have to be /stitched together based on their
contents, rather than on the edits that took place/. This is why in
these systems, conflicts are often painful, as there is no real way to
according to formal axioms that guarantee correctness in 100% of cases.
In contrast, commits have to be /stitched together based on their
contents rather than on the edits that took place/. This is why
conflicts are often painful in these systems, as there is no natural way to
- Fast algorithms: Pijul's pristine can be seen as a "cache" of
applied changes, to which new changes can be applied directly,
without having to compute anything on the repository's history.
- Fast algorithms: Pijul's pristine can be seen as a "cache" of applied
changes to which new changes can be applied directly without having
to compute anything on the repository's history.
However, Pijul's pristine format was designed to comply with axioms on
a specific set of operations only. As a result, some of darcs'
features, such as `darcs replace`, are not (yet) available.
However, Pijul's pristine format is designed to only comply with axioms on
a specific set of operations. As a result, some of the Darcs'
features, such as `darcs replace`, have yet to be made available.