I try to make my commit history nice but the way people obsess about it, I don't think is productive.
I try to make my commit history nice but the way people obsess about it, I don't think is productive.
I have a local branch, usually just called "wip" for work-in-progress and commit to it frequently. Then when I want to push to origin I pull all the contents from that branch into my "real branch" and commit it as one commit. Then delete the wip branch and repeat.
If I'm working on multiple tasks at once as my distracted brain loves to do, I'll have several wip branches. wip-new-hook-events, wip-update-sdk-version, wip-refactor-button-state. Sometimes the branches conflict with eachother, but dealing with that is worth being able to drop a task for a few days while I'm stumped or blocked. I also don't tend to micro commit when tests pass, just whenever I feel a smaller idea is either done, or I don't know how to progress yet.
I'll also add that sometimes I do break them into a few commits on "real branch" if it makes more sense to do so, and I use a GUI tool for merging if I need to solve conflicts. I also don't really worry about commit messages being useful in the wip branches. Oftentimes the commit message is just "wip".
The idea is that each commit should be small enough to fit in one "page" of PR review, with source lines and test line diffs <150 each, and everything should be one integrated and independent change with unit tests all passing and deployable to prod, etc. Honestly, I can't see a downside to this, other than maybe taking a while to internalize this process and to properly decompose commits.
Have you considered advocating for a change of company standards? Sometimes thats a sisyphean task, but if the only argument against it is "that's how it's always been done" it might be a worthwhile endeavor.
I have a "micro commit" sitting in a branch right now that's just a single line change, for example. That's not super common, but I don't have any strict rules for myself about when to or not to quicksave.
> Have you considered advocating for a change of company standards?
Oh trust me I did. I'm at a better job now :p My current company's git policy sounds identical to yours. But I still like this workflow for myself.
If you do 'git checkout wip .' it pulls in all the changes committed to your wip branch into the staging area of your current branch. Then you can just 'git commit -m "My meaningful commit message."'
That's the cool thing about git though, it has a lot of compatible workflows so you can do what's most comfortable personally.
Why bundle all changes into a single commit? How can the commit message be meaningful at that point? Why not just submit multiple atomic commits?
If I'm working on really small tasks where I know I'll be done quickly and won't need to look back at my earlier changes, I don't bother making a wip branch.
This is one of those "ounce of prevention vs. a pound of cure" situations.
We tend to discount everyone else's time but our own.
Might also be worth thinking about long term asymptotic effort vs marginal effort at a particular point in time--typically, the more often you do something (decomposing a commit into multiple independent parts, in this instance), the easier and less time-consuming it becomes.
Both. I don't really follow what you're getting at, I think we're in agreement? confused
My commits all stand alone; each is a distinct change that pretty much always is in a working state. Often it will be a series of refactors before the real change. Ironically, though it makes bisect easier, I find it rarely need to use bisect: just looking at commit messages (via either log or blame) is often enough to isolate a problem.
I accomplish this using interactive staging, and within my branch, and before I push, using any combination of rebase, squash, amend and fixup. I also prefix commits with the ticket to make referencing way easier.
My failed experiments (a change that later is undone) don't usually make it to anyone else, unless it's something modified during a PR review. On a small handful of occasions I've changed something radically and will delete the remote branch, modify and interactive rebase ny local one and push it again (or push as a new branch). For a feature I work on for a couple days, I'll commit a couple dozen times or more, rebase/squash to maybe 5-10 commits anyone else sees, and push to origin maybe 2-5 times.
When merging the branch (PR), I use merge --no-ff. This preserves commits and makes it easier to see later during a blame. And since the commit history is clean, it's not "noisy".
One of the massive benefits of this is the ability to take a big PR and split it up for easier review: I can branch off halfway, make a PR there with just the refactors, merge it, then the actual change merges cleanly later, and preserves the parent commit relations, so you can visually see what happened. This also works great when you fix a bug on the way to adding a new feature, or want to ship the early part of a feature early before everything is done (but only decide that after work has already started on stuff you're not ready to ship).
In general our OSes aren't storing a complete history of a file, so we rely on git "quick saves" (as someone else put it).
The git log is as much an artifact of the development process as the ticket history or the code itself. You don't want to publish your quick saves for someone else to have to dig through in two years time - give them something a bit more polished than that.
Up until the point of merging, other developers reviewing the PR can see your development path, and optionally examine individual commits. In GitHub at least, these individual commits usually make their way into the squashed commit's comments as a bulleted list of changes (after some cleanup), which encourages better final commit messages in general.
The point about bulled list of changes is a good one.
Why squash commits to begin with? Unless you're getting too many commits per package per time period, then maybe that's an indication that you should modularize your codebase.
I usually have my changes planned out before I start writing code, including which commits I want to make. Figuring out how to go about making a change is a design time problem, rather than implementation time imo
His commit messages are equally maddening - “change this variable to 5”, “fix broken spec”, “change variable to 7” ad nauseam…
It's the git equivalent of "useless comments" like `int x = 10; // set x to 10`
Comments answer why (and even 'what' is fine if the code is difficult.)
But simple rules like that always have exceptions.
It also makes tracing the historical "why" of a change easier to understand. If you don't squash it's a random change in the log, if you do squash then it's "adding feature x".