Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Its tragic how either/or git is.

Both are great in different ways. If Im trying to understand a complex tricky bit of code, a long string of small commits is ideal. If Im browsing a repo, large squashed commits or PRs are better.

It's be great to have better heirarchy, to get both.



Resorting to sleuthing around the commit history means the codebase has a problem with adequate commenting or unclear code.


Thats a remarkable amount of idealism.

Why bother writing PRs and commit messages at all, if this is true? Im not opposed to heading there, but I think a huge amount of reason intent & purpose is currently captured there in 99.9% of orgs. And that repository has always seemed like an invaluable repository of context.

I'd like to visit your pleasantville. I dont believe it is real.


Nobody almost ever writes detailed commits at my workplace, but I try to keep the code well documented when I can. Commit history can help sometimes but mostly just to establish timelines.


`git log --first-parent`

`git log --graph --oneline`

It's GitHub you want to complain about. git handles that perfectly well.


You can have both if you keep the PR branches


This is why I follow a rebase-then-merge approach. The commit graph looks like this:

   |
   *
   |\
   | *
   | |
   | *
   |/
   *
   |\
   | *
   |/
   |
Each PR is neatly delineated, and I can quickly follow things at coarse-grained level (follow only the left parents; there's even a `git log` flag for this) or at a fine-grained level.

This isn't just pretty -- this has been actively helpful to me many, many times. I can `git bisect` into a merged PR to more precisely identify where an issue arose, and `git rebase` onto intermediate commits instead of jumping all the way to the end if I find a whole PR to be problematic to rebase past in one go.


Semi-linear merge is my favourite too. I'll also often reset soft and hand craft the commits for the PR to lay out the work of the branch so that it builds up logically, and assist reviewers (and future-me) in understanding the structure of the change.


I also try to adopt this approach whenever possible. The 'git log' flag you mention is '--first-parent'.


Thanks for mentioning the specific flag! I didn't mention it because I don't use it often enough to remember it (the shape of the log is usually enough), but it does exist if you want it :D


I also enjoy waiting for unnecessary pipelines to run again, because we must first rebase. ;-)

It's XKCD's "My code's compiling!" for 2022.


It's a tradeoff. I've been in multiple situations where two branches independently work fine at runtime, and merge without conflict, but the merge is broken at either compile-time or runtime. I'd rather rebase with cognizance over what I'm rebasing over, and make sure my changes are actually semantically consistent afterwards.

Of course, if you have an organization-wide monorepo, this isn't going to work. (At the same time, at that point, you should probably be a bit more selective about what CI you run based on what components have changed... and make decisions about what checks to run nightly rather than on PRs.)


I leave all the commits in without squashing, but filter to only show merge commits


This is really weird to me -- the merge commits are the only ones without any information, because they are all autogenerated. The only time I ever look at a merge commit is when someone screwed up a merge conflict. I have written commands to filter out merge commits before.


It's worth noting that a lot of git's tooling supports --first-parent which only shows the "top level" commits in a branch. This means top level merge commits and commits that aren't part of any merges into the branch you are looking at. Ex:

For git log, this only shows you the commits that are merges and direct commits to the branch. For most repos this should correspond to individual patches/PRs/issues. It also sets the diff settings to use the same setting while in the log.

For git show, this shows you the diff against the previous commit at the same "level" in the merge hierarchy. So on master this should generally show you the diff between pr47-merge and pr46-merge. If you step one level into the merge hierarchy and diff a merge commit from master into that feature branch (even if said feature branch has now been deleted but was merged into master), it'll show you the diff between that merge commit and the previous commit prior to that merge.

For git bisect, it only tests against these top level commits before stopping. If your development requires that commits be rebased to functional commits prior to merge, this doesn't really change anything but for most merge-with-history style repos, this setting allows you to quickly identify where bugs are introduced.


There’s no reason merge commits can’t have a useful message.

On-disk, the only difference between a merge commit and a squash merge is that the merge commit has two parents.


> the merge commits are the only ones without any information

Huh? Merge commits usually have a high-level MR description included in their commit message.


By default from git, not gitlab or github, it's just "Merge branch 'Branchname'".

I think the project in gitlab also has to be configured to include the merge request description, so it can also be easily missed. No idea about github.


Git isn't either/or: GitHub is because it has extremely poor support for nonlinear history. It's not alone in that but git itself has the fundamental tools to support it.


Having all the commits, including the ones where you change your mind and try something different is not useful. Spending a ton of time to rewrite history crafting a ton of tiny commits is a waste of time over squashing.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: