Rebase only requires you to review the commits to the same extent that merge does, unless you're doing an interactive rebase.
Honestly, I expect the differences between Darcs and Git in terms of rebase / interactive rebase / cherry pick / merge to be a matter of implementation. Both systems are fed the same input, both track enough of it, so both could theoretically provide the same output. (I think Darcs is a little better at it, but every merge should be done with a watchful eye in either system.)
But I get the feeling that the patch-centric model is encouraging users to play fast and loose with patch order. If you wantonly reorder patches, you might get a sequence of unusable code bases culminating in the current working version of your software. It's easy to move a patch that uses a feature to a point before the feature is introduced.
Basically, the claim that "Darcs automatically groups changes which depend on each other" is one that I can't take seriously. How can it know which changes depend on each other, if (for example) they're in different files? By comparison, I hear from the Git folk advice along the lines of, "Be careful with rebase, because it is a destructive operation".
And because Git is snapshot-centric, if the app crashes in testing you can look at the SHA-1 used for the build to check out the exact tree used for the build, even years later, if necessary. No tagging required.
Git actually doesn't track cherry-picks, at all, and that's been a huge problem for us.
Consider for example, having two branches: "stable", "master" which have already diverged. Fixes go into "stable" and are regularly merged into "master".
Now imagine someone writes a fix F, which must be applied immediately to both "stable" and "master" and can't wait for the regular merge effort.
So with git, you just cherry-pick F into "stable" and "master".
Now, someone who uses "stable" discovers a big flaw in F, and reverts it. They assume their work will be merged into "master" as usual.
Then, a merge from "stable" to "master" happens, and the merge sees that the "stable" branch has 0 changes w.r.t F (commit+revert), whereas it has the F change in "master". Git's merge algorithm will consider this a trivial case, and do the wrong thing. The merge result will have the broken F application in "master", and there will be no conflict or any indication of a problem! This has been a huge problem for us.
So the result of this is that git forces you to either "merge" upstream, or "cherry-pick", but you really should not mix these two modes.
If you only use "merge", then the guy who merges must intimately understand everyone's changes in all cases of conflict. If he doesn't, others must help him resolve the conflicts on his working directory. Then, the merge result is one monolithic commit that makes understanding changes very difficult.
If you only use "cherry-pick", then you lose tracking of which changes have already been merged upstream, and which haven't. You start relying on the grep of "git log", which is unreliable, and you have no reliable tools to automate this. "git cherry" is unreliable and has plenty of false negatives/positives. Then there are of course problems with patch dependency, where you have to figure it all out on your own.
In short, the snapshot model is very problematic here. None of these problems would occur in the darcs model. Unfortunately, darcs does not scale. Whether that's inherent or not, I don't know. But if it did, I know I'd definitely prefer to use darcs in a large collaborative effort than git.
If I understand you correctly, your problem would occur if, say, you were maintaining 1.0 and 2.0 branches of a product and needed to apply the same bugfix to both; you can't merge, so you cherry-pick.
Surely this is something that the Linux project runs into constantly? I wonder if they have a solution?
In the case of two maintenance branches (1.0, 2.0) you're probably going to use only cherry-picks, and no merges, and just manually track what you've already cherry-picked.
In our case, we had the "bleeding edge" branch (master) and a maintenance branch. Fixes generally go into the maintenance branch and then are merged upwards. But we allowed "emergency patches" to be cherry-picked upwards (or downwards) too. The combination is the problem.
If we had stuck to just cherry-picks or just merges, we would not have this problem. But as I also explained, sticking to one of the approaches has severe drawbacks too.
> It's easy to move a patch that uses a feature to a point before the feature is introduced.
Well, if you use git yes, since there is no check for this, in the normal darcs workflow either the patches are independent or you can't reorder them.
So, "fix About" can be moved before "new login screen", but "using data in the new login screen" cannot.
> How can it know which changes depend on each other, if (for example) they're in different files?
Because _you_ told it so, by making them part of a single commit, or by creating a commit which depends on lines in both files affected by previous commits in those files, or by tagging the repo.
Surely it's not a crazy idea to group related changes across files in a single commit :)
E.g.
# distinct commits
A1 "added foo() in foo.c"
B1 "added foo() in foo.h"
# depends on b1, if you cherry pick this you get B1, B2
B2 "added ifdef in foo.h"
# depends on all three, you get A1, B1, B2, C1
C1 "renaming foo() to bar()"
# depends on all four, you get A1, B1, B2, C1, C2
C2 "renaming foo.(c,h) to bar(.c,.h)"
Notice that yes, you can miss a commit, or include too much. In the worst case you end up with the same "I'll review the commits" workflow you use in git cherry-pick/merge/rebase.
FWIW, I am not advocating darcs over git, just trying to shed some light.
this is a critical reason why git makes sense to me, cause all non trivial code changes conflict, and then need to be resolved with understanding of the underlying code.
the only way to reorder these in git is with rebase, but that is flagged as a dangerous tool, and with good reason.
if darcs can find a way to do this it would really be worth switching to, but if not then it would fall short in it's claim of safely being able to reorder patches. doing so behind the scene automatically would really worry me about code integrity.
Don't forget that there are two kinds of dangerous in a vcs: code-dangerous and repo-dangerous: stuff that can give you a working repo containing code that does not work, and stuff that can give you a non-working repo, or changes between repos that are tracked inconsistently. Cherry-picking (i.e. creating a version that has not been seen by a developper before) is as code-dangerous with darcs as it is with git. Commit and merge are also code-dangerous. On the other hand, in darcs it is not repo-dangerous: you don't have to worry about merges versus cherry-picks, a repo's final state is only defined by which patches you've pulled. This is the kind of consistency that git does not give, and that makes git rebase repo-dangerous. darcs' cherry-pick is no more dangerous than merge, while git's is in fact more dangerous.
It is quite common to have people come to #darcs asking how to reorder patches. The answer to that is "why would you want to do that?" To darcs, the order in which the patches are stored in the repository is a transparent implementation detail, and there's no command to change that. Darcs users are not constantly reordering patches, they're just enjoying a bit more freedom on pull. In general, if you don't use commands marked as unsafe such as unpull, each repository is honest about the order in which it pulled patches: darcs will simulate patch reordering to compute merge results, but won't change the order of patches in the repository.
There's one "patch theoretical" thing which git does better than darcs (and a lot of practical things), which is that it tracks more explicitely which stuff was pulled from where when. That information is neglected by darcs, which cares more about when stuff was originally written, and it should be tracked somewhere. Still, this seems easier to add to darcs than adding darcs' freedom of workflow to git, for which, as far as I can tell, you'd have to embrace the patch-centric view of darcs.
Yet, it would be cool if I could explicitly tell Darcs about patch dependencies, maybe at `record` time. It's no guarantee (I could forget some), but it could help avoid screw-ups when cherry picking.
You can, you just use `darcs record --ask-deps`. There's also the idea of allowing some kind of test to infer more dependencies for you at record time.
Honestly, I expect the differences between Darcs and Git in terms of rebase / interactive rebase / cherry pick / merge to be a matter of implementation. Both systems are fed the same input, both track enough of it, so both could theoretically provide the same output. (I think Darcs is a little better at it, but every merge should be done with a watchful eye in either system.)
But I get the feeling that the patch-centric model is encouraging users to play fast and loose with patch order. If you wantonly reorder patches, you might get a sequence of unusable code bases culminating in the current working version of your software. It's easy to move a patch that uses a feature to a point before the feature is introduced.
Basically, the claim that "Darcs automatically groups changes which depend on each other" is one that I can't take seriously. How can it know which changes depend on each other, if (for example) they're in different files? By comparison, I hear from the Git folk advice along the lines of, "Be careful with rebase, because it is a destructive operation".
And because Git is snapshot-centric, if the app crashes in testing you can look at the SHA-1 used for the build to check out the exact tree used for the build, even years later, if necessary. No tagging required.