8 ms·
The "squash and merge" trend with git bothers me, and perhaps I'm "doing it wrong" but it just doesn't capture what I need a commit history/git-blame for. Usual
by 32bitkid 10y ago
The "squash and merge" trend with git bothers me, and perhaps I'm "doing it wrong" but it just doesn't capture what I need a commit history/git-blame for. Usually, I don't care what feature a line code was for. I want to know why a developer thought that was the right change. And to get that visibility I tend to make lots of commits, treating commits almost as out-of-band comments that don't clutter the file/repo.
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.
- pcl 10y agoI'm with you. History is mostly useful after the fact to understand the details, not the big picture. 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.
- sergiosgc 10y agoI get close to the milestone-ish commit by opening feature branches and then merging with no fast forward. All commits in the main branch are merges, and all of those are features. The feature incremental commits go in the branch. It's ok, I'd just like to be able to apply this structure to stuff like bisect or blame.
- pcl 10y agoYeah exactly -- if git knew about a milestone point, then "git bisect" could tie into it. That in and of itself would be fantastic.
- bennofs 10y agoDoesn't `git blame --first-parent` work for that? From my quick tests, it seems like it shows the merge commit if you have such a structure (`--first-parent` also works for `git log` etc)
- juped 10y agoTotally does (though your maintainer has to care about first-parentage order, which they should, and which should be enforced by the software but isn't - see Junio's blogpost "fun with non-fast-forward", or "fun with --first-parent" for more basic info)
- gsylvie 10y agoAnd this: http://bit-booster.blogspot.ca/2016/02/no-foxtrots-allowed.html http://bit-booster.blogspot.ca/2016/02/no-foxtrots-allowed.h... (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. https://news.ycombinator.com/item?id=11193048.)
- juped 10y agoThanks. Git superstitions bug me a lot because it shouldn't have to be this way.
- sergiosgc 10y agoThanks! It does. Learning something everyday.
- 0942v8653 10y agoI agree, but here's their reasoning: https://github.com/reenhanced/gitreflow/issues/52 https://github.com/reenhanced/gitreflow/issues/52 > 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.
- deathanatos 10y ago> 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) 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.
- andrewchilds 10y agoAgreed, I'd much rather have the context of the commit message than the context of an entire PR, which could be a combination of 20 discrete changes, each with their own reason for existing which is explained by the commit message. If I need more context, which almost never happens, I'll just go check out the PR on GitHub.
- CJefferson 10y agoI agree, I wish some VCS would figure out how to do a "history of history". I hate every time in git I destroy history (delete a branch, do a force push / update), but it is almost impossible to use git without doing these things, particularly when committing to another project.
- jordigh 10y agoWe did figure it out, that's Mercurial Evolve: https://www.mercurial-scm.org/doc/evolution/sharing.html https://www.mercurial-scm.org/doc/evolution/sharing.html
- amk_ 10y agogit reflog https://git-scm.com/docs/git-reflog https://git-scm.com/docs/git-reflog
- jordigh 10y agoThat's not the same thing as a metahistory. It doesn't tell you which commit(s) replaces with commit(s). Mercurial Evolve, for example, will record if a commit was split into several commits or if a commit was folded (squashed) into a single commit. Thus you can trace the history of a commit as it, well, evolves. You can't easily do this with git reflog, because it doesn't store that information.
- amk_ 10y ago> because it doesn't store that information 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.
- jordigh 10y agoAll of the actual infrastructure for evolve is actually in hg core. This is the obsolescence markers and the logic for hiding obsolete commits. This infrastructure makes it so that all hg commands see a filtered set of commits if any are obsolete and "unreferenced" (hg doesn't really find commits by referencing, but the logic for when an obsolete commit is hidden is similar to git's referencing logic). 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.
- npsimons 10y ago> But there are so many people into it, that I feel I must be missing something obvious and it bothers me. 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.
- JimDabell 10y ago> 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 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.
- ghayes 10y agoI agree here. Be a good steward of your commits, and let `rebase -i` be your tool for that. A bunch of "err, try this instead" should be washed away, but it doesn't help to commit "Add Huge Feature" +10,000/-2,000 because "I should squash my feature"
- mikepurvis 10y agoIf you're putting up 10k lines of code in a single review, you're doing it wrong anyway. Why wouldn't you have multiple reviews that each add different parts of a feature and link to the same ticket?
- maxxxxx 10y agoI don't think history should ever be changed but there should be a way to view history as if a "squash and merge" or whatever you like had happened.
- 0x0 10y agoI like this a lot! Maybe way to add some metadata for a "commit collection" in git that is collapsed into a pseudo-commit by default (for browsing, bisect, blame, etc) but with the option to drill down/expand into sub-commits.
- zwily 10y agogit already does this. The message for the merge commit contains the overview of what's happening in the commits in the merge, and use `git log --first-parent` to only include the merge commit when one is encountered. That said, I still prefer squash/merge myself.
- infogulch 10y agoThis! 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.
- tomsmeding 10y agoThis would give the best of both worlds. People preferring the squash style can view the log cleanly, and people preferring detailed history can get detailed history.
- Kiro 10y ago> Usually, I don't care what feature a line code was for. I want to know why a developer thought that was the right change. 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.
- jon-wood 10y agoI've wanted both at different times, they answer different questions. The feature answers what it was added for, the commit answers the question of why.
- tunesmith 10y agoI think there's an inherent tension between your style, and the style that prefers pushing new branches immediately. 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.
- lotyrin 10y agoPush after rebase is safe and easy if: 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.
- takeda 10y agoAs long as no one else is using your branch as well, then they'll hate you.
- heeen2 10y agoIf I want to cherry-pick a feature, I want less commits to search for, ideally one big coherent one with maybe a few smaller fixes later on.
- Filligree 10y agoWith feature branches, I can merge the branch. That works just as well.
- ecobiker 10y agoThe way I see it, I don't want somebody else to do the squash for me. It's my responsibility to make sure my commits are logical. I do as many rebases, fixups, squashes as necessary and provide a logical set of commits. I want the merges to preserve that as it is. But as others have said, there are plenty of really valid reasons to alter history as one deems necessary.
- tjbiddle 10y agoIt's a good idea when you're working with small changes. If I'm working on fixing some bug, it should probably be in one-commit and done. But sometimes you're working on a bunch of "testing123" "save where I'm at" commits - and you don't want those in the end. 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.