As someone in favor of squashing, I can say that I don't want to see things like "oops, reverting last commit" popup in my git history, especially if I'm browsing history or bisecting a bug. That's noise - useless data. OTOH, commits should be the Minimum Necessary Change to accomplish a well-defined goal. The code itself should always be clear on what it is doing, otherwise it's badly written. If it's "deep magic", then comment it in the code as such.
That being said, I do think that reasoning for why a change was made, at every level, should be in the commit message. I'm also not a fan of merge, but prefer squash+rebase.
In all cases/workflows, it can be abused, and people writing bad code, bad comments or bad commit messages will do so until you can make them care to do it better. There's no silver bullet.
There's a middle ground between squashing and leaving a load of disorganised crap in the history. Rebase before merging. It gives you a chance to clean up the rubbish, but it doesn't force you to squash an entire feature's work into a single commit. You can preserve the logical changes without letting the crap into your history.
But as part of your point that commits should be the "minimum necessary change", it makes sense to send a logical series of patches that iteratively change a project to implement a new feature (e.g. adding new infrastructure), rather than one big patch to implement that feature.
Yes, but WHY it does that may not be obvious. "Oh, this code checks for a funny condition, but why would we care about that?". That's what commit messages are for.
> When it really comes down to it, the only place we care about enforcing a particular style of commit is in the master branch. We don't care if you make a thousand commits to get there, the only thing we care about is the individual features that come in from each (small) pull request.
> And while the history is nice, the biggest advantage of using the squash merge is that over time, git blame becomes way more useful. You get to see for every line of code in your project, not only the person who changed it, but their commit in the full context of why that change was made, including an easy-to-reference link to the pull request and ideally (through the pull request description), a link to the ticket tracker. So we can tie any line of code all the way back to the ticket that caused it's creation.
> And over time, that's all we really care about in the history. Who made this change and why was it made. Squash merging allows us to do that while still giving all of our developers the individual freedom to develop in the way that suits them best. To try and enforce commit styles in branches owned by other devs is to me, micromanagement that will go against the best results.
This is somewhat fair, but I feel it needs to be noted that even if you don't squash commit, if you look up a commit in Github, at the top of the page it will link you to the PR even if that commit is not the merge commit. I use this all the time to go from a random commit to a PR in our code, even though we do not squash commit. (We encourage, but do not enforce, an autosquash rebase against master; that is, history is kept, but you're permitted fixup! commits for really silly things like typos that we don't care to remain in the history, and it's left to your judgement what should be kept. The rebase cuts down on the amount of criss-crossing branches.) That said, I also use the individual commit message to, as the grandparent noted, figure out what a dev was — or wasn't — thinking.
There's value in both use cases: 1. Scrolling through the log to see an overview of the direction of the project on the level of complete features. 2. Being able to see exactly when, who, and why any single specific line was changed.
Squashing gives you 1, but throws out 2 on the way.
That said, I still prefer squash/merge myself.
I personally like to create a new branch locally - sometimes I'm experimenting and get ahead of my commits, and then I'll make 3-4 commits in bite-sized concepts. Other times I'll commit something that seems like it will probably work, and then I realize it doesn't, so I'm able to revert/reset the commit (so the commit is deleted rather than seeing a commit and then a revert in the log). And once I'm close to done, I can even rebase so my clean commits are all in a row. Then I push my branch.
I lose all that flexibility as soon as a team's process demands I push my branch as soon as I create it. I can no longer rebase (I still don't understand the guides that explain how to use rebase after pushing), reverts add noises to the log, merges from master interrupt the flow, etc. So in that sense, I can see the allure of a squash-and-merge to master.
I just don't think that pushing an empty feature branch takes advantage of the benefits of using git.
You have protection on your remote trunk branches against force push.
You have git configured to push only the branch you are on, to the same name on the remote.
git rebase; git push -f;
It is HARD, DANGEROUS and SHITTY under other configurations.
<3 Git.
It'd be nice if git let you push (for backup/protection) without letting other people see it or check it out yet.
Another option you might consider, if you need more flexibility, is doing your work in a branch off of your `feature-branch`, e.g., `feature-branch-wip`. When you're happy with your progress on `feature-branch-wip`, interactively rebase atop `feature-branch`, merge in, and push. Their process is satisfied, and they'll never be the wiser.
I wish git had a first-class model of a milestone-ish block of commits, so that the detailed commits and the feature milestones are disambiguated. I try to do this with merge points, but it doesn't seem to always work out, and since it's not native, it depends entirely on convention.
It's ok, I'd just like to be able to apply this structure to stuff like bisect or blame.
(p.s. your old comment on "git branching models" that starts "Not another one. All good git workflows are different..." was hilarious/awesome - https://news.ycombinator.com/item?id=11193048.)
And then if you're working on a larger feature, you have that feature branch and make these small one-commit merges into that branch. When you merge that larger feature - it'd be great not to squash those commits.
Is there something about the Hg architecture that makes it easier to plug in something like Evolve than with Git? Evolve isn't enabled out of the box on Mercurial either.
The "only" thing the Evolve extension does is expose a UI for creating and manipulating obsolete commits, but it's not the only extension that does it.
So, I guess you could build Evolve for git, if you absolutely cannot be persuaded to use anything but git. You would need to build obsolescence markers, and the proper logic for exchanging them between clones. Getting this right has taken a lot of work for hg, but maybe now that the ideas are mostly there, it would be easy to replicate them.
I'm the complete opposite. When I do a blame I want to see a direct link to the feature. I couldn't care less about the specific commit that changed the line.
When I think I'm done with a feature is exactly the time that metadata becomes relevant! Why would I want to lose it?
If anything, I wish ides would integrate git-blame more into my visualisation of a file
But there are so many people into it, that I feel I must be missing something obvious and it bothers me.