Merging is the bread and butter of distributed source control, so I want to get this straightened out in Pijul.
Someone from hackernews posed the following scenario:
I’m comparing git merge to adding a patch to a set in Pijul.
Let’s say I have a patch A that adds a line: return 1 + 1 + 1 + 1;
and a patch B based upon A changes it to: return 1 + 1 + 2;
and a patch C based upon B changes that to: return 1 + 3;
and a patch D based upon the original A changes it to: return 4;
So we now have:
A
| \
B D
|
CNow lets say we add them all to the same set of patches. Will I have to resolve the conflict in B and D and then also the conflict in (the resolution of B and D) and C?
I replicated this so far by recording A, forking and recording D, resetting back to main, and recording B and C. At this point I got no idea how I’m actually going to start the merge. The only thing I have found is applying the change, by hand, one at a time, from the other channel into main by looking at the hashes from that channel’s log. This is obviously unacceptable, so that’s definitely on the to-do list. (Let me know if there is already another way). Anyway, I apply D onto main. I get no feedback, so I guess pijul thought it was a perfect merge. The log shows D → C → B → A, as expected. diff
shows nothing. If we look at the file we find:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
return 1 + 3;
================================
return 4;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Okay, so not a perfect merge. Alright, I pick return 4;
. diff
now shows:
message = ''
timestamp = '2020-11-16T19:17:28.751950638Z'
authors = []
# Dependencies
[2] VWXEHN53VYFFZLVSFIY63BPI5NQ7BXFSD57Q3Z3EXVQQ4KHXBJWQC
[3]+PZOBADFPPTJZC5ETS5D4HS5FJYPNW26HJALW25W7WDH7MMS7CKDAC
[*] AJUWPHUPEOQC34FU7SMVJXZLRX7POFJPP32LKLANS46SMJT573NAC
[*] OJLDUJT6AYQ7PLGVUTDFCT2TAS5LI5USBCPUH7GNE2A62XDMJE7AC
[*] PZOBADFPPTJZC5ETS5D4HS5FJYPNW26HJALW25W7WDH7MMS7CKDAC
# Changes
1. Edit in file:0 3.7
B:BD 3.7 -> 2.0:14/2
- return 1 + 3;
diff
only shows the removal of return 1 + 3;
. That’s good! Conclusion: the original file content is merely the way pijul represents a graph with conflicting changes. Kind of like a 2D shadow of a 3D cube. I find it problematic at the moment that I can be in completely normal repository state while I have conflicting changes. If I merge two channels that compile and run, I want to get a repository in the end that also compiles and runs. If there is a conflict, I should definitely get some sort of warning at the very least. Just to contrast, this is what it looks like in git:
qrpnxz@box:~/tmp/gitteest$ git merge feature
Auto-merging file
CONFLICT (content): Merge conflict in file
Automatic merge failed; fix conflicts and then commit the result.
qrpnxz@box:~/tmp/gitteest$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: file
no changes added to commit (use "git add" and/or "git commit -a")
qrpnxz@box:~/tmp/gitteest$ vi file
qrpnxz@box:~/tmp/gitteest$ git commit
[master 2e2a770] Merge branch 'feature'
qrpnxz@box:~/tmp/gitteest$ git lg
* 2e2a770 (HEAD -> master) Merge branch 'feature'
|\
| * db00a3b (feature) D
* | b1a60f4 C
* | b565af0 B
|/
* a0c8a5c A
So let’s compare and contrast. What I think this means for git is that if I revert this merge on master
, I get what is expected: master
as it was before the merge, and feature
as it was before the merge. If I unrecord the merge fix on pijul, I get back a bad merge. Another thing to note is that D doesn’t remember arriving at main through a merge. That means that on history, this patch could’ve been made or come from anywhere and all we know after the merge is that now it’s in main
. This makes that log at the end impossible for pijul at the moment. The main bad consequence, however, is that a guarantee that I can get with git that I can point to any commit and that will be a valid project state is gone. After a merge in pijul, not only is the final state possibly broken, but there’s no clean way of looking at main
before the merge (ABC), or main
minus it’s last change before the merge (AB), etc.
So I feel that either pijul is lacking in major ways, or I’m using it really wrong.
@pmeunier Would really appreciate your feedback.