1. 28
    1. 67

      I love rebase.

      There are a couple things rebase enables that are really powerful which are, unfortunately, not possible in fossil.

      The first is a clean history.

      My commit history as I create it has no value to anybody else. I “finally got this bit working”, I go “This is close but I’m going to try a totally different approach now,” and I leave my computer for the day. All of these are valuable to me, but have no place in the long lived history of my source code. Why?

      A simple misconception. Commit history is not supposed to be how I think, but how the software committed evolved.

      I commit then run tests. Should I be committing the failed results and then committing the successful ones? Should I be cluttering my history with commits like “fix tests” since I commit all over? Or should I be producing nice, small, specific commits for specific features or specific points in my software’s progression towards its current form?

      Bisect means nothing if I have many small commits where I repeatedly broke and unbroke a feature. Bisect means a lot when I have a specific commit that makes a set of changes, or when I have a specific commit that fixes a different bug. It means nothing when I have to try “Hey, does this pass our CI as it stands?” (welcome to big-corp coding).

      So point by point:

      1. Yes! Rebase is dangerous! Don’t blindly use this command, know what it is you want at the end.
      2. Cleaning history so it becomes about the software and not about your brain is a new and useful feature.

      2.1) Nope, history all still there, just because you don’t know where the work started doesn’t mean you don’t know where the software gained the work.

      2.2) You can merge this way in git too. You can diff two commits in git too. And then you can rebase because again, it’s not about my brain but about the software.

      1. Siloed development? “Hey can you check this branch and it’s my branch I might clobber it later” is very different from “It’s my code and you can’t see it until it’s all done.” Master/trunk can’t be rebased. Everything else is fair game.
      2. So what? Do you really want my commit to show when the work was done at 2 PM instead of 10 AM?
      3. Who cares how a line of code came together, so long as the reason for it to exist (commit message) and a clean story for how it fit into the previously-existing project both exist?
      4. How your brain works is not so valuable it must be imprinted on your commit history.

      6.1) They were thinking “blargh.” Obviously. That’s why it’s an intermediate commit.

      6.2) Nothing wrong with small check-ins in a linear progression, rebased into complete commits that add things in small and appropriate ways.

      6.3) “blargh” “aargh” “fix the thing” “wtf is with java” “dude. stop” “I AM A ZYGON.” I’d rather a nice commit shaped by a rebase into being a useful object because….

      6.4) Cherry picks also work better with single commits that are useful, instead of five commits all that need to go together to bring a single feature across branches. Also, notably, commits with terrible useless messages. See 6.3.

      6.5) You want to back out just the testing fix? Or the whole feature while reconsidering how it fits in the existing code. Again, rebased commits for that clean history make this easier.

      1. Sure. Rebasing for a merge, maybe a cherry-pick in fossil’s model is actually better. Won’t argue with the local SCM semantics for performing a nice linear merge.
      2. Dishonest only if you think SCM is about the developer’s brain, and not the software.

      Really I worry the author had too much Enterprise coding experience, where all your work will now become a single commit fitting the Jira formatting rule and you have a multi-dozen line commit because that way the pre-CI checks can pass. I understand being in such a system and thinking rebase is to blame. Maybe your org should trust developers a little more, and spend more time saying “don’t say blargh” instead of “all one commit.”

      1. 27

        The best analogy of this I’ve come up with is your private work is like a lab book (meticulous, forensic) and the public/merged branches are the thesis (edited, diversions gone, to the point).

      2. 4

        As I started reading you comment and was convinced you had not read the article, but I see you did as you addressed points individually. The author does negate your first claim and shows the evidence. I think you mean that some things are not achievable the same way they are in git. Cleaner history is achievable in fossil in a way that is a superset of git, as explained in the article thoroughly.

        I am a git user and never used fossil. Git works fine for me and has proven to be a reliable and snappy VCS for me from day one. I don’t have any interest in move to fossil, nor am I a member of the group of people that advocate for changes in git, specially not on git’s principles. It works for me, the parts of it I dislike or would have built in a different way are acceptable choices by people who offered an immensely useful tool to the world. That isn’t to say that valid criticism doesn’t exist or that there aren’t things that could be solved better. I think this article very strongly proves that rebase is just a hacky workflow whose results could be achievable by resourcing to better designed functionality. The author did this masterfully, but on the other hands there is nothing wrong in having a workflow in muscle memory and use it. Even if said workflow relies on glitches or rough shortcuts.

        1. Do you not mean the opposite? They way I see it, it doesn’t make sense to call a tool ‘dishonest’, one could call it potentially confusing. But it does what it does, how is that possibly dishonest?

        Regardless personal opinions, the article was so clear, and explaining things so well with clear information and to such detail, that it was a joy to read. This is the mind of a great engineer at work in a way we don’t see so often these days.

        1. 3

          rebase is just a hacky workflow whose results could be achievable by resourcing to better designed functionality

          Argued with examples and suggestions which do not share the same assumptions. There may be a case for rebase being a hacky way to go about making changes to past/private commits, but it was not made in this post. Rather the case was made for any manipulating of past commits as technically and socially wrong.

          I understand fossil allows overlaying new information on past commits, however there comes a time for messing with actual commits, and not much lost when you change a parent commit.

      3. 3

        Maybe I’m missing something, but it seems like the author is specifically talking about git rebase and not git rebase --interactve (at least for the majority of the article). Many of their points are valid for the former, but this response seems to be speaking almost exclusively to the latter.

        That being said, I don’t think Fossil supports rewriting history in any form, so quite a few of your responses are critiques of Fossil, but not really the article. Similar to you, I’ll try to go through all the points and show what I think the original author was getting at. On a side note, I personally don’t think that rebasing all commits so the master branch is flat is very helpful, but some people seem to like it. In any sense, that specific use is what I’ll be speaking to because it seems to be what the article seems to be talking about.

        1. Everyone seems to agree on this, no sense speaking more about it.
        2. Raw git rebase is more an alternative to merging in prod than it is cleaning up the commits. Commit cleanup is often useful, while blindly rebasing on prod rather than merging it in isn’t always the best option.
          1. Your argument is saying “some data was lost, but everything is still there”. I have to agree with the original author on this one - a rebase drops the parent commit where the branch first came from, so all the history is not still there (or is purposefully misrepresented). Also see my response to #4.
          2. I think the point they were making is that the claimed benefit from rebasing (“rebasing provides better feature branch diffs”) can be easily achieved by other means - in this case, merging the parent branch back in to the feature branch. On a related note, there are very subtle, but potentially fairly dangerous, differences when you look at the diff from the HEAD to the feature branch without merging in prod, so either rebasing or merging in prod are 2 ways to solve this. That is what the graphics and table show.
        3. While I tend to view personal branches as potentially rewritten at any time, have you ever tried to base your branch on someone else’s when they’re using a rebase-based workflow? It’s a nightmare. Trying to get your changes to re-apply on top of their rebased changes often causes conflicts which are very hard to recover from.
        4. The issue is not “when was work done”, but “what was the order the work was done in”. Using a rebase workflow, you could easily end up with commits later in the history which were much earlier chronologically. This is extremely confusing if you’re trying to track down what actually happened.
        5. I’m not sure what you’re getting at here - fossil seems to allow amending commit messages to fix information or a mistake at a later date, you can’t do that in git without rebasing… and once something is in prod, that really shouldn’t happen. There have been many times when I’ve wanted to go back and add more information to a commit message (or fix a typo) after it was merged in.
        6. For these, I tend to agree with your response - this seems to be one of the only places where the Fossil article is speaking about an interactive rebase and I think they really miss the point.
        7. Not much to respond to here.
        8. From the original article, “Rebasing is an anti-pattern. It is dishonest. It deliberately omits historical information. It causes problems for collaboration. And it has no offsetting benefits.” I agree that rebasing is often an anti-pattern, but I’m purposefully excluding the modification of local commits to get a more useful history. Rewriting local history can definitely have benefits though, so I don’t think they’re completely right.

        I often wish Git’s UI was clearer - the multiple uses of “rebase” seems similar to the many things “checkout” can do. To make the distinction clearer in my head, I personally view git rebase --interactive as a git rewrite-history command. While it may share some of the internals of rebase, it has quite a different goal from the plain “rebase” action.

        I hope this helps shed some light on their opinions, even if you may not agree with all of it.

        TL;DR: there should be a distinction made between rebasing to keep a flat merge history and rewriting feature-branch commits to make them more useful. The first can cause quite a bit of confusion and lead to a more misleading history, while the second can be a very valuable tool.

        1. 1

          Interactive rebase should give you only those abilities available from the commandline, just with a nicer interface.

          I’m OK with fossil commits being append-only. That doesn’t bother me, I love the OpenCrux database which offers an immutable base. A similar thing for commits is an excellent idea.

          But so is modifying the stream of commits to match when commits hit mainline. And so is merging or splitting commits. And so is ordering the work not in how a spread-out team might complete it, with multiple parallel useless checkins a day, but with what matters long term: In what order did this work introduce regressions to the codebase.

          1. 1

            In general I agree with you - I like modifying the stream of commits, but I really only like doing it before they hit main… and I don’t like forcing main to be a straight line without merges. I was primarily trying to point out that most of their arguments focus on rebasing commits to maintain a straight line on main, and not on rewriting history for the sake of a clearer commit log. I think there is very little value to the former (most times), and plenty of value for the latter.

            Again, I really dislike how “rebase” has often been taken to mean “rewriting history” in git, because in a DAG, a rebase is a specific operation. It’s unclear which people are talking about during this conversation and I think some of the wires may have been crossed.

      4. 2

        I generally agree that git rebase is fine as long as one knows exactly one is doing and using the tool to make deliberate changes and improve the state of the project, but

        So what? Do you really want my commit to show when the work was done at 2 PM instead of 10 AM?

        2PM vs. 10AM is unlikely to matter, but it often matters whether it was yesterday or Thursday 2 weeks ago, which is before we had the meeting about X,Y,Z. I don’t go about memorizing the commit timestamps in my repositories, but I still find them useful occasionally. I wish we’d all be more careful about avoiding argument from lack of imagination in our debates.

        1. 5

          but it often matters whether it was yesterday or Thursday 2 weeks ago, which is before we had the meeting about X,Y,Z.

          Not long term, which is where SCM exists.

          Long term those distinctions turn into a very thin slice of time, and people forget about the discussions that happened outside the commit history. Thus all that remains is a commit message in a line.

      1. 9

        I actually really like “considered harmful” essays. For most topics it’s a lot easier to find material in favor of it than against it, so searching “$x considered harmful” is a good way to find cold showers.

        (Usually they’ll be pretty bad articles, but some are good like this one, and it’s a good launch point for doing more research.)

        1. 5

          Bring back “Against X”. It worked for Cicero, it will work for us.

          1. 3

            Is “Against considered harmful” “‘against’ considered harmful” or “against ‘considered harmful’”

        2. 4

          I find them really annoying for the reasons stated in GP. I wish the author of this submission would have chosen a different title and that they would leave out a couple of inflammatory sentences. The article is very informative and well written otherwise. “Considered harmful” in the article will probably end up being counter productive.

    2. 23

      Maybe I just don’t get where the fossil author is coming from but when I was using fossil regularly (and sometimes still do) I’d end up having two copies of the same repo… a short-lived one in whatever work-in-progress state with all the useless commits (“really fix edge case this time”, “friday WIP” etc.) and then a second persistent one where I’d rsync the worktree and make a new commit or, less easily, cherry-pick from the first. I’m not convinced that seeing the sausage being made in the commit history has any benefit over a single commit or small number of clean commits per feature.

      1. 14

        I’m not convinced that seeing the sausage being made in the commit history has any benefit over a single commit or small number of clean commits per feature.

        Yes, the lack of ability to clean up history, even locally, is the one thing about Fossil that ensures I’ll never use outside of work, where I have to use it in some situations.

    3. 14

      Most people, even strident advocates of rebase

      Again with Fossil marketing, they paint people thinking differently as emotional and noisy, unlike their perfectly rational argumentation.

      Bisecting is made more difficult by having to deal with intermediate commits. Those commits can break, then fix build and / or tests, before being integrated. As the main tree will jump to the end of the list, those breaks won’t be seen until bisect is attempted.

      When doing a series of commit, each individual one needs to support build + testing. As it will always happen that someone makes a mistake, they need to be fixed individually and locally would be better.

      Not having a local draft history to improve and work on is just an anti-feature that makes Fossil a bad VCS. Reading another comment here about having to use two Fossil repositories, one for local work and one shared, is a good sign that this is something missing. It’s also pretty hilarious considering the complacent tone of the article. I mostly feel for the developers forced to deal with this team opinions on software development.

    4. 4

      So, git rebase advocates try to keep the canonical history cleaner, while the fossil author suggests that it’s the job of the tooling to expose a clean version of the history while the VCS doesn’t lose any history. I think this argument has a lot of merit, but IMO what the author is missing here is the number of tools interacting with your VCS. By lying and simplifying your history, you’re forcing a canonical view onto any consumers of your repository, but an honest history suffers from the inconsistent interpretations from different tools.

      You can actually approach the problem from the other end. Let’s keep the commit hierarchy simple, but retain any information we want in the commit messages of rebased or cherry-picked commits. So, whenever we cherry-pick a commit, let’s take note of the original time stamp and/or the name of the branch where the commit came from, in a way that keeps or collapses multiple layers of some metadata. If we do this systematically, then we can teach our tooling to process that metadata consistently and recover the original history when needed.

      IMO, retaining that metadata in the commits and hoping that the tooling agrees isn’t very different from retaining that information as a core component of our VCS and hoping that all the tooling agrees on what is canonical. The difference is, git, by itself, enforces only the minimum amount of metadata it needs for itself to work without really stopping you from retaining anything extra, but fossil forces you to deal with a world with that extra information whether or not you like it, but the up side is that you have a much better chance of getting an ecosystem of tools to agree since the shape of the metadata is standardized.

      My personal preference is to work with systems that impose the minimum amount of complexity on top of the bare minimum they need themselves to operate. I find it easier to combine such systems to build exactly what I need.

    5. 3

      From my point of view “rebase” implements the following important convention about software development. If I am modifying a code base and want to submit a patch to it (this is the use case for git, after all) then the polite thing to do is to always submit code which is based on the most recent version of the software. The remote is, in my view, the “authoritative” version of the project. If it has moved on since I started working on something, then its my responsibility to adapt my changes to the new state of the remote. Hence a rebase.

      I think of merges as literally only appropriate for a genuine merger, when two versions of the code have diverged significantly and intentionally and someone wants to integrate changes from one codebase to another.

    6. 2

      [a sequence of] cherry-pick merges work better than rebase

      isn’t that usually how rebase is implemented though? at least with all of the git clients I have used, that seemed to be what it was doing under the hood :\

      I thought it was fine, you don’t have to squash the commit history when you rebase, and honestly IMO its fine to give people the option, the team can make and enforce their own standards on how verbose/ugly or minimal/clean the commits are

    7. 1

      I accidentally discovered that you can click on the commit graph diagrams and it reveals some kind of source code. Seems to be this: https://pikchr.org/