Four Steps to Maintaining a Clean Git History
spin.atomicobject.com
spin.atomicobject.com
As with most things, there's no silver bullet that applies to every single case; different workflows work best for different teams and projects. Gitflow is both reasonable and fairly simple to understand and implement, but so is commiting straight to master and tagging "when it's done" for a single-person hobby project.
There's also no free lunch, and maintaining a clean history (whatever that means) takes more effort than just applying a set of rules (such as, always rebase, squash commits) after the fact. Linus Torvalds has said it better than I could ever do[0].
As far as the article itself goes, the author maintains that:
> A few common commits on my branches are: “WIP,” “Run Rubocop,” and “Fix typo.”
And then goes on to say that the solution to this is to rebase, rather than creating better commits from the get-go, or just deferring any commits until the end of the feature work, and then staging interactively in order to create multiple thematic subdivisions, or just commiting the entire workspace.
[0]: http://www.mail-archive.com/dri-devel@lists.sourceforge.net/...
Because we have rebase, there is not as much need for discipline when creating commits, because you can change change them later.
> and part desire to hide work that is incomplete or "imperfect"
When I do any kind of work, I usually submit the finished work to whomever needs it. It's not hiding, it's just giving people what they need.
When I use `rebase -i` in my workflow to alter my commit history, it's almost always for the purpose of helping code review. I want my commits to lead a reviewer logically down a path that helps them understand the role each change makes in a push request.
I kept wondering whether I was missing something.
I think maybe I had an epiphany just now, the last couple of sentences where the OP spoke about maintaining a clean project history suddenly made things click.
Personally, I don't want that, on the very occasional time I go into the git history what I am looking for is code history.....the story of how a piece of code arrived at its current implementation....that means I need all the commits, the "fixing a typo" commits, the "oops, overlooked a logic error" commits...
I don't want to see the history of the project when I look at git history, I want to see the history of the code.
Its messy, but it tells me so much. I can see how this piece of code arrived at its current state, who worked on it, and what they did.
The idea of git history as a way of tracking the project history just never occurred to me. Now I understand it, I definitely don't want it, but its nice to have a mystery cleared up.
Develop on a branch, yes; rebase the branch instead of merging in master, sure. But why delete the history by squashing, when a merge into the mainline can look just as neat without requiring history to be deleted.
The argument that I've heard is "so that I don't have to all of that detailed history." But that is a display problem, not an argument for removing history.
The reason I like doing squashes is not because I don't want a detailed history. It's because (1) it allows me to commit often, even when the code isn't fully finished, might not build or pass all the tests and (2) during code review, I might need to fix a typo, change the code, or make other changes. By squashing these commits into one feature commit, I can ensure that each commit builds and passes tests, which is very helpful when doing git bisects later. It also removes history that doesn't matter (those code review fixup commits, as well as all my work-in-progress commits), so what's left is a nice history of the project, hopefully with each commit describing in high-level detail what changed and why, as well as linking to a ticket/issue/bug report.
That also lets me only use merge commits for things that really are "merging", such as merging develop into master, where master has additional hotfix commits. I always use merge commits for that (never fast-forwarding), so it's always clear when code was merged from develop and released.
What you've described -- committing often and later combining commits together into cohesive units that don't break tests -- is a lot like how I work. I use `git rebase -i` for this; never `git merge --squash`.