I was guilty of merge hell until I learned about rebase.
I think it's a natural instinct to want to protect your production environment so I'm sure others have made the same mistake as I did. Main is my default branch, I don't want anything pushed into the default branch to result in a deployment to production.
So naturally I create a new branch called production. The relationship makes sense to me because we develop in main, might even deploy to staging from main, but it's not until we feel we're ready that we merge main with production. And to a user of git this requires a manual step where you explicitly specify the word production, git checkout production.
But that resulted in merge hell until I learned I could just rebase main onto production.
And the command structure is even exactly the same, standing in production branch I either do git merge main, or git rebase main.
In my experience, if there are no conflicts to resolve, then merge and rebase have near equivalent UX. Just a single command and git handles the rest.
However, if there are conflicts, I've always found them to be far easier to resolve during a merge than a rebase. That's not to say it's always easy, but at least with merge you only need to resolve them once. With rebase, you resolve the conflict, then have to resolve it again when git tries to apply the next change, and so on. Sometimes you even need to resolve conflicts bacwards if you're reordering commits. Much of this can be mitigated with git rerere, but if you're averse to merge, you probably don't want to learn about rerere either.
As a promoter of the rebase faction .. that's one case where I think "merge" is correct. Since you're not changing production without going through main (I hope), every merge should just go straight through ("fast forward"?)
git checkout production
git pull --ff-only main production
git push
(at which point CI auto-deploys 'production')
(edit: have you got "rebase main onto production" the wrong way round?)
I think they must have been cherry picking changes into production. Git merge might choke on the duplicate changes, but git rebase will usually see the change from each cherry pick is already applied and skip it.
Production shouldn't have its own branch - it shouldn't even be a new build at all. The same binaries that were deployed to staging should be redeployed to production once you approved. Otherwise, your "staging" environment has the wrong name... and the testing there doesn't represent what goes to production.
In a system with production branches and staging, you build for staging from the production branch.
When you're in the release process, the branch won't match what's currently deployed, but that's ok. The point of a production branch is not to indicate what is on production at this instant, but to be a record of what was deployed to production or at least was intended to be, for changes that get canceled before deployment.
Why not? A branch is a pointer to a commit, so the commit built for staging can be the same binary that will be deployed to production, if the production branch is updated to point to the same commit as staging was pointing to. No rebuild necessary because it is the same commit.
If you have fully reproducible builds, and if it's from the same commit, then it's probably okay. With multiple branches in play, and staging built from a different branch than production, the latter doesn't hold.
Good point. That is my conclusion as well, its been a while since I worked on deployments, but that is how we set up. Deploying is just a different pipeline on main branch that runs same exact artifact build in production
Its not a hill im dying on, but when you rebase the default branch, its gonna create conflicts for every single other team member. Its annoying to cause so much noise for every team member. Now I run with auto.rebase set, but that is not the default. Ymmv.
Yes, but rebase is like rebranch. So you take a branch from a tree, and plant it on top of a new tree. So, you rebranch (rebase) production branch on top of the main branch.
The point, as I understand it, is that production has no meaningful history separate from main's history: it acts as a bare pointer, and rebasing it just fast-forwards it to later points in main's history.
I think it's a natural instinct to want to protect your production environment so I'm sure others have made the same mistake as I did. Main is my default branch, I don't want anything pushed into the default branch to result in a deployment to production.
So naturally I create a new branch called production. The relationship makes sense to me because we develop in main, might even deploy to staging from main, but it's not until we feel we're ready that we merge main with production. And to a user of git this requires a manual step where you explicitly specify the word production, git checkout production.
But that resulted in merge hell until I learned I could just rebase main onto production.
And the command structure is even exactly the same, standing in production branch I either do git merge main, or git rebase main.
This comment was a message to my younger self.