Hacker News new | ask | show | jobs
by ktross 1772 days ago
I agree with the idea, but disagree with the approach. This seems like a lot of extra work for not much, or maybe even less, benefit.

The process I've set up for my team allows us to get the best of both worlds, in my opinion, with almost no extra effort:

1. Create a branch and open a pull request. Nothing gets pushed directly to master.

2. After the pull request has been tested and reviewed, we Squash and Merge into master on GitHub with a single button click.

This way we end up with a single commit in master for each feature, bugfix, etc. There's also a link to the PR in the commit message where you can view the individual commits that were squashed as well as links to any related Jira issues.

2 comments

I think I'd go the other way around. Instead of squash/rebase, you should instead use `merge --no-ff`. The allows your main branch to have a clean history with the `--first-parent` option (e.g. `git log --first-parent`), while still maintaining the history on the branches. If you squash the commits, the original is no longer part of the commit history. Yes, there is a link in the commit message, but being able to manually click through to the commits on an external web page is a huge usability drop as compared to getting the information straight from `git bisect`.

Squash/rebase also plays horrendously with my local branches. If I make a PR, I should be able to use `git branch -d branch_name` to safely verify that the branch has been merged into main and can be deleted. If you squash/rebase instead, then I need to use the unconditional `git branch -D branch_name`. git can no longer verify that I'm performing a safe operation, because the history needed to determine whether it is safe has been rewritten.

> Squash/rebase also plays horrendously with my local branches.

This is a very good point, and it has been slightly annoying at times with this approach. It hasn't been a major pain point for me, so I've just dealt with it. I've seen some scripts/aliases that claim to solve this, but I haven't spent much time looking into it.

My current workflow is to watch for a PR to be accepted on github, then use the delete branch button in the GUI. On my local repo, I'll then use `git remote prune origin`, and only call `git branch -D` on branches that were pruned. It's a workable solution, and it could be scripted around, but I don't want to. Reproducing the functionality that already exists in git feels like a waste of time, when the entire purpose would be to work around the existence of a rebase workflow. Better would be to just use a merge/no-ff workflow in the first place.
The individual commits disappear if the branch or repo used in the pull request are deleted.
GitHub actually keeps these in the pull request indefinitely if you delete the branch. You can also restore the branch at any time if needed. We have the branches set to automatically delete when a PR is merged.
When I’ve done this before the commit messages get listed in the squash commit.
The list is useless, it's the contents that are helpful when debugging (and the wip commits just get in the way).
Exactly! Suppose feature A is implemented (commit 1). Then it is discovered that the original implementation breaks feature B, and that is resolved (commit 2). In merge workflows, you have a merge commit on main, while commit 1 and 2 are maintained. In rebase/squash workflows, you have a single commit on main, with both changes. If 6 months later I find that the commit broke some feature C, I really want to know if it was the main change or the compatibility fix that did it.
Right, though usually commit 2 would be placed before commit 1.
True, and that's a better way around it, since then both commits can run and pass the tests.