On Thu, 17 Dec 2015 13:16:43 +0100 Joerg Sonnenberger <jo...@britannica.bec.de> wrote:
> > [...] > > > I realize that 'get rebase -i' gives a lot more tools, but > > > couldn't 99% of rebase use cases be handled with private branches? > > > > `git rebase` is about rewriting history. It has several modes of > > operation (that is, it can be used for tasks different from its > > original intent -- rebasing -- such as squashing several commits > > together, editing a commit, splitting commits, deleting commit etc) > > but no matter what mode `git rebase` is being used in, it rewrites > > (recreates) commits. > > The important point here is rewrite vs recreate. That's quite a > different, both practically and semantically. It would be useful to > have a "linearise" command, however you want to call it, which > performs *one* part of what rebase does: I'm writing a bunch of > changes in disconnected mode and want to push them back. Someone else > has committed a change in the mean time and I don't want to merge. > "No merge on the main branch" is a pretty useful property for things > like bisect and the like. > > Now the tricky part is this can be done *without rewriting history*. > Essentially, you can (semi-automatically) reapply all changes on top > of the new commit and record which commit they were originally. This > allows three things: > (1) Tight main line with keeping incremental stages. > (2) Preservation of what commits originally happened in case you need > the full audit trail because there was a subtil merge fault or the > like. > (3) It allows automated follow-up rebases for 3rd parties that already > got the initial changes. I.e. you can safe push your work-in-progress > and still transplant it later. > > "git rebase" only really allows the first point. Not quite. Well, `git rebase` does indeed replace the tip of the branch it operated on with a set of changed commits, but this counts as a so-called "drastic head movement" in the Git parlance. Such movements are recorded in the so-called "reflog" ("reference log" -- with refs or references being heads (branches) and tags), so as soon as a rebase operation completes successfully (as opposed to having been aborted using `git rebase --abort` where the branch being operated on is left intact), you can retreive the previous tip of the affected branch from the reflog. The reflog keeps about 30 days worth of such changes by default which is more than enough to cover the "oops!" situations. As to "without rewriting history" bit, this might be a terminological issue but in a (typical) DVCS you simply cannot cherry-pick or otherwise (re-)apply an existing commit to some tip to produce another commit without essentially rewriting it because the commit hash includes the commit creation date. And once you've changed a commit's hash, the next commit being applied on top of this one will have its hash changed also because it will refer to the changed hash-name of its parent commit, and this "link" is hashed as well. Another point is that when you rebase (or "linearize"), the new upstream tip might actually contain changes which will make some or all of the commits in the series being rebased/linearized be apply with some fuzz, and in complicated cases they might even fail to apply. In this case, even "the contents" (as opposed to metadata) of the rebased/linearized commits will be re-written quite literally. In the sense that if you had a commit A on top of upstream's U, and then rebased A on top of the updated U' to produce A', the differences A':U' and A:U might be substantial. I hence insist on that you can't rebase and not re-write commits at the same time. Even your specific "linearization" case still requires commit re-writing. _______________________________________________ fossil-users mailing list fossil-users@lists.fossil-scm.org http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users