Hacker News new | ask | show | jobs
by anandsuresh 2292 days ago
I agree with this approach. It worked beautifully for me at my last job. Keeping master ready to deploy is the way to go, along with squashed commits for a linear history. A side-effect of this approach is that it makes it super easy to bisect your way should a regression occur; something that I've found is impossible with GitFlow.
2 comments

We use this work flow and it works masterfully. I have no need to save all my small commit - partly because I commit often to run tests in parallel on a CI server.

Does anyone know of a layer that you can use on top of git to make the occasional squash and rebase easier?

I know gitless is a helpful layer on top of git but not sure it support this specifically.

I mean, GitHub allows you to squash merge a PR, which is what we do at work. I find it really simple to summarize everything in the PR in that squash commit that ends up on master. I only rebase/squash locally if I need to make it easier for review
Can you still easily bisect to find which change broke a certain feature? I usually recommend against squashing because it's easier to identify an error in a 10-line diff than in a 2000-line diff.
We use the same method and yes, it's been usually easy enough to bisect from squashed commits. In mobile development it even helps, as bisecting effort is dominated by rebuilding time -- less commits makes for much faster bisecting.
The problem is more the state of the rebased commits. If it is a dirty history, bisect will break for a myriad of random reasons (broken tests, incomplete features etc.). So if you don't squash, and want to run bisect, you _have_ to ensure that all commits are clean and working. Easier said that done.
> So if you don't squash, and want to run bisect, you _have_ to ensure that all commits are clean and working. Easier said that done.

It can be done if the commits are separate logical units of work rather than work in progress commits. One approach I take is to take the diff between your branch and master, make a new branch based off of master and stage parts of that diff (parts that make a logical unit of work) and make a commit out of it. You can do that with commands like git apply with the relevant diff hunks.

Then, to test whether each commit works, you can run git rebase --exec "your-test-commands" master and it will apply each commit in your branch and run the test commands. If they fail, then you can fix the issue in that commit and run git rebase --continue to move onto the next commit.

This way, you can get a logical set of commits where each of them are in a working state.

Can the PR still show all the individual commits when you come back to it? If so, are they still in the repo with some keepalive tag or are they persisted outside of the repo along with the PR-comments/metadata?
Yes, GitHub keeps the separate commits visible in the closed PRs. For what it's worth, I never ever found those useful anyway and worked just with the squashed commits. It's up to the team to make sure the squashed commits don't grow to thousands of lines in size.
> Keeping master ready to deploy is the way to go

Are there really teams that don't do this?

Any software that has more than a few dozen developers and has tests that run for more than a few minutes necessarily will have broken master states at least occasionally. Otherwise you slow everybody down because merging to master can only happen (working hours/test run time) times per day.
And not all projects produce a single output from their source code.

I've worked on multiple projects over the years that had mostly a common code base but had to build and release to support different hardware platforms. In some cases, these needed significant but permanent divergence between the code for one platform and another.

In this sort of environment, concepts like "master branch" and "continuous deployment" have no meaning, and neither does a principle like always being ready to deploy. Your whole approach to things like branches, merging, rebasing, cherry-picking, bug tracking, and what a version number means is probably different to, say, deploying a long-running web application with frequent updates and all users running the same code.

If you're using gitflow, you've got a separate develop branch that everybody merges to, while master remains stable. Only when develop works and passes its tests, can it be merged to master.

And with multiple teams sharing the same code base, breaking master is going to slow a lot of people down a lot more.

I have little experience with multiple teams working on a single code base, but it sounds like a recipe for disaster no matter how you organise that. Make your code as modular as possible, so each team can take responsibility for their own code.

Openstack has the issue of long tests (nova takes two hours: https://review.opendev.org/#/c/711277/ ), but they still keep a green master. I don't think it's a problem in itself. The question is - why is anyone slowed down by merging? Why are people waiting for that action to happen?

Merging can happen more than the (simple calculation) times a day though. What openstack does is check each branch on its own, but then tries to merge all a number of waiting PRs at one time. If they pass on fake master again, that's merged into real master.

Github's interface is a big part of the issue (only for those using Github, of course).

Say you branch off of master, make some changes, and make a PR. Call this branch A.

Then you want to make a new branch, that depends on branch A. Call this branch B. The PR for branch A is still waiting to merge when you finish with branch B.

If you make a PR to merge branch B to master, you get a diff showing both PRs worth of changes. That's annoying to review.

If you make a PR to merge branch B to branch A, you get the correct diff for B. Huzzah! But if branch A's PR then merges, Github deletes the branch B PR and any comments/review. You have to remember to retarget branch B PR to master, then merge branch A.

It is interesting how in such a case there is an increasing blur between git and blockchain.
I work on an embedded device. Our tests include power analysis testing in LTE/GPS simulators of all the sleep/wake states. Total testing of a release takes about two weeks.

Trying to keep master consistent without git-flow means we get PRs sitting around for a month and merge-conflict hell days when we merge everything to make a build to send to QA.

Git-flow is bad if you have CD. Git-flow is great if you can't do that.

The part that's most contentious about git-flow is release branches.

You still should merge often to develop, which when tested becomes master.

The issue there is that you typically find some issues in testing, and need to fix them. That's why you test. You can either have a release branch and a develop branch, cherry-picking/merging fixes into the release branch as well as develop, or you can just hold off on merging any "not-for-this-release" branches for a few weeks. Just let the PR sit there. Alone. In the dark.
Amazon FreeRTOS.

Master is a working branch. Releases are pushed to Release and tagged with a date.