5 ms·
I feel that having a default merge strategy to squash and merge all commits in a branch is a version control anti-pattern. This discourages thoughtful and frequ
by mrinterweb 5y ago
I feel that having a default merge strategy to squash and merge all commits in a branch is a version control anti-pattern. This discourages thoughtful and frequent commits that express the intent of a change because all the commits are just smashed together anyway so why bother. I think context and intent is lost when looking through git history of large smashed commits.
I prefer using a precommit hook to automatically prepend a Jira ticket number to each commit so when you look at the history you'll see multiple commits grouped together with the same ticket prefix, but the commits still retain the intention of the commit. Knowing that commits will not be squashed promotes devs to make meaningful commits. I still advocate for cleaning up and squashing your own commits as you see fit with an interactive rebase before your branch is merged. Having discrete commits can also help when running git bisect to find when a bug was introduced so you identify the specific commit instead of a feature being merged.
- halestock 5y agoI've seen this argument come up a few times, and the best suggestion I've heard which could make both camps happy is to add the notion of commit groups. You could view a pr in history as a single commit group, or see each individual commit for the full context.
- hnlmorg 5y agoIs commit groups a feature or a wish list? I hadn't heard of it before but a Duck Duck Go search only throws up a blog post discussing the desirability for such a feature in git.
- periodontal 5y agoYou can get something somewhat similar with "always create merge commit" workflows (no fast forward) and changing your tooling to look at the first-parent-history by default. This view will have one commit per merge, but you can choose to follow the second+ parent history for a given commit to see what went into it.
- globular-toast 5y agoOr just include a group name in the commit message. No need for empty merge requests in your history. Since most people use issue tracking systems, just prepend the issue number to each commit message in the group.
- maximilianroos 5y agoIME this depends on whether people make large or small PRs in a repo. If people make small PRs, committing to mainline as they go, then squashing each PR fits well.
- lysp 5y agoThat's why I prefer feature branches with merge commits. Your dev branch is clean because each merge-commit is a single commit per task. So you can see which tasks were merged and in which order and what file as a whole were changed in each task. If for debugging / code review or any other reason need to look at specifics, you can look through the feature branch commit by commit to see what was changed and why. It's best of both worlds. Similarly merging dev into master/main. You get a release by release view of what files were changed in a single merge commit.
- rvdginste 5y agoCompletely agree with parent and grand-parent. For me, a nice clean commit history is an investment in future maintenance. Following the rules described above means that you get a lot of context on why code was changed: * the invidivual commit which should contain a description of the change if the change is not self explanatory or not 'intuitive', the individual commit should consist of only 1 functional change * the commits surrounding it, the feature branch (clearly visible because of the merge commits) * the issue number on the commit itself and possibly in the merge commit I've found all this context very informative for projects that are in maintenance mode and still need changes from time to time. Obviously, the higher the quality of the commit history, the higher the quality of the information you get out of it. Meaning: if you put a rename with an impact over the whole code base (because the original name just happened to bother you that day) together with a bugfix in the same commit and the commit message has the very informative text 'fix', and the referenced issue mentions 'add support for blah' (but the commit obviously does not implement anything related to 'blah'), then... well, yeah, then how you organise your commit history does not really matter.
- lysp 5y ago* the issue number on the commit itself and possibly in the merge commit Absolutely this too! My process is to create a feature branch named "ISSUE-123-issue-description" The benefit of this is all changes are tracked (and tested) against a specific issue in bug management software. It also prevents people making small / unrelated changes or fixes in association with another task. If these are grouped in together in a single and unrelated task they won't be trackable or testable.
- nuerow 5y ago> This discourages thoughtful and frequent commits that express the intent of a change because all the commits are just smashed together anyway so why bother. This is only the case if said squashing just bundles commits without context or consistent logic. If merges to a mainline branch consist of feature branches whose pull request was already approved after a couple of iterations then the end result is a cleaner commit with it's history thoroughly audited. In practice it's equivalent to a fast-forward merge of a single-commit feature branch that just happened to be nearly lined up with mainline.
- astrobe_ 5y agoAgreed. This is when you believe that your program should at the very least compile (or pass tests) at any point in the history. In this case a commit must be a consistent and related set of changes. In other words, a commit to us is sort of like an "atomic" change, something that cannot be split or else more or less bad things happen. I have trouble conceiving a better way to use Git when you really care about the readability of your history. in some cases I don't care about readability though. On hobby projects I sometimes use Git more like a file transfer and synchronization tool. In this case I don't give a huck about how the history looks like. Just like with code, the more readable this history is (in terms of what features/fixes are in there at some point in time), the better.
- rectang 5y ago> This is when you believe that your program should at the very least compile (or pass tests) at any point in the history. I only expect that at merge commits, which I can see with `git log --merges`.
- bonzini 5y agoWhy would you? Linux (and any other C or Rust open source project I have worked on) compile and work at any commit.
- 5y ago
- globular-toast 5y agoSomething people don't get about commits is they have multiple purposes. A lot of this is due to still entrenched assumptions and practices from older, inferior version control systems. There are at least two types of commit in git: a savepoint and a version. A savepoint is what happens during development on a branch. Git makes it super easy to make many, many savepoints throughout the day. These help you as a developer because it gives you something to fall back on if you make a mistake. But most of them should never be exposed to anyone not directly working on the branch. A version is what you share with others. A version is a fully working version of the software that can be reasonably checked out and put through a release process at any time. Usually a version will be unit tested but not subject to the same rigorous tests as a release. There is a direct analogy here with database transactions. Just replace version with transaction. Often while working you will find it's possible to write the version commit right away. This is usually for more trivial fixes or in some cases when a commit is required for something like a database migration (when things need to be deployed in stages). Other times you will need to make several savepoints before you get to a new version. This is what rebase is for. Many of those savepoints don't belong on the master branch as they are often fixing stuff you haven't even committed to master yet. Git has a few tools to help you defer rebasing until later. In particular you can make fixup and squash commits. These will be normal savepoint commits, but they will be labelled in a way that later you can issue an "autosquash" command to automatically rebase these into version commits.
- WorldMaker 5y agoThere's also nothing wrong with leaving "savepoints" type commits in a branch. Sometimes "I stopped here and took a break" is still useful information to have later on. Git provides a DAG and you can use a --no-ff merge to build your "version commit" from the sub history of its "savepoints". You can follow one parent of the merge to the next "version commit" or you can follow the other parent through the intermediate "savepoints" that built it step by step. You can use --first-parent today for most git operations to get "clean views" no matter how complex the DAG web is beyond it. I think a lot of these debates would "go away" if more people and user interfaces defaulted to --first-parent and "drill down" navigation rather than firehose of the complete graph and confusing (but pretty) "subway diagrams".
- daitangio 5y agoI agree. I do not use squash, I prefer to have a feature branch and live it alone after a merge. Anyway some workmate use Squash when accepting pull request on GitLab/GitHub as a general workflow suggested by such tools and in context where trunk based development is not feasible.
- jonkoops 5y agoI have to disagree with this as it relies on the assumption that every commit on a branch is logical and descriptive. In my experience a lot of PRs will have small commits that have poor names as they go through a review process. If you merge this using a regular merge commit or by rebasing the commits on the target branch this creates a lot of noise for those who look at the commit history. In my opinion it is best to squash all commits into one before rebasing it on top of the target branch. During this process any information that is considered important for the history can be preserved by leaving it in the commit body.
- rectang 5y agoAs someone who carefully crafts my git history, I hate it when somebody smashes my work.
- omegalulw 5y ago> I have to disagree with this as it relies on the assumption that every commit on a branch is logical and descriptive. In my experience a lot of PRs will have small commits that have poor names as they go through a review process. There's your problem. Code reviews should not allow such commits to pass through.
- t3h2mas 5y ago> Code reviews should not allow such commits to pass through. Are you suggesting that your code review process has a stage for combing through commit messages? What does this look like? If the third commit message of 15 isn't up to par what happens?
- derekperkins 5y agoYou ask them to fix the commit message. Every git GUI should support that by now, so it should be a 1 minute fix, even for junior devs.
- rzwitserloot 5y ago> I have to disagree with this as it relies No, you didn't read the comment fully, or you only disagree with part of it. Because, you clearly missed this part: > I still advocate for cleaning up and squashing your own commits as you see fit with an interactive rebase before your branch is merged. If you do that, you don't end up with 'small, poorly named commits'. Or if you do, you have a lazy programmer / an idiot programmer in the team. Which certainly happens, but, they ruin everything. You can't start shooting down processes, languages, tools, or anything else in the programmer space __just__ because some moron who abuses it ends up in a bad place. You need to show that a tool / feature / process / hook / etc turns otherwise fine, capable programmers into idiots in order to advocate for its abolishment. Not the other way around, or you end up with a blunt rock and a club and are then debating that they're holding the club at the wrong end.
- dahart 5y ago> I still advocate for cleaning up and squashing your own commit Completely agree. And I suspect the increasing frequency of squash-merging is mainly to avoid having to do the work of cleaning up and commenting individual commits in a longer sequence. I can see this both ways, it really is faster and easier to squash. And you’re right, it really does bury some context and functionally makes large changes harder to read or bisect or revert or modify. One benefit to squash merging that you might have overlooked is that it can encourage frequent (and messy) committing, knowing that the churn will disappear without having to work hard to clean it up. This does, in a way, make the git workflow more appealing and easier to manage for more people.
- mrinterweb 5y ago> One benefit to squash merging that you might have overlooked is that it can encourage frequent (and messy) committing, knowing that the churn will disappear without having to work hard to clean it up. I've noticed the opposite. Developers who know all of their work will be smashed into one commit at the end tend to not commit as frequently, and the commits they do make are just checking in all of their work at intervals. It is more of a process of saving state. It doesn't matter how frequently they commit if all the commits will become one.