6 ms·
It would be nice if the authors could provide practical examples of their features, instead of a theoretical talk about mathematical soundness. Ie; how does th
by arka2147483647 6y ago
It would be nice if the authors could provide practical examples of their features, instead of a theoretical talk about mathematical soundness.
Ie; how does this make my life, as a programmer, easier?
- gjulianm 6y agoAs far as I understand, the main change with respect to Git is that commit hashes don't change depending on previous history, so if you rebase the same change IDs are retained. Personally I've never had an issue with conflicts after cherry-picking, if Git sees the same change in two branches it manages it correctly most of the time. Furthermore, I like that commit ID changes when previous history is changed: a commit ID refers to a certain state of the repository. I don't like that two repositories in different states could have the same commit ID.
- pmeunier 6y ago> As far as I understand, the main change with respect to Git is that commit hashes don't change depending on previous history, so if you rebase the same change IDs are retained. That is not the main change, merely a by-product. There are many changes: - Perhaps one of the most crucial differences is that Pijul uses a rigorous merge algorithm, and doesn't run into the bad merge examples described in [1]. Note that the situation described there happens without any conflict, and doesn't tell anything to the user. - Changes that could be written independently commute, meaning that they can be pushed independently. You don't have to worry about isolating them on feature branches, which can save time if you (like me) work on many features at the same time. - Rebase and Merge are the same operation in Pijul, and happens automatically. Conflicts happen between changes, and conflict resolutions are recorded as changes, so you don't need any `git rerere` (which essentially guesses what to do), since conflict resolutions work even in a different context. - Everything is invertible! You can even remove an old change from a channel if you like, as long as other changes don't depend on it. > I don't like that two repositories in different states could have the same commit ID. That never happens in Pijul. Changes are not commits, they're diffs between commits. And states have identifiers too, they're just more subtle: if you have two changes A and B, Pijul can apply them in any order without changing the result (so why change the commit id?). In Pijul, if you run `pijul log --state`, on "A, then B" and "B, then A", you will get the same state id. [1] https://pijul.org/manual/why_pijul.html https://pijul.org/manual/why_pijul.html
- vbrandl 6y agoIf the order of changes does not matter and identifiers do not depend on previous changes, ist there still a way to uniquely identify a specific set of changes? With git, I like to include the commit ref in release binaries which is great for debugging since I can just git checkout and see the exact form of the code running on the server. Is there something similar in pijul?
- dan-robertson 6y agoFrom reading the blog posts/source code, I can explain how it works. Here’s a simple way to give a set of changes (a state) an id: 1. Take the hashes of each change 2. XOR them together 3. This is your state ID. The problem is that because of the way you’ve made it (basically adding a bunch of vectors in a vector space over F2), one could use Gaussian elimination to construct any given ID without it being of the intended set of changes. Therefore pijul uses a process which works similarly but in a more cryptographically secure way which makes forging state IDs harder.
- gnufx 6y agoI assume it's the same as with Darcs, where you would record a tag patch. The darcs --exact-version option prints that for a released version of darcs.
- rcthompson 6y agoNot having to worry about the order of patches would (except where they explicitly depend on each other) is a really nice property to have. One consequence of this property, alluded to in the article, is that if I understand correctly, rebasing and merging effectively become the same operation. In Git, the difference between rebasing and merging is the resulting dependency graph of the commits. However, in Pijul, there is no dependency graph, at least not based on the order in which the commits are applied, so rebase and merge are equivalent. For example, have you ever been doing code-review on a Github pull request and made an inline comment on a line of code, only to have that comment later invalidated by a rebase? That happens because the commit hashes were changed by the rebase, so the commit hash referenced by that comment is no longer contained in the pull request. There's probably a new commit with a new commit hash representing the same change, but there doesn't have to be. So Github can no longer be certain of where to place that comment, and it can't tell you whether that comment is still relevant to the pull request in its current state. (IIRC, Github continues to show such comments but marks them as associated with commits that are no longer in the branch, which makes it hard to know if they're still applicable.) In Pijul, I'm pretty sure this problem simply doesn't exist. A hypothetical "Pijulhub" that implemented the same "comment on changes" feature could certainly have comments on old changes that subsequently get removed from the pull request, but if that happens, then "Pijulhub" can confidently declare that those comments are no longer relevant to the current state. On the other hand, if some version of the same change is still present in the current state of the pull request, then "Pijulhub" can confidently continue to include that comment, still associated with that same change, because even after modifying the pull request, that change still has the same hash, because it still represents the exact same change.
- ithkuil 6y ago> A hypothetical "Pijulhub" that implemented the same "comment on changes" A "pijulhub" ready exists and it's called "Nest". There is still a lot of work to do but at least it has a name :-)
- pmeunier 6y agoAbout your guess on the Pijul hub: nest.pijul.com does something nicer than PRs, which is to attach changes independent from the context, to discussions. See the following discussion, for example: https://nest.pijul.com/pijul/pijul/discussions/104 https://nest.pijul.com/pijul/pijul/discussions/104 These two contributors (@cole-h and @lowenheim) are trying to add colours to the output of `pijul change`, and discuss changes, rewrite them, amend them, push them again. Certainly, some of these changes conflict with others. But that's totally ok, since you can pull them independently. For example, when preparing release 1.0.0-alpha.9, I didn't pull the latest patch from that discussion into my main local channel, and I preferred to pull some of the older ones instead. I did this because the latest one doesn't detect whether the standard output is a TTY. If I apply them to the main channel on the Nest, my current local channel will be in sync with it, even though I've worked on ten other features since then.
- zeotroph 6y agoI'd especially be interested in examples regarding multiple channels / branches (one development and several production branches), and then backporting a fix into older versions. In the conflict free use case I expect to just notify Pijul that this fix now belongs to not only to the dev-master, but also and rel.22, rel.21 etc. - in contrast to switching to every release branch and cherry-picking it with git. How is the workflow if this applies cleanly to rel.22, but not rel.21 anymore? What if the same conflict happens in rel.20, rel.19 and rel.18? If I (in git speak) "--amend" the original fix, could I automatically include this in the release branches? What if the conflict resolution changes every single line, but I still want to record that, "Yes, this fix is also in rel.17, even though it does not look like it".
- pmeunier 6y ago> I'd especially be interested in examples regarding multiple channels / branches (one development and several production branches), and then backporting a fix into older versions. I've been maintaining to versions of my SSH library for Rust, called Thrussh (https://nest.pijul.com/pijul/thrussh https://nest.pijul.com/pijul/thrussh). For some context, the Rust asynchronous ecosystem is undergoing a change, with a fundamental library called Tokio going from version 0.2 to 0.3. Some crates have made the change, others haven't. So if you're like me, and some of your code implements both an SSH server and an HTTP server on the same event loop, you might want to stay with Tokio 0.2 (since Hyper, the main HTTP library, hasn't published the move yet), while allowing others to benefit from all the bugfixes you find, and start transitioning now. The cool thing about doing this in Pijul is, you can work on your Tokio-0.2 version, and push your changes directly to your Tokio-0.3 version without having to care about cherry-picks, merges and rebases explicitly. Do this locally, test, publish. > How is the workflow if this applies cleanly to rel.22, but not rel.21 anymore? What if the same conflict happens in rel.20, rel.19 and rel.18? Good question. In Pijul, conflicts occur between changes (not between commits or states), and are solved by changes. This is in contrast with e.g. `git rerere`, since the solution to a conflict depends only on the changes that introduced it, not on anything else. This means that once you've solved the conflict in rel.21, you can push it to rel.20, rel.19 (it's the exact same change, with the same hash). > What if the conflict resolution changes every single line, but I still want to record that, "Yes, this fix is also in rel.17, even though it does not look like it". Excellent question. Two answers: - If you're really doing this, then your intention cannot really be guessed from your change, which sort of defeats the point of using changes, and you will get another conflict. If you fix that conflict again though, that fix will apply to any "branch" (Pijul users call these "channels" because they are not exactly the same as Git branches) that has the two changes. - There is ongoing research to extend the theory to allow large restructuring of code to commute with edits to that code. Note that no other system handles that well: Git and Mercurial don't even consider commutation (but their merge heuristics handle refactoring correctly sometimes), Darcs doesn't do it at all. Since our goal is to get something that works 100% of the time, we have to be a bit more careful.
- rstarast 6y agoThe one potential effect of this that I'd love over git is being able to check in local changes that I never intend to upstream. E.g. I could have a local change adding some editor config files, or modifying some compiler flags in the Makefile to suit my local config. With git my typical solution for this is to basically keep rebasing them as uncommitted changes with `git stash`, until I inevitably lose them. Or keep a separate branch, and keep explicitly rebasing (and stay on my toes not to accidentally push the commits).
- saagarjha 6y agoOoh, yes, I have this problem with Git too. I maintain it mostly by keeping stuff constantly unstaged, but there’s a lot of git tooling that doesn’t respect my working area and dumps things in the wrong place. (And there’s a lot of people who don’t understand the point of staging at all…)
- pmeunier 6y agoThis is incredibly useful for a project like Nixpkgs.
- didericis 6y agoWhy don’t you add those files to .gitingore?
- kadoban 6y agoThat only works the way you'd naively expect if the files aren't already tracked. To be explicit: gitignore has no effect at all on already-tracked files. So you end up depending on the upstream correctly foreseeing and working around this problem, or you're sunk. If the give you say a Makefile that's not correctly parameterized for you (doesn't let you adapt to your system via env variables or whatever), there's not a lot of good options unless you fix that yourself and get upstream to accept it.
- didericis 6y agoIn the case of a makefile already tracked with parameters incompatible with your system, fixing it to depend on some sort of input seems like something you’d want committed upstream. The fact that that’s the best option practically seems good to me, as I think it’s the best option architecturally. I don’t think it’s great to have a file committed to an upstream repo that is too particular about the machine being used when shared among multiple people. It’s better to make it so you can share it with people on different machines, and put those changes in the repo so others aren’t repeating that same work on their local machines. If you have an unresponsive upstream repo maintainer, that’s a whole problem in and of itself. Seems better to fork it in that kind of a situation rather than have a local bandaid. In the case of editor config files already tracked in the repo, I think it makes sense to remove those from being tracked, add to the gitignore, and push that upstream. Unless dealing with a team that agrees to use the same editor and wants to share settings, having editor settings committed to the repo seems like a mistake that should be corrected upstream. Same thing applies as in previous situation if the upstream maintainer is unresponsive.