6 ms·
I agree with the author's sentiment. The way this problem is typically framed is as a dichotomy between preserving a "true" history of what really happened on t
by infogulch 5y ago
I agree with the author's sentiment. The way this problem is typically framed is as a dichotomy between preserving a "true" history of what really happened on the micro/commit scale VS presenting a "clean" history that makes the story of the change easy to follow on the macro/PR scale.
This is a false dichotomy. I'm greedy, I want BOTH. Give me story mode when I'm just browsing the repo, but offer me the option to switch into commit-by-commit mode when I want more detail.
- andy_ppp 5y agoI've often thought this too, you shouldn't have to rewrite i.e. lie about what happened. Git history ideally should be completely immutable but there should be a view that tidies up what happened for those that like to see individual features/bugs/hotfixes all listed in history in a nice way. I don't like the name thought, commit groups seems odd, I prefer feature view or something else. The reason is commit groups sounds to me like groups of people who are allowed to commit.
- infogulch 5y agoI want to be able to preserve two parallel commit histories: one where the the commits are ordered by time, and another where the commits are ordered by 'story'. Git could cryptographically verify that the end-states of the two histories are identical, and allow me to alter the storied history at will (shifting hunks between commits, splitting/combining commits, reordering commits etc), where during merge both histories are preserved. I don't really follow your naming critique though. "commit groups" seems like a fine name, they are groups of commits. What you describe I would call "committer groups".
- dllthomas 5y agoSomething like --date-order to view commits chronologically vs --topo-order to view them topologically sorted?
- nine_k 5y agoWhat is your use case? How do you develop so that your story does not belong to one (or more) feature branches where it can be held, unmixed with other stories? Can your story continue through multiple merges to the main / release / whatever branch(es)? I'm asking totally unironically; every company's flow may be different, and for good reasons which I'm oblivious about. So I'd gladly read if you had time to explain.
- fragmede 5y agoThe ugly truth though, is that the process of programming can be shamefully bad. Often times the in-progress branch commits are the opposite of the platonic ideal commit message, for common human reasons. By 'common human reasons' I mean programming is messy, and it's often unclear why something does or does not work until after something functional is arrived at. The important thing is that your tools, specifically git, works for you, and not the other way around, so 'bad' commit messages like 'before', followed by 'after' are totally fine while working in the branch as long as it gets cleaned up during merge. However, they are the antithesis of useful months or years down the line while playing code historian. (Hilariously, the answer to the question "what idiot wrote this code", is sometimes the reader!) So is it a lie that sometimes after lunch on a Friday, the act of programming is often a series of off-by-one, off-by-two, off-by-one-the-other-direction compile-test-edit-commit loops? And that we'd prefer to be thought of as a genius that wrote some fundamental-to-the-company code 5-10 years later, with beautiful commit messages that live up to some platonic ideal, rather than "that one dumbass"? It's a lie the same way that people who wear makeup are 'lying'. It's true under a very specific, weird framing, but it doesn't really agree with reality. There are notable high profile exceptions like publicly viewable patch series against the linux kernel, but you're deluded if you think those aren't edited before being released for human consumption.
- Quekid5 5y agoThis is exactly right. It encourages people to Commit Whenever They Want To, secure in the knowledge that people will never see my -- I mean their -- feeble intermediate attempts at working code. Committing frequently is good. It means that reflog will often have interesting stuff in it, bisecting your feature branch might have a decent chance of finding obscure bugs discovered during development, etc. etc. It's a godsend once you truly Get It that all that ugly intermediate nonsense can be removed before merging. I suspect that people who advocate against the "rebase+rewrite" philosophy do Not Get It and work in a way where even their branch-local commits are pretty meticulous and tested, etc. Nothing against those people, but they can still work fine in an environment with rebase+rewrite being the default. I also have literally NEVER heard a good argument for keeping the full commit history (with WIP commits, etc.). There is nothing to be learned from it unless you're specifically investigating peoples' commit habits. ETA: Some IDEs have a Local History thing where you can basically see all versions of a local file (snapshot every 60s or whatever). Do you want that in your repository history? I don't think so.
- nine_k 5y agoGit history should not be kept immutable. Git release branch history should be kept immutable, because this is a way to see how things were in past, for troubleshooting, for ensuring that the code under source control is actually the code you deployed, and / or the code your downstream depends on, etc. On your feature branch, you can do anything, as long as you can later cleanly merge with the main branch from which releases are cut. I'd say it's a completely normal practice to rebase, split, and fixup your commits on the feature branch, in order to present a clean picture to the reviewers, to easily show that a new test catches the error in the old broken code, and the new fix actually makes that test pass, etc. Nobody cares about what happens on your feature branch but you. Its commit history is not holy, it's a tool like other tools. Somebody depends on oncoming progress of my feature branch while developing their own? Well, `pull --rebase` regularly, same as you do with the main branch. Squash that history during the merge to the main branch. Do not delete the feature branch, uncheck that checkbox in Github repo settings. Clean history representing completed features: check. Detailed explanation of development in code: check. On the topic of the article: to my mind, "commit groups" can be sufficiently well implemented as branches, or as tags and ranges of commits between tags. For some very complicated cases, they can be implemented as actual text tags inserted into commit messages.
- lmm 5y agoThe whole point of using a DVCS is to be able to publish and pull from each other's branches. If your feature branches are private, or you have to check with someone before pulling from their branch (which you do if they're in the habit of rebasing), then you're missing out on most of git's value.
- dasil003 5y agoThis is an absolutely ridiculous strawman. Just because not every branch is a shared branch doesn’t mean you aren’t getting “DVCS value”.
- lmm 5y agoI've been a programmer for long enough to have used SVN seriously. It really wasn't so different - it honestly did feel much the same as when I've worked in places that used a rebase-heavy git workflow.
- TomSwirly 5y agoI used to think this way. Now I think that we as programmers already suffer from too much information. I spend considerable time these days making my commits as clear and readable as possible, and between rebasing, squashing and amending messages, it's quite likely there there might be dozens of intermediate commit IDs for every single commit ID that enters the repo.
- jhardy54 5y agoI use merge commits as the “clean” history and non-merge commits as the “true” history. Are there problems that this approach doesn’t solve? My only gripe is that apps like GitHub don’t give me the option to display commits how I want, but that’s a problem with inflexible tooling in general.
- forty 5y agoI use the semi linear history function of gitlab: it's like rebase & merge, but doesn't fast forward (ie it always creates a merge commit) This way to see feature per feature I do git log --merges and to see the commits git log --no-merges
- hashhar 5y agoA pragmatic middle ground is learning fixup and autosquash and making the story mode before merging the code. Your story mode == commit mode provided you can divide at a good enough granularity. This is generally not a problem though.
- cortesoft 5y agoCouldn't you get this with squash and merge, along with not deleting merged branches? The main branch would have the story, and you could go into the actual squashed branch to get the actual commit history?
- Izkata 5y agoThat creates a mess. It's not clear which remote branches are still active, and can be difficult to link the branches back to the merges historically for hunting bugs. The best way I've seen by far: Prepare a fast-forward merge, then merge it with --no-ff. You end up with a linear history of commits grouped by the merge commits, can see either view in git log using --first-parent or not, and bisect can find the actual commit when needed.
- stormbrew 5y agoDoes this have some kind of distinct result from rebasing the branch before merging does? I'm not thinking of anything that would be different, so I'm not sure if using the more obscure command (`git merge --no-commit` vs `git rebase`) is for a specific reason.
- Izkata 5y agoDid you mean to respond to someone else? I never mentioned --no-commit, I'm talking about rebasing if needed - set up a fast-forward merge, which may or may not need a rebase. This top-level comment shows what the commit history looks like doing what I said: https://news.ycombinator.com/item?id=27723435 https://news.ycombinator.com/item?id=27723435 I also didn't just say rebase because that could also mean squashing commits manually and isn't what I'm talking about.
- stormbrew 5y agoNo, I've just never heard rebasing a branch described as "setting up a fast-forward merge." It implies doing something very different to me from a straightforward rebase, though with this elaboration I can see how you could describe it that way.
- dec0dedab0de 5y agoIt's pretty easy though. Leave all the commits. Put meaningful messages in your merge commits, and your clean macro history is just merge commits and the messy one is the rest.
- nomel 5y agoDoesn’t this require that you get everything right before that merge commit? I often do this, but then have some integration related change that’s required after.
- dec0dedab0de 5y agoThe change after would just be a new branch and then a new merge. First merge is adding the feature second merge is the bug fix.
- astrange 5y agoMerge commits prevent having clean history, because they lie to you. If you "git show" a merge commit, it hides almost all changes because they've been automatically merged, but it doesn't follow that they were merged correctly. This can cause things like gotofail.
- eMGm4D0zgUAVXc7 5y agoYou can show the full changes by one of these: > git show --first-parent COMMIT # perspective of target branch = branch you were on when merging > git show -m COMMIT # perspective of both branches Lengthy explanation and more ways to do it: https://stackoverflow.com/questions/40986518/git-show-of-a-merge-commit https://stackoverflow.com/questions/40986518/git-show-of-a-m... Also the following works in my experience and is more easy to memorize because the command literally says what you want to know: > git diff COMMIT_BEFORE_MERGE..MERGE_COMMIT
- Twisol 5y agoI think the scenario you've described assumes that the branches have diverged -- that each branch has a commit not on the other. But if you always rebase your branch onto `develop` before merging, your branch definitively has no conflicts. If you then use `--no-ff` to merge, it will create a merge commit anyway. This article shows what I mean: https://euroquis.nl/blabla/2019/08/09/git-alligator.html https://euroquis.nl/blabla/2019/08/09/git-alligator.html . (The only thing missing is the rebase before merge, since the example image shows a case where a merge could have hidden some changes.)
- blt 5y agoI interpret the author's proposed model as: "story mode" is git log --grouped and "commit-by-commit" mode is git log Are you proposing something different?
- reissbaker 5y agoGit does provide this feature :) For a view of commits that shows when they entered the current branch, rather than when they were authored (i.e. group all commits from the same PR together in the history): git log --topo-order For only viewing merge commits (as if you were using a squash-and-rebase strategy, but without having to rewrite history at merge time): git log --merges Assuming you are using branches as groups of commits — kind of the point of a branch — and you're using merges with --no-ff (which is the default on Github for the Merge button — https://docs.github.com/en/github/administering-a-repository/configuring-pull-request-merges/about-merge-methods-on-github https://docs.github.com/en/github/administering-a-repository... — and is necessary in this scheme to prevent fast-forward "merges" that would mess up viewing the merge history) rather than squashing and rebasing, `git log` shows you the "true" history, `git log --topo-order` shows you the chronological history of when commits entered the main branch, and `git log --merges` shows you the zoomed-out "clean" history of PR merges. Many people don't know about these features because Github doesn't have an option to view the log that way: only git does. TBH I wish Github had offered a --topo-order and --merges selector to their commit log view before offering a myriad of PR merging/rebasing options: git provides a wealth of solutions to viewing commit history without forcing you into destroying parts of it with squash-and-rebase. Edit: IMO, part of this issue is because of git's bad default log view. The --topo-order view is a much more useful view for reading the history of the repo (both for knowledge building and for debugging) than the default chronological-by-commit-timestamp view; typically you don't care what date a commit was authored on, as much as you care when it entered the main branch. I can't think of a single time I've actually wanted the default log view, and yet it's the default, and thus it's what Github shows.
- native_samples 5y agoYes! Thankyou for that. I knew about some of the flags discussed on this topic but not --topo-order. For my new project I've already decided some months ago to use merges with --no-ff when merging in work by other people, along with a kernel style "everyone gets their own repo" model. A lot of the discussion around Git workflow is basically noise created by the weak and hardly ever improved GitHub UI. True. They prefer building AI to building better log views on their core product. But, even much more advanced Git clients like the one in IntelliJ don't properly expose all the different ways of looking at git logs, and git has so many flags and options that it's nearly impossible to know them all. Even if one day you spend the time to read the user guide from cover to cover, newer versions will add new features and you won't see them. If the GUIs were better, I suspect all these discussions would quickly dry up.