this post was submitted on 26 May 2024
43 points (92.2% liked)
Git
2886 readers
20 users here now
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Resources
Rules
- Follow programming.dev rules
- Be excellent to each other, no hostility towards users for any reason
- No spam of tools/companies/advertisements. It’s OK to post your own stuff part of the time, but the primary use of the community should not be self-promotion.
Git Logo by Jason Long is licensed under the Creative Commons Attribution 3.0 Unported License.
founded 1 year ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
view the rest of the comments
In many providers it’s possible to set up an automatic squash policy when merging to main. At our company the git history is just linear with well defined commits.
I don't think this is necessarily better. Some branches/projects are big enough that there are meaningful commits that should be made inside the project.
Yeah I agree but in my experience developers seem to struggle with "keep important things in history; squash unimportant things". An open "merges allowed" policy leads to people unthinkingly merging branches with 50 "typo", "fix" commits for a 100 line change.
Dunno what the answer is there.
The answer is Gerrit and learning interactive rebase.
How does that help?
The key thing gerrit provides is relation chains. You can push to the server your local branch and it will make a “patch” (like a pull request) for each of the commits in your branch. The patches are automatically put into a relation chain which lets reviewers go through them in sequence. Also your CI can test them together.
The idea is you need to locally make your commits ready for master. This is where interactive rebase comes in. You’ll have a normal local working branch and when you’re ready for review you use interactive rebase to squash some commits together, redo the commit message on some, change the order, etc. Basically you clean up your working branch into a series of commits ready for main.
Being able to easily push a relation chain of reviews up makes it way easier to make commits that land on main that just do one thing.
The second part of the solution gerrit provides is patchsets. When you need to edit a patch to deal with review comments, you actually rewrite your local history using git commit —amend or interactive rebase and push to gerrit again. In gerrit this will make a new patchset of your patch that you can diff between, see comments on, etc. It works very well for dealing with review feedback and for reviewers to quickly rereview.
It achieves this magic through a change-id that is added via git hook to the commit message. Even if you rewrite your history and your commit id changes it will still consider the rewritten commit to be the same patch as long as the change-id stays the same.
It’s pretty hard to just explain it like this. Using the workflow for a bit makes it much easier to see the value it has.
Yeah I get what you're saying. Gitlab can pretty much do that too, you just need a branch & MR for each commit, and then you tell it to merge each branch into the previous one. It automatically rebases them when their dependency merges.
Definitely more tedious to set up than just pushing one branch though. Maybe I should make a tool for that... Does Gerrit test each patch in CI sequentially or just all of them together?
But in any case that wasn't really the problem I was talking about. What I'm saying is that whether or not you should squash a branch depends on what that branch is. Neither "always squash" not "never squash" are right. It depends. And developers seem to have a real problem with knowing when a change is important enough to warrant a commit.
Though I suppose if people have to actually review each commit they would get a lot more push-back to "fix fix fix" type commits so maybe you are right.
Does Gerrit require each individual commit to be approved or can you just approve the whole branch/changeset?
Yeah you’ve gotten the idea I was going for. The workflow of gerrit incentivises forming commits with single ideas. It’s not always squash or never squash, it’s squash when it makes sense to. You still have to stay on top of reviews to get devs to do it, but it’s so much easier that there’s no excuse.
For CI, it depends how you set it up but usually you would test each commit in the relation chain to ensure they’re cherry pickable, back portable. It also helps to push devs to make commits single well contained ideas. Patches higher up in the relation chain will build with the patches below it.
Often you’ll push a relation chain up, get reviews on all of them, get green from CI on all, and then merge them all together. Normally you would set it up to rebase the commits and ff merge them to main.