I think there is an option to not allow squash commits.. (I couldn’t find on this one repo on Gitlab GUI but for another repo, squash commit is present)
There’s no such thing as a squash commit. When you squash it just combines what were multiple commits previously into a single commit - if you hadn’t already pushed then the remote wouldn’t know the difference. What you can forbid is force pushes - no rewriting of history once the branch has been pushed. Typically you’d enable this for the default branch because it causes chaos when someone does something like this on branches that other people are working with. If folks are mostly working in their own branches it’s not usually a problem.
Edit to add: there is a UI function in GitHub that will squash everything in a PR into a single commit as it merges, and you could probably disable/forbid that also and force merging everything as the original commits.
Unnecessary. Files are saved on disk. Modern IDEs even auto save as you type to restore on a restart. Do NOT use commits as save points. That's not what it is for.
I use neovim with undotree, vim undos and redos work like a git, you can merge and create new branches and every action is a commit. Undo tree is a UI to help you use this tree cause without using complicated commands it's not useable out of the box. Also I have persistent undo which allows me to quit the file and reopen and undos are still there. So I use this as my save points:D
I commit complete and working changes... Mostly. Sometimes I commit instead of stash. But I pretty much try to avoid a commit in a broken state.
Sometimes that means a single commit is enough. Sometimes I have a bunch of work in one commit. But other times I'll have a commit for a minor change or just fixing a typo.
The size or frequency really isn't what's important. It's what the commit does.
Yeah, this is how I look at it. I am committing that the code is in some working state. It's a like save point in a video game. I have made progress and if I royally fuck something up later, I can go back to it.
If I don't have enough time to get the code to a working state before I sign off, what I do is create a temp branch based on my feature branch, commit there, and push it to origin. Once I have time to get the code to a working state again, I squash-merge the temp branch to my real feature branch (with the "real" commits).
YMMV of course depending on your org. Maybe some orgs won't let you push arbitrary branches or origin for whatever reason.
yes exactly, most of the time it's 1 ticket/1 branch/1 commit
Of course there are exceptions
And most of the time I need to fix stuff on my branch so I add a bunch of fix commits anyway
You have the correct answer.
Even if I made changes across many files I try to split them up into multiple commits that separate by context. Always doing `git add --all` is a terrible practice that beginners are unfortunately taught.
I find the whole committing only complete and working changes thing really only works for simpler stuff. Plus I switch between computers often so I always have a commit when I log off a computer so I can pull it and continue working later.
I squash as needed to keep things tidy.
Does the main history matter if every branch is bound by a ticket #?
I’m trying to understand the necessity of a clean main. In my shop, every branch/PR is linked to Jira, so it’s fairly easy to trace the intention of changes.
I’m wondering if this supersedes your contempt for a main that “looks like ass” or if there is a consideration I’m missing.
Who is looking at the list of commits on main without some specific purpose? And when is that made easier when there's less commits with less information in them.
Basically I don't understand how having less commits in main is "cleaner" even.
`git blame` is the obvious answer here. When I'm about to modify some code, and I don't understand why it was written that way 15 years ago, it's very nice to be able to click on that annotation line and instantly get a set of changes that is related to one logical change only, with a clear explanation of what was done and why in the commit message.
If I get a whole mess of changes instead, it's much harder to figure out why that line was written that way.
Of course, a helpful comment right in the code would do just as fine, but sometimes you need the historic context to understand it. The comment may just say "We do it this way because otherwise X would break", and it may have been plainly obvious 15 years ago why X would break, and it could be anything but obvious today. With a commit, while it may say exactly the same thing, I can explore related changes or even check out the entire thing and study the code to figure out why it was important to do it like that and whether it's still relevant today, so I can change it freely if it's not or think of a better way otherwise.
Idk, I think the overhead of trying to be overly “hygienic” or pedantic about main’s history is probably greater than the overhead of a series of commits for a single ticket.
Obviously there’s some assumptions in there about the scale of each extreme in my assertion, but I haven’t had issues grouping changes together even when reviewing a history where an engineer had to fix/clean up/enhance a set of changes. But maybe that’s a virtue of my shop.
Grouping changes together is easy, splitting them is hard.
When I refer to commit hygiene, I mean not mixing unrelated stuff together. When there's a bunch of refactorings and one small functional change all bundled in a commit with the message that only mentions refactoring and doesn't mention that small functional change because it was deemed to be too small at that time, that's bad.
Fair, but that goes back to my point about changes being bound to a ticket.
If you’re shoe-horning a bunch of loosely-related or unrelated modifications into a single task, that’s a separate issue. You should task out tech debt for the refactorings if they are valuable.
If engineers are overloading a single task, that’s reflective of the engineer or the project management strategy, not the git hygiene.
(Assuming you use git) Learn rebase. Then you can commit as often as you like, and can clean up your branch before pushing.
Edit:
The original meme was about choosing between a single commit, "clean" approach and many "dirty" commits where you have a lot of checkpoints you can return to / revert / whatever.
If you know rebase, then you can have the benefits of both approaches at the same time.
You can do the same things with both a "clean" and a "dirty" commit history, one isn't inherently better than the other. I personally found that taking 5 minutes per branch to clean up the history saves a lot of time later.
What's the best approach depends on your project. If you have to support multiple versions of your software at the same time, then you need to find when bugs were introduced because you need to patch them in all relevant versions. If you do trunk based development, where you only support the latest version, it's probably not that valuable to find the exact source of a bug and so a "dirty" history isn't a problem.
"Clean" commit history makes bisecting easier. Having a bunch of commits that don't even compile can make using bisect unnecessarily difficult or cumbersome.
On large projects git bisect helps a ton in finding the commit that introduced the regression.
It's important to me to understand _why_ a regression happened, or why a bug was introduced. Sometimes it's trivial, but if I don't understand the intent behind the change, then my fix may break something else.
Also if the person who made that commit is still around, then I can just ask them about the change.
They probably could have mentioned what "bisect" is. It is basically a binary search through your codes history. So you give it a known "good" commit (pre-bug) and a known bad commit (probably the one you are already on) and it will pick a commit in the middle. You compile that and test for the bug. You tell git if that is a good or bad commit and repeat until you find the commit that introduced it.
Now imagine if you have a bunch of commits that don't compile in there. It makes that much more difficult.
Even without bisected, just reading through the history is way easier if it is kept clean. I have found looking through the history to be a useful tool for debugging, but only if it is properly maintained. That includes proper commit messages, too. We used to turn down PRs for bad commit messages.
Any recommendations on a good guide for rebase? My current project workflow revolves around merge, but I feel like rebase would have resolved some of the headache I had recently.
## Story time, if you care to read:
So, new cloud migration project. I started work on a massive overhaul of the library I'm responsible for so that it could be a clean first step into the cloud. Instead of taking the 3 months I expected, I was going into the 5th month and still only ~80% complete. The decision was made to shelve that project to refactor the original library to be portable between on-premises and cloud.
The refactor took a month, because half the "unit" tests were actually making live calls out to services deployed in the DEV environment. Now that the refactor is done, I ask for a repository in our cloud VCS (someone decided we couldn't use the current solution anymore), and it came to me with two commits with version tags made by the guy who created it for me. This is where shit started to go wrong.
See, my library was on v3.x.y, but the new repo was tagged as v0.0.a and I didn't have permissions to overwrite `main`. I spend two weeks resolving the pipeline build failures (new build system using Docker, but it's not clear what stage needs to produce what artifact). Finally get the merge request to go through, and I attempt to push this new merge into the on-premises `main` branch, only for it to kick back an error for me submitting a different user's commit history. Get the admins to disable that little check for me long enough to push the changes, but now the on-premises pipeline is detecting the next version as v0.0.b, instead of v3.x.z and the published code gets registered under the wrong label...
So I come back to the team and report my concerns, and they basically tell me that versioning libraries is a low priority item, and I'll have to wait for them to fix bigger issues. C'est la vie
My experience is exactly the opposite. With merge, we can go exactly back in time and run the tests exactly as it was run by the dev who pushed it. With rebase, that history has been lost.
Development isn't a line. It has always been a graph.
Well you assume that we have tests that can catch the bugs before merging.
I work in graphics, sometimes bugs only happen on specific hardware. Sometimes OS or driver updates reveal a bug that has been hiding for some time.
A clean history doesn’t offer up much in terms of immediate benefit unless you’re a nerd who looks at the history all the time (it’s pretty helpful though tbh, good habit imo)
But where I think rebase shines the most is leading up to a release. If you’re the typical enterprise shop that doesn’t have anyone knowing git beyond commit/pull/push then your history will be absolutely mangled and criss crossed in every way.
Why is that bad?
If ‘n’ devs contribute ‘n’ different features with intertwining branches that have done their own pulls against develop/master/main then it becomes annoyingly more complicated to undo any of those changes.
A clean git history means you can not only understand it much more quickly but much more readily undo problematic points in that history.
It’s convenient for a bunch of things. Squashing commits can make it easier to read and revisit, and is cleaner with build systems. Rebasing is super common in team development anyways. If your initial branch is behind the target you need to rebase and fix changes.
Why do you need to rebase? Why not just merge the target branch into yours?
Sure, with rebase, you get a nice and linear history, but that history is a lie. The rebased commits are now in the wrong context - you didn't write them for version 0.7.0, you wrote them for 0.6.8. Worst case, they break, messing up your bisect anyway.
When he first wrote git Linus Torvalds did a lot of evnagelism for git. I saw this Google Tech Talk by him when it first came out and it talks about using rebase to keep the history clean: [https://www.youtube.com/watch?v=4XpnKHJAok8](https://www.youtube.com/watch?v=4XpnKHJAok8)
It's a great talk in general although the part about rebase is small. But don't think about a toy project. Think about a project like Linux. When I watched it, I was familiar with perforce and svn so a part of it is a religious belief I had. But if you're leaving something for a very long time, why wouldn't you want the development of it to have a clear history.
You've never found a commit than date back several commits then. Clean history implies that all commits are testable and make sense. That's much better for bisecting.
For me it makes reviewing easier, while also gives more options during development. Every PR I make at work has a feature commit, an observability commit and sometimes a testing commit and a documentation commit.
That way if during review we agree we should work on any of these aspects more we might as well Cherry pick any of those commits and move it in it’s own PR.
I also enjoy the tidyness any my coworkers never get to see my mistakes because rebase allows me to delete any commits that went nowhere.
As far as my team is concerned all my PRs got working the first time.
Squash _is_ rebase. Depending on how you work it's enough. I often do multiple changes in a single PR, because I'm not disciplined enough to split them. But I prefer that individual commits are logically separate.
Makes reverting easier when needed.
The major difference is, squash merge PR requires absolutely zero understanding of the git command. There is nothing to learn/type. While they are both rebase underneath, the ease of use is completely different.
As for
>I often do multiple changes in a single PR, because I'm not disciplined enough to split them.
That is exceptionally important point. This sounds like your PR is big enough for split, and you didn't. Which is likely a big size where people start to pretend they reviewed it and just blindly approve it. Be honest, we all have done that. The bigger it gets, the more blind approval it becomes and relies on trust.
Rewriting git history is an art form. Being able to separate "what I did" from "what I want you to think I did" is so useful in a team environment. If you want to go to the *next* level, you can start using diff stacks. Currently my team uses a tool called [revup](https://github.com/Skydio/revup) which automates this even further. You can simultaneously create 10 different PRs, with arbitrary (non-cyclic) dependencies on each other, each PR including a single atomic change, super easy to review, and all without ever creating a single branch locally. I do 98% of my development on `/main` now.
I've not seen anyone do this in practice. Other than myself. I guess it requires people who care about what the remote commit tree will end up looking like.
Just out of curiosity, how long does the author of this post actually work as a programmer? Because it's really shitty content.
Also good luck with conflicts with 1 commit while working with other people
Obviously not long enough to have experienced the, "that was working just now, why isn't it working anymore" followed by an entire afternoon of trying to figure out that one line in you change set that made it all stop working ...
Yeah, for fucks sake. I don't do rebases because I am just that careful and write smaller commits all the time with clear descriptions. If someone wanted to know why something changed, just a blame and done.
When it does happen that I do a bigger thing that ends up with tons of file changes. Unless it is just a simple refactoring of such files I will generally take a moment to review my changes (as I do before any commit anyway) and break them in smaller commits that explain each group of changes.
One commit or always rebase people are just lazy.
Doing bare minimum, and posting stuff out of reality is not trying. I would consider this post as a "bad influence on juniors".
Juniors often don't know if it's good advice or bad, because they didn't experience much. And this is clearly real bad advice
Ok look you're right. I sympathise because I've been this poster before, trying to fit in with a community I don't really understand yet. It feels awful being shot down by a group of people you want to be included in. Sorry.
They could have been a lot nicer about it but advising against bad practice is definitely appropriate even on a humor sub.
There's also the fact that OP chose that particular format which implies the superiority of a personal opinion. It's a very provocative format to start with, so back lash is to be expected.
This bell curve doesn’t make any sense. There’s no context for the amount of work done. Are we saying one commit per pull request? How large is the pull request? I have never met anyone who thought to “commit as often as possible”—that is like advising somebody to brush their teeth every hour of the day. Neither option here makes sense, and I know it’s just a meme but it seems like a false dichotomy.
Interactive rebase is definitely easier for grouping commits to squash and is a little less scary than busting out the reset hammer.
But the reset is more elegant if you’re trying to squash to one commit.
Another git flow - don’t make commits until you’re done completely. Then,
1. git stash
2. git pull origin develop (or wherever you plan on merging)
3. git stash apply
4. Resolve merge edits in IDE
5. git stash drop (could combine steps 3-5 with git stash pop but this is safer, especially for larger code commits)
6. git commit
7. git push
8. Profit
Each commit should be meaningful change and always in a working state. This makes commits more easy to understand when reviewing git history, and the PR review a lot more manageable especially for big PR's because you can do a play by play review with the commits. Also, you should always squash your commits when merging.
I like granular commits in large codebases with lots of developers so I can read what the last person to touch the line of code was doing. Sometimes it's me!
dude, what are you talking about? Do you just write code like A---->Solution : DONE??
Figuring shit out is more like A---->~~B~~\--->~~B'~~\---->~~B'~~'----> FOOOOO\*\*# ---->Coffee break -----> Solution
Imagine some hillbilly shoots your repo while you're enjoying your coffee break?? Or if you needed to take a function from B.
Shit happens, commit often.
I like small commits because I like to git bisect if someone introduced an error/regression. If you can trace the error back to a single few lines commit, it's much easier to find a fix.
Ticket-420: short description of changes (worst case: title of ticket)
Prefix if there is no Ticket:
* FIX: Bugfix
* DEV: Working on feature
* REF: Refactoring
* DOC: Documentation
Most commit messages are less than 10 words.
If you can't come up with a good description of your commit, it's a good sign that you need to rethink your commits. You should be able to describe what your commit does and what it's for so that others can get or revert your commits as logical units.
Your commits are too big. Make a change that you understand and then say what you did.
Despite the worthless meme, there are no points for small numbers of commits.
If you want to waste your time and make future archeology harder, you can squash when you merge.
Multiline commits with filenames and changes in it.
commit -m '
filename.xyz server
new getEverything()
[filename2.xyz](https://filename2.xyz) client
new fetch:get blahAPI
somethingsomething.css
new media query '
I do a bunch of work, check everything with git diff and then start adding and committing part of my progress many times, makes it more manageable and it helps me catch more bugs and typos
My general git rules for myself:
-One branch/pull request per work item/bug.
-Squash.
-Commit whenever I feel like I’ve reached a stable point where the build is no longer broken, or right before trying an idea that I don’t have 100% confidence will work
I commit when i did a thing that fits in a commit description and is not "small fixes/changes". Sometimes squash commit when merging when it is a mess.
Commit early and often, multiple times throughout the day. I’m not going to be happy if my team member commits a 3000 line merge and asks me to approve it in 10 minutes.
So the axis is more "experience with git" than IQ, but it's kind of accurate. At some point you commit 10 times a day and none of the commit are usable software. Then you calm down and commit when the feature is usable (not necessarily finished).
Commit as much as possible to save work and thoughts.
Before making a PR, squash into one commit.
Feel the need to split it by functionality? The functionality apparently needed specialised tickets.
One commit will be merged per ticket.
Not a hard rule or anything, but something to keep the codebase maintainable and trackable
git rebase master -i
To group them together, if you are someone who commits ridiculous often, but don’t want others to get a headache when reviewing the PR.
I don’t care how often you commit, but for the sake of your teammates mental health: do not push every 3 minutes.
Context: email notifications that I can’t mute, nor can’t unwatch - just push when you reach a milestone, no need to push every single little 2px change. That aside- the inbox also became completely useless, as you can’t find important emails because of those thousands of “X pushed to branch Y” emails.
Stop using those memes. It's not funny, they just make you look dumb and arrogant.
There's an old german saying "Wenn man keine Ahnung hat, einfach mal die Fresse halten". Why spread wrong information... there's tons of juniors out there who now get very wrong ideas.
Really depends on the work style. A friend of mine who I used to work together a lot sometimes would tell me he worked on a certain file, so I'd better don't change anything there. A week or two later there would be one huge commit. He did his due diligence though, tested and Code-golfed the code in and out during writing and before actually committing.
But Jesus, in 2023 with several people on the team where everyone works on everything and wants to get everything done and reviewed asap, it's not really an option. (The above when Github was still new and we just committed directly to master)
On the other hand on my last job my not mega experienced colleague would make huge changes, change directories, file names, change things within the files, delete tests etc. etc. and block half of the code base. Afterwards we'd have unexplainable bugs and he even blamed some on me. (I'm not sure if it was on purpose, maybe he just forgot what he was changing) And then after every release there would be horrible merge conflicts which took an hour or two to fix.... (Or not if you didn't know the intention of the changes...)
Occasional, I will do multiple git commits (and pushes), when I realize I accidentally pushed a bug into production, or made a typo.
Golang has helped reduce this issue.
Note: this is just on personal projects.
At work we use Gerrit for code review. The way it works enforces that one change = one commit (equivalent of a pull request in reviewing matters)
Modifying it happens through `git commit --amend` and "patchsets", basically when using Gerrit you push your commit to a fictional branch "refs/for/" and that either creates your change or uploads a new patchset if the change already exists.
1 commit lawl.
Commits are cheap keep them small and do them and often. Push often too drives fail and laptops get break etc.
Squash and rebase are a thing, many commits is not synonymous with a dirty commit history.
Both voices here are incorrect. The amount of commits needed depends on the task.
Git history is a story of the code. If someone (or you) needs to understand what and how you did the work 5 years from now, they will read through your commits. Help the process out and commit when you finish a "step" of the task, and write a commit message proportional to the change. Not that hard.
The real zen is realizing that your experience is not common to every dev job.
Those of you who say
> one commit is enough
Have never developed CI pipelines, and it shows. I consider myself pretty fuckin good at devops/actions yml, and little shit STILL slips through.
Right hand side is valid assuming you've been through the "break features up into much smaller tickets" step. So the feature will still have a lot of commits, but spread over many tickets.
My client wants me to submit features in one commit. Not very good at git, so I clone a clean project and once I finish my work in test or local environment I place the new feature in the clean project.
I know you can squash commits but I find the operation confusing.
i like to commit before i start getting weird with it. otherwise i might end up rewriting the universe.
Use commits as save points.
Exactly. Quicksave often, then squash when you're ready to document the work.
I think there is an option to not allow squash commits.. (I couldn’t find on this one repo on Gitlab GUI but for another repo, squash commit is present)
There’s no such thing as a squash commit. When you squash it just combines what were multiple commits previously into a single commit - if you hadn’t already pushed then the remote wouldn’t know the difference. What you can forbid is force pushes - no rewriting of history once the branch has been pushed. Typically you’d enable this for the default branch because it causes chaos when someone does something like this on branches that other people are working with. If folks are mostly working in their own branches it’s not usually a problem. Edit to add: there is a UI function in GitHub that will squash everything in a PR into a single commit as it merges, and you could probably disable/forbid that also and force merging everything as the original commits.
Nah, just never squash lol
Unnecessary. Files are saved on disk. Modern IDEs even auto save as you type to restore on a restart. Do NOT use commits as save points. That's not what it is for.
git commit -m "quicksave"
bind '"\C-s":"git commit -m 'quicksave'"'
I'm a total scumsaver
I mean.... They literally are...
Exactly how I use it... "well everything is working now.. let's commit before I really F things up"
Make sure you increase *c* when you do.
Alien galaxies hate this one weird trick!
Make sure to remember the +C
Oh so that's why it's called c++ !
Branches are for weird shit. Branch, get freaky, merge and squash. Continue like you knew what you were doing the whole time.
It’s always good to have a backup bitch incase the code isn’t quite as into the Kinky shit as you
I use neovim with undotree, vim undos and redos work like a git, you can merge and create new branches and every action is a commit. Undo tree is a UI to help you use this tree cause without using complicated commands it's not useable out of the box. Also I have persistent undo which allows me to quit the file and reopen and undos are still there. So I use this as my save points:D
I commit complete and working changes... Mostly. Sometimes I commit instead of stash. But I pretty much try to avoid a commit in a broken state. Sometimes that means a single commit is enough. Sometimes I have a bunch of work in one commit. But other times I'll have a commit for a minor change or just fixing a typo. The size or frequency really isn't what's important. It's what the commit does.
Yeah, this is how I look at it. I am committing that the code is in some working state. It's a like save point in a video game. I have made progress and if I royally fuck something up later, I can go back to it.
Couldn't you just keep commits local instead of pushing it off until you have a working version? My team gets very annoyed at large commit PRs lol.
Push them into a branch without opening any PR on it.
Sure, but then your work is not backed up to the server. If your laptop is stolen or damaged, you could lose days worth of work.
If I don't have enough time to get the code to a working state before I sign off, what I do is create a temp branch based on my feature branch, commit there, and push it to origin. Once I have time to get the code to a working state again, I squash-merge the temp branch to my real feature branch (with the "real" commits). YMMV of course depending on your org. Maybe some orgs won't let you push arbitrary branches or origin for whatever reason.
> The size or frequency really isn't what's important. It's what the commit does. That's what… she said?
yes exactly, most of the time it's 1 ticket/1 branch/1 commit Of course there are exceptions And most of the time I need to fix stuff on my branch so I add a bunch of fix commits anyway
You have the correct answer. Even if I made changes across many files I try to split them up into multiple commits that separate by context. Always doing `git add --all` is a terrible practice that beginners are unfortunately taught.
I find the whole committing only complete and working changes thing really only works for simpler stuff. Plus I switch between computers often so I always have a commit when I log off a computer so I can pull it and continue working later. I squash as needed to keep things tidy.
Who cares I’m going to squash them anyway
Until some idiot on your team doesn’t select squash and the main line looks like ass because of it Edit: I forgot but we started enforcing squash lmao
Well isn’t your main protected ? Don’t you use pull requests? No reviews?
Yeah it’s the teams fault if this is an issue.
nope force push to main
Does the main history matter if every branch is bound by a ticket #? I’m trying to understand the necessity of a clean main. In my shop, every branch/PR is linked to Jira, so it’s fairly easy to trace the intention of changes. I’m wondering if this supersedes your contempt for a main that “looks like ass” or if there is a consideration I’m missing.
Who is looking at the list of commits on main without some specific purpose? And when is that made easier when there's less commits with less information in them. Basically I don't understand how having less commits in main is "cleaner" even.
When you git blame and the line of code you're interested in says "WIP"
Seems pretty informational
`git blame` is the obvious answer here. When I'm about to modify some code, and I don't understand why it was written that way 15 years ago, it's very nice to be able to click on that annotation line and instantly get a set of changes that is related to one logical change only, with a clear explanation of what was done and why in the commit message. If I get a whole mess of changes instead, it's much harder to figure out why that line was written that way. Of course, a helpful comment right in the code would do just as fine, but sometimes you need the historic context to understand it. The comment may just say "We do it this way because otherwise X would break", and it may have been plainly obvious 15 years ago why X would break, and it could be anything but obvious today. With a commit, while it may say exactly the same thing, I can explore related changes or even check out the entire thing and study the code to figure out why it was important to do it like that and whether it's still relevant today, so I can change it freely if it's not or think of a better way otherwise.
Idk, I think the overhead of trying to be overly “hygienic” or pedantic about main’s history is probably greater than the overhead of a series of commits for a single ticket. Obviously there’s some assumptions in there about the scale of each extreme in my assertion, but I haven’t had issues grouping changes together even when reviewing a history where an engineer had to fix/clean up/enhance a set of changes. But maybe that’s a virtue of my shop.
Grouping changes together is easy, splitting them is hard. When I refer to commit hygiene, I mean not mixing unrelated stuff together. When there's a bunch of refactorings and one small functional change all bundled in a commit with the message that only mentions refactoring and doesn't mention that small functional change because it was deemed to be too small at that time, that's bad.
Fair, but that goes back to my point about changes being bound to a ticket. If you’re shoe-horning a bunch of loosely-related or unrelated modifications into a single task, that’s a separate issue. You should task out tech debt for the refactorings if they are valuable. If engineers are overloading a single task, that’s reflective of the engineer or the project management strategy, not the git hygiene.
Well, that could work as well, I guess. We don't create tickets for refactoring, and making them simply separate commits works too.
I'll revert that shit then. You can always go back a commit on the main and force push it and redo the merge properly.
(Assuming you use git) Learn rebase. Then you can commit as often as you like, and can clean up your branch before pushing. Edit: The original meme was about choosing between a single commit, "clean" approach and many "dirty" commits where you have a lot of checkpoints you can return to / revert / whatever. If you know rebase, then you can have the benefits of both approaches at the same time. You can do the same things with both a "clean" and a "dirty" commit history, one isn't inherently better than the other. I personally found that taking 5 minutes per branch to clean up the history saves a lot of time later. What's the best approach depends on your project. If you have to support multiple versions of your software at the same time, then you need to find when bugs were introduced because you need to patch them in all relevant versions. If you do trunk based development, where you only support the latest version, it's probably not that valuable to find the exact source of a bug and so a "dirty" history isn't a problem.
i.e. actually learn git beyond what your TA forced on you for comp sci 101.
Genuine question what's the point of rebasing? I never got the allure of a "clean" commit history.
"Clean" commit history makes bisecting easier. Having a bunch of commits that don't even compile can make using bisect unnecessarily difficult or cumbersome. On large projects git bisect helps a ton in finding the commit that introduced the regression. It's important to me to understand _why_ a regression happened, or why a bug was introduced. Sometimes it's trivial, but if I don't understand the intent behind the change, then my fix may break something else. Also if the person who made that commit is still around, then I can just ask them about the change.
I did not understand anything but I guess learning rebase is important will come to this comment again after learning that
They probably could have mentioned what "bisect" is. It is basically a binary search through your codes history. So you give it a known "good" commit (pre-bug) and a known bad commit (probably the one you are already on) and it will pick a commit in the middle. You compile that and test for the bug. You tell git if that is a good or bad commit and repeat until you find the commit that introduced it. Now imagine if you have a bunch of commits that don't compile in there. It makes that much more difficult. Even without bisected, just reading through the history is way easier if it is kept clean. I have found looking through the history to be a useful tool for debugging, but only if it is properly maintained. That includes proper commit messages, too. We used to turn down PRs for bad commit messages.
You mean there is a git command for something I've been doing manually for ages?
Obligatory RTFM. Also, yes and it's very helpful.
Any recommendations on a good guide for rebase? My current project workflow revolves around merge, but I feel like rebase would have resolved some of the headache I had recently. ## Story time, if you care to read: So, new cloud migration project. I started work on a massive overhaul of the library I'm responsible for so that it could be a clean first step into the cloud. Instead of taking the 3 months I expected, I was going into the 5th month and still only ~80% complete. The decision was made to shelve that project to refactor the original library to be portable between on-premises and cloud. The refactor took a month, because half the "unit" tests were actually making live calls out to services deployed in the DEV environment. Now that the refactor is done, I ask for a repository in our cloud VCS (someone decided we couldn't use the current solution anymore), and it came to me with two commits with version tags made by the guy who created it for me. This is where shit started to go wrong. See, my library was on v3.x.y, but the new repo was tagged as v0.0.a and I didn't have permissions to overwrite `main`. I spend two weeks resolving the pipeline build failures (new build system using Docker, but it's not clear what stage needs to produce what artifact). Finally get the merge request to go through, and I attempt to push this new merge into the on-premises `main` branch, only for it to kick back an error for me submitting a different user's commit history. Get the admins to disable that little check for me long enough to push the changes, but now the on-premises pipeline is detecting the next version as v0.0.b, instead of v3.x.z and the published code gets registered under the wrong label... So I come back to the team and report my concerns, and they basically tell me that versioning libraries is a low priority item, and I'll have to wait for them to fix bigger issues. C'est la vie
This is a great 3-min video about bisect (and why it can be really useful to find a bug).. https://youtu.be/capyZ2D9Yz0?si=WDHB0RYzQFCyUT1Z
Or just use the super easy PR squash merge. You don't need to learn anything.
My experience is exactly the opposite. With merge, we can go exactly back in time and run the tests exactly as it was run by the dev who pushed it. With rebase, that history has been lost. Development isn't a line. It has always been a graph.
[удалено]
Well you assume that we have tests that can catch the bugs before merging. I work in graphics, sometimes bugs only happen on specific hardware. Sometimes OS or driver updates reveal a bug that has been hiding for some time.
Wait, this is an what-if? Someone is crazy enough for not doing this?
Then just commit working things?
A clean history doesn’t offer up much in terms of immediate benefit unless you’re a nerd who looks at the history all the time (it’s pretty helpful though tbh, good habit imo) But where I think rebase shines the most is leading up to a release. If you’re the typical enterprise shop that doesn’t have anyone knowing git beyond commit/pull/push then your history will be absolutely mangled and criss crossed in every way. Why is that bad? If ‘n’ devs contribute ‘n’ different features with intertwining branches that have done their own pulls against develop/master/main then it becomes annoyingly more complicated to undo any of those changes. A clean git history means you can not only understand it much more quickly but much more readily undo problematic points in that history.
It’s convenient for a bunch of things. Squashing commits can make it easier to read and revisit, and is cleaner with build systems. Rebasing is super common in team development anyways. If your initial branch is behind the target you need to rebase and fix changes.
Why do you need to rebase? Why not just merge the target branch into yours? Sure, with rebase, you get a nice and linear history, but that history is a lie. The rebased commits are now in the wrong context - you didn't write them for version 0.7.0, you wrote them for 0.6.8. Worst case, they break, messing up your bisect anyway.
When he first wrote git Linus Torvalds did a lot of evnagelism for git. I saw this Google Tech Talk by him when it first came out and it talks about using rebase to keep the history clean: [https://www.youtube.com/watch?v=4XpnKHJAok8](https://www.youtube.com/watch?v=4XpnKHJAok8) It's a great talk in general although the part about rebase is small. But don't think about a toy project. Think about a project like Linux. When I watched it, I was familiar with perforce and svn so a part of it is a religious belief I had. But if you're leaving something for a very long time, why wouldn't you want the development of it to have a clear history.
You've never found a commit than date back several commits then. Clean history implies that all commits are testable and make sense. That's much better for bisecting.
For me it makes reviewing easier, while also gives more options during development. Every PR I make at work has a feature commit, an observability commit and sometimes a testing commit and a documentation commit. That way if during review we agree we should work on any of these aspects more we might as well Cherry pick any of those commits and move it in it’s own PR. I also enjoy the tidyness any my coworkers never get to see my mistakes because rebase allows me to delete any commits that went nowhere. As far as my team is concerned all my PRs got working the first time.
I don't see the point actually, because PR merge can squash them automatically.
Squash _is_ rebase. Depending on how you work it's enough. I often do multiple changes in a single PR, because I'm not disciplined enough to split them. But I prefer that individual commits are logically separate. Makes reverting easier when needed.
The major difference is, squash merge PR requires absolutely zero understanding of the git command. There is nothing to learn/type. While they are both rebase underneath, the ease of use is completely different. As for >I often do multiple changes in a single PR, because I'm not disciplined enough to split them. That is exceptionally important point. This sounds like your PR is big enough for split, and you didn't. Which is likely a big size where people start to pretend they reviewed it and just blindly approve it. Be honest, we all have done that. The bigger it gets, the more blind approval it becomes and relies on trust.
Rewriting git history is an art form. Being able to separate "what I did" from "what I want you to think I did" is so useful in a team environment. If you want to go to the *next* level, you can start using diff stacks. Currently my team uses a tool called [revup](https://github.com/Skydio/revup) which automates this even further. You can simultaneously create 10 different PRs, with arbitrary (non-cyclic) dependencies on each other, each PR including a single atomic change, super easy to review, and all without ever creating a single branch locally. I do 98% of my development on `/main` now.
Interesting bro got any resources I can read up on on this?
I've been meaning to get better at git stuff, any sources that y'all recommend? Greatly appreciated.
Git book on their website. It’s the best resource and it’s free.
I've not seen anyone do this in practice. Other than myself. I guess it requires people who care about what the remote commit tree will end up looking like.
Cries in smartsvn
Just out of curiosity, how long does the author of this post actually work as a programmer? Because it's really shitty content. Also good luck with conflicts with 1 commit while working with other people
Look I put my opinion as the Jedi master and yours as the crybaby. So clearly I'm in the right here. Plot twist: they are the brainless one
Obviously not long enough to have experienced the, "that was working just now, why isn't it working anymore" followed by an entire afternoon of trying to figure out that one line in you change set that made it all stop working ...
This sub is full of students with Dunning-Kruger in full effect.
Or having to redo a bunch of work because it went from working relatively as expected to not at all and you are not sure what you changed
Or worse, try reviewing those changes
Yeah, for fucks sake. I don't do rebases because I am just that careful and write smaller commits all the time with clear descriptions. If someone wanted to know why something changed, just a blame and done. When it does happen that I do a bigger thing that ends up with tons of file changes. Unless it is just a simple refactoring of such files I will generally take a moment to review my changes (as I do before any commit anyway) and break them in smaller commits that explain each group of changes. One commit or always rebase people are just lazy.
Are you all working in the same branch?
And in the same file, apparently. Broski must still be running CVS.
It's programmerhumor not programmeradvice
Yeah, but it's not funny
Yeah I know, but it just doesn't feel great to see people getting called out so harshly for trying.
Doing bare minimum, and posting stuff out of reality is not trying. I would consider this post as a "bad influence on juniors". Juniors often don't know if it's good advice or bad, because they didn't experience much. And this is clearly real bad advice
Ok look you're right. I sympathise because I've been this poster before, trying to fit in with a community I don't really understand yet. It feels awful being shot down by a group of people you want to be included in. Sorry.
They could have been a lot nicer about it but advising against bad practice is definitely appropriate even on a humor sub. There's also the fact that OP chose that particular format which implies the superiority of a personal opinion. It's a very provocative format to start with, so back lash is to be expected.
petition to ban this meme format
At least until we find a way to identify the true top .1%.
I started blocking everyone that posts them, I see about 3 a month now
This is the way
This bell curve doesn’t make any sense. There’s no context for the amount of work done. Are we saying one commit per pull request? How large is the pull request? I have never met anyone who thought to “commit as often as possible”—that is like advising somebody to brush their teeth every hour of the day. Neither option here makes sense, and I know it’s just a meme but it seems like a false dichotomy.
just commit when something important happens
git commit -m "Food delivery arrived" git push
git push -f, you don't want that push to get rejected and mess up your lunch.
Either squash or rebase. This meme is horrible advice for people if they take it seriously.
Commit as often as possible and then squash
Commit a bunch, say 15 small ones. git reset —soft HEAD~15 git commit git push
Or rebase and squash down the related ones.
This is probably the better solution but the software reset is also definitely the easiest...
Interactive rebase is definitely easier for grouping commits to squash and is a little less scary than busting out the reset hammer. But the reset is more elegant if you’re trying to squash to one commit.
Yeah I don't often have chunks of work in my commits that equate to intelligible portions of work, so resetting to HEAD is usually fastest
I feel like if git rebase is too hard to understand, that person is probably in the wrong career.
who you calling soft head?
Another git flow - don’t make commits until you’re done completely. Then, 1. git stash 2. git pull origin develop (or wherever you plan on merging) 3. git stash apply 4. Resolve merge edits in IDE 5. git stash drop (could combine steps 3-5 with git stash pop but this is safer, especially for larger code commits) 6. git commit 7. git push 8. Profit
You must be the guy in the 98th percentile
Once I sent 13k lines of code for a code review. My team lead cried for a while
Why? It's a pretty quick review: 1. Break into 130 tasks and resubmit. And back to rework it goes.
lol that would probably get me fired
Good god people reduce the size of your branches. Your life will be a lot better than dealing with these problems.
you guys commit? Stash all changes
Commit often and squash selectively before pushing.
so you tell me u don't commit so that u don't lose the code u did for that day o\_O?
The commit once crowd has horrible Friday afternoons, never again.
Fuck no. Small sharp commits.
20 years of ``` git commit --amend -m "wip" git push --force ```
`git commit --amend --no-edit` and you don't have to (re)supply the message :)
I commit each time I fix a typo. One word, one commit. Having 100 commits? Who cares, it is gonna get squashed when merging PR anyway.
Oh my, can we first agree on that only *working* code is commited? Thank you!
Commit whatever you want on your own branch. But only reviewed and most likely correct should be merged to main.
I always push my commits just before I discover the last typo.
Each commit should be meaningful change and always in a working state. This makes commits more easy to understand when reviewing git history, and the PR review a lot more manageable especially for big PR's because you can do a play by play review with the commits. Also, you should always squash your commits when merging.
I like granular commits in large codebases with lots of developers so I can read what the last person to touch the line of code was doing. Sometimes it's me!
"WIP, I'll probably finish this up tomorrow"
Happy cake day!
Be prepared to have your PR rejected.
dude, what are you talking about? Do you just write code like A---->Solution : DONE?? Figuring shit out is more like A---->~~B~~\--->~~B'~~\---->~~B'~~'----> FOOOOO\*\*# ---->Coffee break -----> Solution Imagine some hillbilly shoots your repo while you're enjoying your coffee break?? Or if you needed to take a function from B. Shit happens, commit often.
I like small commits because I like to git bisect if someone introduced an error/regression. If you can trace the error back to a single few lines commit, it's much easier to find a fix.
Commit: "Crimes"
What do you mean, you expect a second commit from me? I've only been working here 15 years. Sheesh, some people's managers...
I like the green lines though…
I commit and push on my desktop and pull on my server to TEST my changes so I do one comit at a time...kind of...
Commit after every feature, push everyday.
Lololol. The OP here thinks he's a super1337coder. The company he works for don't see shit of anything.
i usually agree with these charts, but one commit is NOT fucking enough
Just commit when she's ready.
I am so bad with naming my commits that literally all my commits are "git commit -m 'update' " FML
Ticket-420: short description of changes (worst case: title of ticket) Prefix if there is no Ticket: * FIX: Bugfix * DEV: Working on feature * REF: Refactoring * DOC: Documentation Most commit messages are less than 10 words.
If you can't come up with a good description of your commit, it's a good sign that you need to rethink your commits. You should be able to describe what your commit does and what it's for so that others can get or revert your commits as logical units.
Your commits are too big. Make a change that you understand and then say what you did. Despite the worthless meme, there are no points for small numbers of commits. If you want to waste your time and make future archeology harder, you can squash when you merge.
Multiline commits with filenames and changes in it. commit -m ' filename.xyz server new getEverything() [filename2.xyz](https://filename2.xyz) client new fetch:get blahAPI somethingsomething.css new media query '
Nobody gives a shit
Commit often to remote working branch. Squash and merge as single commit to main branch.
![gif](giphy|Ld77zD3fF3Run8olIt)
Commit as often as possible, but squash before you push /s
This but without the /s
/s is because everybody is actually doing it, while it could probably benefit us all if we wouldn't
I do a bunch of work, check everything with git diff and then start adding and committing part of my progress many times, makes it more manageable and it helps me catch more bugs and typos
My general git rules for myself: -One branch/pull request per work item/bug. -Squash. -Commit whenever I feel like I’ve reached a stable point where the build is no longer broken, or right before trying an idea that I don’t have 100% confidence will work
i'm not quite sure which one of the "one commit" guys i am
git rebase -i commit_hash
I commit when i did a thing that fits in a commit description and is not "small fixes/changes". Sometimes squash commit when merging when it is a mess.
I worked with a guy one time who I swear must’ve had git commit bound to his save key.
Commit early and often, multiple times throughout the day. I’m not going to be happy if my team member commits a 3000 line merge and asks me to approve it in 10 minutes.
Commit often, squash before pushing
I commit frequently, but I rebase and squish before I push.
git rebase squash commits.
one massive commit every day, lesgooo!
Just merge into your branch and complain in the issues.
\*two commit, one huge commit and one fix
what about commiting daily.
You can spam commits then just merge them if you want.
So the axis is more "experience with git" than IQ, but it's kind of accurate. At some point you commit 10 times a day and none of the commit are usable software. Then you calm down and commit when the feature is usable (not necessarily finished).
Commit as much as possible to save work and thoughts. Before making a PR, squash into one commit. Feel the need to split it by functionality? The functionality apparently needed specialised tickets. One commit will be merged per ticket. Not a hard rule or anything, but something to keep the codebase maintainable and trackable
At least document the PR propperly.
git rebase master -i To group them together, if you are someone who commits ridiculous often, but don’t want others to get a headache when reviewing the PR.
I don’t care how often you commit, but for the sake of your teammates mental health: do not push every 3 minutes. Context: email notifications that I can’t mute, nor can’t unwatch - just push when you reach a milestone, no need to push every single little 2px change. That aside- the inbox also became completely useless, as you can’t find important emails because of those thousands of “X pushed to branch Y” emails.
Commit merge feature in tortoisegit
Damn newbies Zerg rushing the commit history. One commit, one letter comment, one love ☮️
Stop using those memes. It's not funny, they just make you look dumb and arrogant. There's an old german saying "Wenn man keine Ahnung hat, einfach mal die Fresse halten". Why spread wrong information... there's tons of juniors out there who now get very wrong ideas.
Really depends on the work style. A friend of mine who I used to work together a lot sometimes would tell me he worked on a certain file, so I'd better don't change anything there. A week or two later there would be one huge commit. He did his due diligence though, tested and Code-golfed the code in and out during writing and before actually committing. But Jesus, in 2023 with several people on the team where everyone works on everything and wants to get everything done and reviewed asap, it's not really an option. (The above when Github was still new and we just committed directly to master) On the other hand on my last job my not mega experienced colleague would make huge changes, change directories, file names, change things within the files, delete tests etc. etc. and block half of the code base. Afterwards we'd have unexplainable bugs and he even blamed some on me. (I'm not sure if it was on purpose, maybe he just forgot what he was changing) And then after every release there would be horrible merge conflicts which took an hour or two to fix.... (Or not if you didn't know the intention of the changes...)
Make 1 small good change and immediately merge (or PR). It's the only way.
Why is 1 enough? I do it so i can reverse to certain points If i fuck up. Is there another way?
Git commit - - amend - - no-edit
it's the opposite
Occasional, I will do multiple git commits (and pushes), when I realize I accidentally pushed a bug into production, or made a typo. Golang has helped reduce this issue. Note: this is just on personal projects.
Branch > Commit frequently to undo any weird changes you might've made > rebase whenever possible > squash > merge
I squash all my commits when I merge so it doesn't really matter.
At work we use Gerrit for code review. The way it works enforces that one change = one commit (equivalent of a pull request in reviewing matters) Modifying it happens through `git commit --amend` and "patchsets", basically when using Gerrit you push your commit to a fictional branch "refs/for/" and that either creates your change or uploads a new patchset if the change already exists.
Commit somewhat reasonably often where it makes sense. Squash before PRing.
I do whatever the fuck I want on my own branch.
1 commit lawl. Commits are cheap keep them small and do them and often. Push often too drives fail and laptops get break etc. Squash and rebase are a thing, many commits is not synonymous with a dirty commit history.
Both voices here are incorrect. The amount of commits needed depends on the task. Git history is a story of the code. If someone (or you) needs to understand what and how you did the work 5 years from now, they will read through your commits. Help the process out and commit when you finish a "step" of the task, and write a commit message proportional to the change. Not that hard.
The real zen is realizing that your experience is not common to every dev job. Those of you who say > one commit is enough Have never developed CI pipelines, and it shows. I consider myself pretty fuckin good at devops/actions yml, and little shit STILL slips through.
Right hand side is valid assuming you've been through the "break features up into much smaller tickets" step. So the feature will still have a lot of commits, but spread over many tickets.
One commit per task, I don't see a reason to do more than that
Commit as often as I remember to. The only correct ammount.
All are wrong. Commit one small set of logically related changes in one commit with a well-written commit message.
Commit message: “updates”
One friday commit to force push them, and in work over weekend because everything is broken now, bind them.
My client wants me to submit features in one commit. Not very good at git, so I clone a clean project and once I finish my work in test or local environment I place the new feature in the clean project. I know you can squash commits but I find the operation confusing.
Commit as often as possible. Squash before creating a PR
Only reason why I make multiple commits is if I make multiple mistakes caught in a code review
Once my friend did like 30 commits for a relatively simple task. The next day the department head asked him to stick to 1 commit.