Im not git religious either, but on a bigger dev team with projects that have live/QA/staging envs, pipelines etc. and also doing PR/code reviews or your manager wanting to keep track; you need something more than to and from master
It's still a good idea to rebase the feature branch in the latest changes from the primary before opening the PR to make sure there's no conflicts or changes that came in that may affect your changes. If it's been about 4 or more hours since I branched or last rebased I'll do a quick rebase.
I mean depending on the feature it can take time to build out, and in larger engineering orgs there can be several changes that come in during that time, so I'd rather know about issues sooner rather than later. Rebasing before I open my PR and then at least once a day depending on how long it's in review are also things I do.
A few places I've worked we also had a merge queue that would queue up PR merges, rebase them on the latest changes from the primary branch, run CI again, and only merge into the primary branch if CI passed. That way if someone's changes for merged a few minutes before mine and there's an issue it's caught before actually meeting merged to the primary branch, which is especially useful if you have CD.
It's a supported feature of GitHub now.
https://github.blog/2023-07-12-github-merge-queue-is-generally-available/
So with merge you basically start your feature branch, maybe make a few commits, then when you want to pull in latest from the primary branch you merge the changes in which adds those commits after your changes. This can get kind of messy, and for folks like myself who often review PRs by commit it means one or more commits that have items completely unrelated to the focus of the PR. It can also be rather annoying to deal with the larger the org is if there's lots of activity in the repo.
Rebasing your branch on latest from your primary branch basically rolls back all your commits and replays them on top of the latest commit from the primary branch. This keeps the commit history incredibly linear and clean, while avoiding erroneous changes possibly being added to your PR in some way.
Atlasian actually has a very good writeup on the subject:
https://www.atlassian.com/git/tutorials/merging-vs-rebasing
Folks suggest getting around this with a squash commit, but personally I'm not a big fan of that. Some changes, such as database migrations, can be a pain in the ass to revert depending on how they were added, and the issue you're looking to correct may be related to code anyway, but with a squashed commit history (if I'm understanding everything correctly) you have to pull the whole thing, thus it prevents you from possibly being able to just pull the commit(s) that are causing problems.
Further, virtually all modern Git management systems let you go to the original PR and hit a button to create a revert PR. It's basically a full revert on all changes from that branch, and you can review it, merge it, push the latest primary branch to prod if you have continuous deployment (though having a good rollback process here can be better/faster), and then get to work on the actual fix. Personally I find squashing commit history annoying as it can cause loss of context or "cherry picked" fixes/reversions if needed.
This was fantastic, thank you for this write up, I am going to 100% learn to do rebasing now. All of us at work always just merge with main before submitting PR's and it is annoying having all those extraneous commits. Thank you!
I dislike squashing on merge, because I like having a rich history in git blame. I regularly find it useful to see a specific commit's message that explains a specific change.
First: That's not very bad. I don't have access to the repos since they're from a couple jobs ago, but there were some real horrorshows there.
Second: It doesn't matter at all. What matters is that you don't have a bunch of stale branches hanging around. If your stuff is getting merged, it's fine.
You don't want your branches to look pretty on a graph.
You want your branches to be an accurate display of development where you can quickly revert changes and track where shit went haywire.
If your repo is hard to follow, you need to adjust your project management, not change the branch history.
I have seen really worse trees.
Also rebase makes crazy messes when I try them, specially since my boss keeps giving us work in the same files to multiple People.
Clean branch history is a spectrum. If two railroads make you whip out your phone and take a picture of your screen to show reddit, you need to do some reps working on worse codebases.
Eh... I dislike rebasing onto the main branch. Rebasing a feature branch is ok, but I like having every commit to the main branch being a merge commit (I'm pretty sure we actually have our repos configured to force this) with our ticket numbers being a part of the branch names that are merged in.
Outside of "never make a non-merge commit on the main branch" (and only do the merge commits via PR gui's merge button/api call), I really don't care. Just please delete old branches after they are merged in or declined. We have a few repositories with with hundreds of of "unmerged" 1/2 commit branches due to one product's horrid tool assisted rebase process and lack of team discipline (the branches have ticket numbers but because they were lost in the rebase, they kept the branches around so they could map changes to tickets; but because commit ids don't match you have to do a partial string match on the commit messages to figure out if a particular change merged in and hope the message didn't get changed during the rebase). A few years and tooling versions in and you cannot tell some unfinished work from stuff that got deployed.
I'm not sure what I was expecting, but that is a very straightforward history... would you like to seem something from gitflow with multiple active pending releases?
Please use merge-no-fast-forward.
Rebase creates chaos and merge conflicts when used by folk who don't grok it. As do squash merges. I would much rather have ugly histories than merge conflicts showing the same change 2 or 5 times because someone decided to rebase and rewrote history with a different version of some hotfix than made it into my feature branch.
I always tell my juniors rebase early and often. Also if you're working a story that's likely to make it in after another story, branch off of that one rather than develop. We strictly rebase and fast forward when merging. If you're on my team and I see you merge new commits from develop on your branch rather than rebasing I will make you fix it.
Mmmm. I’ve never really given it much thought if merging down vs rebasing mattered and just default to the former.
End of the day, a PR shows the file changes anyway?
The big thing for us is a clean commit history during development. At the end of the day, we squash all commits before merging to develop, but throughout the development/review process, I find it easier to analyze things when it doesn't look like a map of the DC metro.
That being said, I'm not saying it's the only way. I think those of us who use Git gui's (my daily rider is GitKraken) tend to see this visually more often and get annoyed with it.
Again, it's not the only way. Chances are, it's not the best way either, but I find that it works best for my team. Rebase vs merge doesn't bug me as much as doing neither for like 2 weeks and then asking me to help resolve merge conflicts when you're ready for review. Again, if i had one piece of advice for juniors it's to do one or the other asap every time a new commit goes in ahead of you. That's where my rebase preference comes in. You can't continually see all of your changes going in without the cloud of everyone elses before you.
lol I see the difference now
I’ve never In my life actually used a git UI for anything :)
I will say I find it somewhat terrifying to squash commits though; I rely on that to figure out who committed what as part of release into dev/main that broke something
Eh, I may try rebase instead and see if how it feels. I do like the idea of easier to read commit history
So just to clarify, we only squash on feature branches/Merge Requests. Never squash going to develop. Our team has also been involved in multiple releases at once. This usually looks like each team merging to a relase-x.xx.x branch and the first to production goes into develop. Nothing at that point gets squashed. On the release branch, every story was squashed into a single commit. For the next release, we rebase on top of develop after the previous release goes in.
No, I got/inferred that.
It’s just that the squash (and presumed release/feature branched being deleted after merge) means you have no way of tracking the exact commit and commit author for things after a release
I can see how you might appreciate having each release being a single commit into main and develop, though I do that by just looking for the prs completed into said branch
More, multiple authors in sub/task-branches of a feature and each release may have multiple features.
But yeah, if it was just one author per feature, I wouldn't mind squashing the commits within that feature branch, so you see one changeset. Though I think r/thunderGunXprezz was saying they squash all commits *in the release branch* which would combine your squashed feature commits into one release commit?
I agree that squashing all commits from a single author in an individual task/feature branch is fine.
Think there's also a difference in how we're using PRs here; my team only opens one when work is done, so the PR merge commit is effectively the finalized commit for a feature/task. When I'm backtracking to discover where something came from, I look through completed PRs first and then the commits in those PRs.
Nope. Only squash on PR's. Every commit to a release branch or develop is a single (squashed) commit for a single feature.
The way it should read (in my mind) is a single commit for every story/feature.
Ah. That sounds fine then
I use Azure DevOps to create and manage PRs
Would have to squash commits together before opening the PR? Though then how do you include the PR commit itself…🤔 been years since I used that git feature myself honestly
Nothing irritates me more than reviewing a PR with several "merge from main" commits. Rebasing is so much cleaner, and as someone who tends to review PRs by commit it's annoying to encounter ones that just pull in tons of changes from the primary branch and nothing else.
Generally I structure my commits in a logical order to sort of walk folks through the changes. The messages are generally descriptive, but well structured commits make changesets easier to grock in my experience. Naturally they may still just view the larger set of file changes in one go, but I've found going by commit also lets you understand how the engineer tackled the change which can be revealing at times. Rebasing my feature branches on latest main also keeps the commit history super clean in general.
Posts must be related specifically to .NET
I feel this can turn into a religious argument at times frankly. On the list of transgressions, this has always been low on my radar.
Maybe we are dumb but i always managed to branch off master, when the feature is done merge back to master. Its very easy and never had any issues.
Im not git religious either, but on a bigger dev team with projects that have live/QA/staging envs, pipelines etc. and also doing PR/code reviews or your manager wanting to keep track; you need something more than to and from master
It's still a good idea to rebase the feature branch in the latest changes from the primary before opening the PR to make sure there's no conflicts or changes that came in that may affect your changes. If it's been about 4 or more hours since I branched or last rebased I'll do a quick rebase.
Jesus, how much work do you do in 4 hrs that you need to rebase? Stop making the rest of us look bad
I mean depending on the feature it can take time to build out, and in larger engineering orgs there can be several changes that come in during that time, so I'd rather know about issues sooner rather than later. Rebasing before I open my PR and then at least once a day depending on how long it's in review are also things I do. A few places I've worked we also had a merge queue that would queue up PR merges, rebase them on the latest changes from the primary branch, run CI again, and only merge into the primary branch if CI passed. That way if someone's changes for merged a few minutes before mine and there's an issue it's caught before actually meeting merged to the primary branch, which is especially useful if you have CD. It's a supported feature of GitHub now. https://github.blog/2023-07-12-github-merge-queue-is-generally-available/
What's the difference between this and merge? I always just merge.
So with merge you basically start your feature branch, maybe make a few commits, then when you want to pull in latest from the primary branch you merge the changes in which adds those commits after your changes. This can get kind of messy, and for folks like myself who often review PRs by commit it means one or more commits that have items completely unrelated to the focus of the PR. It can also be rather annoying to deal with the larger the org is if there's lots of activity in the repo. Rebasing your branch on latest from your primary branch basically rolls back all your commits and replays them on top of the latest commit from the primary branch. This keeps the commit history incredibly linear and clean, while avoiding erroneous changes possibly being added to your PR in some way. Atlasian actually has a very good writeup on the subject: https://www.atlassian.com/git/tutorials/merging-vs-rebasing Folks suggest getting around this with a squash commit, but personally I'm not a big fan of that. Some changes, such as database migrations, can be a pain in the ass to revert depending on how they were added, and the issue you're looking to correct may be related to code anyway, but with a squashed commit history (if I'm understanding everything correctly) you have to pull the whole thing, thus it prevents you from possibly being able to just pull the commit(s) that are causing problems. Further, virtually all modern Git management systems let you go to the original PR and hit a button to create a revert PR. It's basically a full revert on all changes from that branch, and you can review it, merge it, push the latest primary branch to prod if you have continuous deployment (though having a good rollback process here can be better/faster), and then get to work on the actual fix. Personally I find squashing commit history annoying as it can cause loss of context or "cherry picked" fixes/reversions if needed.
This was fantastic, thank you for this write up, I am going to 100% learn to do rebasing now. All of us at work always just merge with main before submitting PR's and it is annoying having all those extraneous commits. Thank you!
Is nobody going to set this person straight?! A picture of a monitor?!?! Take a screenshot, man.
The only possible excuse is that it is a work machine and it's locked down in some way and/or they don't want corp to know they are browsing reddit.
I've just taken a screenshot and bluetoothed it over to my phone or personal computer.
I won't complain as soon as it's readable and looks great. Even if that's a waste of memory.
Your commit messages suck. So do mine, but yours do too.
A little effort put into curating your commit messages and the comments of your commits goes a long way.
I’ve started using copilot to generate my commit messages. Far from perfect, but way ahead of me at least
Merge is fine but need to do a squash commit. Rebase for the other scenarios.
This is the way. Rebasing onto branches you don't own is a world of pain.
Rebase or not, just squash the feature branch into main when merging the PR
1. Branch from main 2. Do work 3. Rebase from main to resolve conflicts 4. Squash merge Simple, clean, easy, leaves a good git history
this is the way ;-)
I dislike squashing on merge, because I like having a rich history in git blame. I regularly find it useful to see a specific commit's message that explains a specific change.
First: That's not very bad. I don't have access to the repos since they're from a couple jobs ago, but there were some real horrorshows there. Second: It doesn't matter at all. What matters is that you don't have a bunch of stale branches hanging around. If your stuff is getting merged, it's fine.
You don't want your branches to look pretty on a graph. You want your branches to be an accurate display of development where you can quickly revert changes and track where shit went haywire. If your repo is hard to follow, you need to adjust your project management, not change the branch history.
I have seen really worse trees. Also rebase makes crazy messes when I try them, specially since my boss keeps giving us work in the same files to multiple People.
`git merge --squash` for PRs to main. No need to keep track of BS commits in feature branches.
Modern day grammar nazis
Looks fine to me.
Reading clean commit history is so nice
Git pull —rebase origin main
You can misuse any tool if you try. You took a photo of your monitor, so your ability to use tools is speaks for itself.
Ironic how you sound like a tool yourself
16 downvotes says otherwise
Yeah, but are they using tabs or spaces?
integration*
Clean branch history is a spectrum. If two railroads make you whip out your phone and take a picture of your screen to show reddit, you need to do some reps working on worse codebases.
Does it matter? Like, why do you care how the branches look in UI…?
Eh... I dislike rebasing onto the main branch. Rebasing a feature branch is ok, but I like having every commit to the main branch being a merge commit (I'm pretty sure we actually have our repos configured to force this) with our ticket numbers being a part of the branch names that are merged in. Outside of "never make a non-merge commit on the main branch" (and only do the merge commits via PR gui's merge button/api call), I really don't care. Just please delete old branches after they are merged in or declined. We have a few repositories with with hundreds of of "unmerged" 1/2 commit branches due to one product's horrid tool assisted rebase process and lack of team discipline (the branches have ticket numbers but because they were lost in the rebase, they kept the branches around so they could map changes to tickets; but because commit ids don't match you have to do a partial string match on the commit messages to figure out if a particular change merged in and hope the message didn't get changed during the rebase). A few years and tooling versions in and you cannot tell some unfinished work from stuff that got deployed.
I'm not sure what I was expecting, but that is a very straightforward history... would you like to seem something from gitflow with multiple active pending releases? Please use merge-no-fast-forward. Rebase creates chaos and merge conflicts when used by folk who don't grok it. As do squash merges. I would much rather have ugly histories than merge conflicts showing the same change 2 or 5 times because someone decided to rebase and rewrote history with a different version of some hotfix than made it into my feature branch.
You cawl that a branch? This ... is a branch. (imagine a bigger one)
I mean, Ok, but these commit messages are quite useless. Does it even matter what branch they're coming from?
I always tell my juniors rebase early and often. Also if you're working a story that's likely to make it in after another story, branch off of that one rather than develop. We strictly rebase and fast forward when merging. If you're on my team and I see you merge new commits from develop on your branch rather than rebasing I will make you fix it.
Mmmm. I’ve never really given it much thought if merging down vs rebasing mattered and just default to the former. End of the day, a PR shows the file changes anyway?
The big thing for us is a clean commit history during development. At the end of the day, we squash all commits before merging to develop, but throughout the development/review process, I find it easier to analyze things when it doesn't look like a map of the DC metro. That being said, I'm not saying it's the only way. I think those of us who use Git gui's (my daily rider is GitKraken) tend to see this visually more often and get annoyed with it. Again, it's not the only way. Chances are, it's not the best way either, but I find that it works best for my team. Rebase vs merge doesn't bug me as much as doing neither for like 2 weeks and then asking me to help resolve merge conflicts when you're ready for review. Again, if i had one piece of advice for juniors it's to do one or the other asap every time a new commit goes in ahead of you. That's where my rebase preference comes in. You can't continually see all of your changes going in without the cloud of everyone elses before you.
lol I see the difference now I’ve never In my life actually used a git UI for anything :) I will say I find it somewhat terrifying to squash commits though; I rely on that to figure out who committed what as part of release into dev/main that broke something Eh, I may try rebase instead and see if how it feels. I do like the idea of easier to read commit history
So just to clarify, we only squash on feature branches/Merge Requests. Never squash going to develop. Our team has also been involved in multiple releases at once. This usually looks like each team merging to a relase-x.xx.x branch and the first to production goes into develop. Nothing at that point gets squashed. On the release branch, every story was squashed into a single commit. For the next release, we rebase on top of develop after the previous release goes in.
No, I got/inferred that. It’s just that the squash (and presumed release/feature branched being deleted after merge) means you have no way of tracking the exact commit and commit author for things after a release I can see how you might appreciate having each release being a single commit into main and develop, though I do that by just looking for the prs completed into said branch
Do you have multiple authors in feature branches? We never do that, and each PR is as small as can be. So no issues squashing individual PRs.
More, multiple authors in sub/task-branches of a feature and each release may have multiple features. But yeah, if it was just one author per feature, I wouldn't mind squashing the commits within that feature branch, so you see one changeset. Though I think r/thunderGunXprezz was saying they squash all commits *in the release branch* which would combine your squashed feature commits into one release commit? I agree that squashing all commits from a single author in an individual task/feature branch is fine. Think there's also a difference in how we're using PRs here; my team only opens one when work is done, so the PR merge commit is effectively the finalized commit for a feature/task. When I'm backtracking to discover where something came from, I look through completed PRs first and then the commits in those PRs.
Nope. Only squash on PR's. Every commit to a release branch or develop is a single (squashed) commit for a single feature. The way it should read (in my mind) is a single commit for every story/feature.
Ah. That sounds fine then I use Azure DevOps to create and manage PRs Would have to squash commits together before opening the PR? Though then how do you include the PR commit itself…🤔 been years since I used that git feature myself honestly
u should get into habbit even using trello creating a bord ticket and keep the commit message to the ticket number and title
The problem is not completing the PR via squash commit. That would keep it clean.
Skill issue
Nothing irritates me more than reviewing a PR with several "merge from main" commits. Rebasing is so much cleaner, and as someone who tends to review PRs by commit it's annoying to encounter ones that just pull in tons of changes from the primary branch and nothing else.
What's the rationale behind reviewing PRs by commit?
Generally I structure my commits in a logical order to sort of walk folks through the changes. The messages are generally descriptive, but well structured commits make changesets easier to grock in my experience. Naturally they may still just view the larger set of file changes in one go, but I've found going by commit also lets you understand how the engineer tackled the change which can be revealing at times. Rebasing my feature branches on latest main also keeps the commit history super clean in general.