1. 10

  2. 9

    For my low-activity personal projects, I prefer to use git merge --no-ff to preserve history.

    In contrast the repo at work is very active, and I find merges turn everything into a snarl. One big advantage of rebasing is it keeps all of your commits together. I can easily rebase my feature branch forwards or backwards because it’s not intertwingled with other activity.

    1. 3

      This. It’s a massive help to keep my changeset “clean”, aka with no merged changes from upstream midway through the feature branch… which is usually how people deal with bringing a branch up to speed midway through work with a normal branch/merge strategy.

    2. 7

      Merging feature to master is now a fast-forward merge, because all commits on feature are direct descendants of master

      Well, you can always use a --no-ff when you merge from your feature branch into master (after rebasing your branch on master), to create a specific merge commit. I like to do this so I can better track feature development, but still have much cleaner histories.

      1. 6

        I use rebase to merge small fixes into the original commit, rather than having:

        • commit 1
        • commit 2
        • fix for bug in commit 1

        But not if I’ve shared these commits with anyone else. As long as nobody but you has the commit, it should be safe to change its hash.

        1. 6

          I keep hearing this and I couldn’t disagree more. Clean history isn’t about vanity, it’s about maintenance. Those several fumbled commits you made while converging on a solution aren’t at all useful to me years later trying to maintain this code. Commits should be atomic and should never break bisect; that’s also part of keeping a clean history for your future maintainers. Rebasing is one of the things that actually allows you to reshape your work (which naturally gets done in a very messy, human way) into something maintainable. You can and should verify that things build on every commit. Like any powerful feature it is frequently abused and should probably have more safety checks around it.

          1. 5

            Fair point. Article misses a third option, which seems to be encouraged by some tools such as Phabricator: squash the entire feature branch, including the fixes required to make it work with the latest version of master, into one and only one commit onto master.

            Or, the article misses it, but the first comment does suggest it, and the author dismisses it out of hand.

            1. 5

              Merge commits (as mentioned by @trousers) seem to fulfil the same purpose, but they don’t lose any of the intermediate commits. master looks like Merged feature X -> Merged bugfix Y -> Merged feature Z, as in the “squashed” case, but each of those also has another parent which contains the history of feature X, etc.

              Is squashing just a (lossy) workaround for poor UIs (e.g. not being able to hide those other parents)?

              1. 3

                That’s because such squashing workflows sort of defeat the purpose of having a version control system – you can’t really do a bisect to find the place something got introduced, because all of your commits are huge. A series of huge commits is technically version control, but is basically just a set of snapshots.

                1. 3

                  Personally speaking, the projects I work on shouldn’t have large feature branches though. I expect them to be small. This can’t be true for all projects and branches, obviously. But I don’t really see a reason to ditch squash-rebase. For me, it helps in dealing with/reasoning about changes that happened upstream while a branch was in progress. And while others might find the merge-conflict process confusing for conflicts within a rebase, this is likely just a sign that they’re generally not good (enough, imo) at solving merge conflicts in the first place. It’s not an easy thing to learn, and it takes time and hard thinking to learn to get right.