Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
[flagged] Git commit messages are useless (trunk.io)
35 points by joshmarinacci on Jan 25, 2024 | hide | past | favorite | 69 comments


If you find commit messages useless, it's because you're making them useless.

It seems like the workflow where you get 20 "stuff" commits in a PR is to: git commit -am "stuff", test it, see that it doesn't work, make another change, hit up then enter on the shell window, test it, and so on.

If this is how you prefer to develop then I think testing first and squashing along the way might be better:

- initial change, test, worked? git add <files>, git commit -m "meaningful summary\n\n- meaningful note"

- small change: test, didn't work, git reset --hard

- another attempt: test, worked, git add, git add <files>, git commit --amend (new meaningful note)

If the steps you're taking to get to the end are meaningful or significant (maybe for a bisect in the future) then just commit with a meaningful message along the way.

More generally, I think it's more common create commit messages for "me", the writer, and not for the reader. Try instead writing commit messages (comments, documentation..) for an audience who doesn't have the context you have. For example: Nathan in 7 (or 2) years time who is tracking down the reason for a change you made which he suspects is the cause of a bug he's trying to fix.


Our GitLab instance started logging commit messages that all read "end", and I thought about it awhile.

It turns out that a coworker had discovered the --amend flag, but spelled it as -amend, and so it was interpreted as -a -m "end"


Hah. That's life at work thwarting our beautiful stratagems in a bluntly stupid way.

That's a good example why simple is good. Less surface for mistakes to happen.


I prefer the `git commit --fixup` / `git rebase --autosquash` approach myself.


What should happen during a squash/rebase is that the semantic meaning of commits should be revised for maximum legibility of a future maintainer.

If you did one "thing" on a PR branch, and it took you 10 commits to do it, those 10 should be squashed to one, and the commit message should be "Added thing."

If you did 3 "things" on a PR branch, and it took you 10 commits, you should squash those 10 into 3 semantically meaningful commits: "Added Thing#1" "Added Thing#2" "Added Thing#3" This is doubly true if you ran into some complexity during the implementation that caused you to have to do the extra stuff -- that's exactly the type of detail someone looking back on commits needs to understand the development history.

This is something that you are not allowed to do under most squash-merge policies, because "1 PR == 1 commit" for maximum legibility.

Of course, nobody ever takes the time to do any of this which is how we ended up with such policies in the first place.


It's kind of annoying since with squash-merge too if you are trying to develop dependent things since merging gets nasty on the dependees.


I'm yet to see a squash policy that would reject three semantically separated, valid commits with relevant messages.


why squash at all? I craft each commit meticulously. I want to keep every single one of them.


You are better than I. Or have a CI pipeline that can run locally.


I suspect that my opinion is in the minority here, but...

> With modern trunk-based engineering, pull request branches are squash-merged onto main

Commit messages are useless because of squash-merges, yes. However, my opinion is that it's the very concept of squash-merges that is the problem, not commit messages. Squashing eliminates all sorts of valuable information, and I think it's harmful.


I disagree entirely. A new feature or bug fix should be a single commit on the main branch. There's no need to see previous attempts to fix a bug or implement a feature in the git history. Especially commits that merely fix formatting.


Yes, I understand. The reason that I disagree is because of the number of times that having greater granularity than that has been enormously valuable.

In my opinion, a VCS should maintain a history of all commits, because it's impossible to know which commits will be the key to solving a problem in the future. Even commits that are later reversed can occasionally be of tremendous value.

A truly great VCS would allow you to do a "visual squash", hiding the intermediate commits unless you need to see them.


I think the preference to squash and rebase instead of merge is because of Github, honestly. It flattens the history out when the history is not flat at all.

If Github's UI showed branches diverging, commits being made to that branch, then the merge back to trunk like gitk does then devs could visually see why it's valuable.


That already exists. The merge into main is a single merge commit. You can view the merge as a single unit, or unpack it into the individual commits that comprise of the feature branch.


Say I run “git commit -am wip” in a for loop in the background, then squash everything before I make a PR. Is it your position to at every single character change I make in my editor should be preserved? That’s kind of crazy right?

I think you need to recognize that you have some implicit assumptions about what a commit even is, when you make such statements as “all commits [should be preserved]”.


It's equally wrong to rig up a context like that and say that therefore prs should be squashed.

In that frankly ridiculous example, nothing has actually changed but the location and the label for where the meaningful thing happens.

In your example, since you've artificially injected automation to snapshot every 11th keystroke, those keystrokes and those commits are indeed not meaningful. (I would argue that they're not useful either but I allow it's possible to argue they're useful)

But there is still some point where you do decide "here there is a meaningful milestone" and you mark that spot.

Other people do exactly that same thing with commit.

You've just artificially gone out of your way to make your own commits useless for that.


> It's equally wrong to rig up a context like that and say that therefore prs should be squashed.

Why? It’s super helpful for me. It makes me a better engineer, and nobody I work with has to care that this is happening, because it’s all gone by the time I make a PR. Why is it “wrong?” Because you have a certain definition in your head about what a commit “is”, and are making a bunch of blanket statement based on this assumption, and everyone who has different assumptions is therefore wrong?

To be fair, I don’t run “git commit” in a loop. I do however, commit extermely early and extremely often. I commit just about every time the code compiles, whether I’m done with what I’m doing or not. Whenever I decide “hmm, approach A isn’t working great, let me try approach B”, I make a commit. If approach B doesn’t work out either, I can compare it with my commit at approach A and decide which elements I want to take from both. I can create branches to do make this easier, so that I can switch between them at will.

The point is, I make commits at what should be considered arbitrary points in time, because for me, a commit doesn’t mean “a thing I want someone to review”. A commit means “I don’t trust my editor not to crash and wipe my undo history, so I’m going to create a checkpoint right now in case of a crash or sudden power loss”. Who are you to judge me for this? Why is it wrong?

> But there is still some point where you do decide "here there is a meaningful milestone" and you mark that spot.

Right, that’s called “a pull request”. It’s the reviewable unit of my productivity. When I decide “here is a thing I believe should be merged”, I put up a PR. I don’t believe this needs to be broken further into the endless commits that it took me to arrive at this point.

> You've just artificially gone out of your way to make your own commits useless for that.

No, I’ve gone out of the way to save my work. Git commit is extremely good at this, because it lets me save my work in a way that supports branches, which my editor’s undo history does not. It lets me compare these units of saved work in a way no editor can (even for editors which support branching undo history.) But with this workflow naturally comes the conclusion that I must squash all of this into one meaningful commit (with a good commit message) once it’s ready to be reviewed. There’s no reason whatsoever that anyone should care that I typed “git commit -am wip” a bunch of times while getting to that point.


git log --first-parent

Works best if your merge commits have useful messages.


The commit history should be clean, but not necessarily squashed

WIP commits should be rebased out before the branch is pushed

Commits which fix formatting should definitely be a separate commit so they can be added to `.git-blame-ignore-revs`. This allows anyone looking through the history of a change to see the functional fix, rather than having it mixed in with a refactor/reformat operation.

In this case, each commit should have a useful commit message, both allowing them to be searchable, and to help understanding of the change


Did you purposely write this comment so it reads like a series of commit messages, or are you just wired that way?

(I agree on all points.)


"There's no need to see previous attempts" and "a new feature should be a single commit" are very different things. I mostly agree with the first and don't think it's worth saving a failed attempt at something just because it happened to get committed at some point, but I still regularly implement features in multiple commits. It's very normal to do some refactoring to make the new feature easier to implement and then implement the feature, and those are separate changes that should be separate commits.

A commit that only changes formatting is a prime example of a useful secondary commit. Separating formatting changes from code changes makes it much easier to see what the actual functional changes were rather than them being hidden in a mess of non-functional changes.


Depends on the codebase perhaps. I sometimes touch parts which are not directly relevant to the the task e.g. mostly a minor reactor, a minor bug fix etc. It's nice to leave a trail on that particular change that it was just a refactor instead of exploring whole changeset only to find out that this change was irrelevant.


I've found worktrees[1] are a great tool for this use case.

"oh. i should fix this, but it doesn't have anything to do with what i'm currently solving." cd ../worktree-checkout, make a branch, do the fix, push, open a pr. then cd ../original-checkout and continue on. rebasing the fix into my wip when the PR is merged (or cherry-pick if you're confident) as needed.

1. https://git-scm.com/docs/git-worktree


By squashing, you lose ability to effectively bisect.

Instead of finding an offending commit that has only a few lines to analyze, you only get a massive feature-landing commit that doesn't narrow it down.

Interactive rebase or amend can be used to squash "oops forgot a semicolon" junk commits.


This is literally furthest front the truth. Instead of having develop of all building test passing squashed commits you have to fiddle with bisect around commits that accidentally break the build and fail test and god knows why.

Squash is basically a hard requirement for bisect to be useful at all. Especially for compiled languages.


I think you're typically dealing with much messier git histories than I do.

Anyway, accidentally-breaking commits can be skipped, but squashed commits can't be unsquashed.


Making meaningful commit makes sense, however with git you can show parent commits only, to me that's sufficient to say "put whatever garbage you want inside the pr", because you can still look at merge commits only.

Github is the problem here. And squash merge is "useful" as in when I would have squashed a commit even before merging, I don't think we should squash merge otherwise


There is a need when your feature causes a problem. Any nontrivial feature will require multiple distinct conceptual changes to the codebase, any of which could be at fault. Squashing completely neuters git bisect's ability to find the actual change that caused the issue. With squashed commits, you're stuck digging through a giant diff when you could instead be looking at a small unit of change.


‘git log —-no-merges’


Agree. We need a collapsed commit structure.


Every so often I log for a way to have git log only return tagged commits and commits where the commits you’ve requested come together. In general more tools for seeing simplified graphs would be nice


I disagree

For me commits is just backup/save.

The PR contains details.


The author clearly hasn't worked on a project where the maintainers care about the decomposition of the commits and the commit messages Make small commits, each of them do their own thing, each of them build and test successfully on their own. Most critically the commit messages should contain the motivation for the change. I love to cite error logs here to indicate what symptom it fixes.

It's a higher discipline activity but it's really worth it.


I think they do, but in a workflow where “make small commits” is now “make small merge requests”. When the merge request is squashed and merged, the message matters (which they say), but if you’re iterating on one small feature with feedback of CI/reviewers, those individual messages are arguably way less important, if only because they won’t become part of the true history


If you work on a repo with 120 teams across the world you spend your time making sure their stuff compiles and doesn’t break the build. Not that some guy actually made the commit history pretty.

You can have a 3 person team work with such policies. But it is unworkable for a huge repo.


Nice try - I was referring to open source projects like the Linux kernel which has thousands of contributors across the world.

It's absolutely not limited to three people teams.


I don't think commit messages are useless at all. It's not about "showing your work" like the author says. It's about summarising the changes in a way that you can quickly read and understand. People forget that commit messages don't have to be just one line, you can write full paragraphs explaining the motivation and thinking behind the change. Many projects enforce detailed commit messages like this because they can be invaluable years down the road when everybody involved is gone.

>Git recently added an --allow-empty-message flag, but really this is backwards. Commit messages should be empty by default. If you want to name your save points, you should have to do so explicitly. Actually, why doesn’t it just constantly autosave your work, like editing text anywhere else (Google Docs, Notion, etc.)?

If I were to clone a repo and find empty commit messages I would probably flip a table and refuse to work on it. This is a terrible idea. How would you use git bisect without commit messages?

The tool should not allow people to do things just because it feels easier.

>We all write them, and they cost the collective engineers of the world countless hours writing ridiculous messages like, “changed something”, “did work”, or the super descriptive, “stuff”.

These kinds of commit messages are typically an indicator of a broken process where somebody needs to commit to see something happen, like a deployment or build process, and aren't able to assert that stuff works locally.

I think the problem comes down to many people just using git as a glorified storage drive for code and not really understanding how to get the most out of the tool.


> These kinds of commit messages are typically an indicator of a broken process where somebody needs to commit to see something happen, like a deployment or build process, and aren't able to assert that stuff works locally.

This is one of my biggest pet peeves with services like github actions. Something running locally like "act" [1] isn't sufficient because it doesn't have everything github has and is extra friction anyway to get everyone to use it for testing.

[1] https://github.com/nektos/act


I think you're missing the point. How a lot of projects operate is that the commits on PR branches are completely pointless since they will be deleted when the PR is merged and the PR description will become the real commit message for the commit on the main branch from the squash-merge.

The trouble is that Git is trying to do two things at once. It's trying to do remote synchronization as well as change tracking all at once.

An alternative is just to do "git commit --amend" every time you want to fix some small bug, but that has downsides in preventing reviewers from seeing what has changed between PR iterations as well as preventing you from going back to an earlier point in time for some branch. When you have less than a dozen commits, it is completely reasonable to just look at diffs and timestamps to determine which commit you want to go back to.


In my opinion, squash merges are evil and enabled only out of necessity because people fill their PRs with spam commits and won't bother to fixup/squash themselves.

There are very good reasons not to enable squash merges. For example, code formatting changes should almost always be in a commit of their own and not squashed together with a refactor or new feature. If you bundle these changes together, git blame output becomes a mess and it's more difficult to distil what the actual changes were in a commit.

Crafting intelligent commits is a skill in itself that more engineers need to learn.


Non-squash commits are kind of a nightmare to actually implement securely. You need to make certain that all the commits are properly assigned to an actual person (no impersonation) which would involve implementing commit signing infrastructure which a lot of orgs don’t want to do.

It can also get confusing as a reviewer if people do any rebasing after submitting the PR.


If you think commit messages are useless, you're almost certainly using them wrong. The examples provided are fairly contrived. Yeah, so your local commits may not have a _ton_ of meaning, but you should write a meaningful PR description and (many times) if you do that part well, you can just re-use that for your commit message with minor tweaking.

Combine the flexibility of the shell and git aliasing, and I just don't understand how they could possibly be complaining about this.


One of the reasons I prefer squash or merge commit workflows over rebase is you choose the message for the entire blob of work at once.


Life is funny.

I am making a VCS that works exactly like this!

* Commits on personal branches are called "saves," and they are meant to be an undo/redo history that can be discarded.

* Saves don't need commit messages.

* Saves can only be merged into designated branches, and those merge commits need real commit messages.

* Saves can be rebased as much as possible.

* Commits on master/main cannot be rebased. (There will be a nuclear option for things that should have been secret.)

There are other things, but that is the gist.


Couldn't this be achieved in a git system via hooks at the shared repository level?


Probably.

I am not just developing the VCS for those features. It's also to solve the large file problem, the binary file problem, and the centralization problem.


I suspect the author just needs this a ‘git wip’ alias for their work in progess:

git config --global alias.wip '!git add . && git commit -m "WIP"'


Really depends on the project. For spinning up an MVP in ~1 week, there's very little benefit wasting time on thoughtful commit messages, because i) you're highly unlikely to use them for anything, ii) in an absolute disaster scenario, just rebuild the whole app - at most you lose a few days.

For a recent project, I didn't push to GitHub for about 8 weeks. No point. Just one extra step. Only benefit is if I lose my laptop I've got a backup. But there's a backup on heroku. So the only time I'd need the GitHub version is if both my laptop went missing (hasn't ever happened, but I cede it could happen), and heroku somehow loses it (again, has never happened, but I guess it could).


My method is slightly different. For pet projects, I work on main until I deploy something, and I push to GH when it's building/running at the end of a session. I do git commit initially, and then "amend" as I go with intellij/goland's one click UI.

I try to write one line commit messages, mostly for posterity. Ive had some nice moments looking back on the "OMG it works" projects


Any human written text (commit messages, code comments, Merge Request messages, etc) that explain WHAT is done are useless. They are basically a GPT bash command away : `git diff | aichat "summarize and explain these git diff changes" `

Instead , people should write WHY are those changes being made. That's info that cannot be generated automatically, they surely have at the moment in time they are making the change and most importantly, that's the question that another dev will be asking himself 5 years later when reviewing the commit in the middle of a code archeology session: "why the heck did they do that??,"


Because of ticket FOO-123.


I agree with the author.

I think this is the consequence of git's model - there is continuous interaction happening locally.

It is important to save your work. I've even wondered if there should be "autosaves" just like in video games.

In other (centralized/shared) version control systems, the commit messages are important and well thought out, because a commit is when you merge your work with other people's work.

I think that point is when you should be prompted to enter a comment - it might even be required.

somewhat related, I also hate that when looking at files in gitlab, it shows the commit message beside each file, where more intuitively it should describe the file


If you work with more than 1 person on a project, commit messages can be very useful during reviews. Sometimes a change sets up a later change, and you need context on why the change is being done. It also forces you to split up your code into bite sized chuncks so changes are easier to understand for other contributors.

That being said, this is the only reason I think of for writing a commit message. After adding the commits into master (via rebase preferably), I've rarely read a commit message.


I somewhat agree. I like to just include an issue tracker's ticker number in a commit message.

It's just my preference. It's more important to enforce a consistent repository rule.


> They’re the author’s local save points

I would much prefer to use commit messages this way. I kind of do, but only half-way because someone else might read them and want information relevant to them, not just to me. But what I actually want is a message by me, for me, since I am far and way the most likely person to ever read it.


They are beyond invaluable for us, but we use githooks+shell to enforce the structure of the commit messages. Sounds authoritarian, I know, but this is MIL-STD stuff. The specs require detailed accounts of every change, so it's pretty important to be able to summarize them accurately.


My repository history tells a nice story. I like to keep it that way and certainly not useless.


Yeah I think the title is a little hyperbolic - the author is really saying "intermediate commits are useless, make sure you squash commit when you merge to main and have a good message there"


Like so much of HN "news", this is really just one person's opinon.

For the meme illiterate, please refer to the big lebowski...

NOTE: meme illiteracy is the condion of not being able to understand anything without references to a popular internet meme


This article says to use commits with the github title and summary which defeats his main point of it being useless and that it should be empty.


The source code tells you the "what." Good commit messages tell you the "why," especially when fixing regressions and bugs.


Useless? Come on. Documentation is hard, and I suspect rather than admit something is hard we'd just rather pretend that "it's not important."

> Requiring commit messages is a vestige of engineering practices from the ancient times of the mid-aughts.

I know it's been ~20 years, but hardly ancient. I suppose it's ancient to the young?

> With modern trunk-based engineering, pull request branches are squash-merged onto main — and all those silly commit messages are thrown out in the process.

I do work that way; but those commits are still preserved in git history on the branch I cut the PR from. People have gone back and read them! They've told me as much!

But also worth noting that this is a very github/gitlab-centric workflow; certainly the kernel devs don't work that way.

> You shouldn’t have to show your work like you did in school.

Commit messages aren't for showing your work, they're for explaining why you did what you did at a given point.

---

Honestly, in some ways I kinda see the point. But if you're not disciplined enough to squash your damn commits on your branch and re-write messages as-needed there, I just don't believe you're disciplined enough to write good PR messages. The author alludes to this when talking about how the real good stuff is captured in slack, google docs, etc. (all infinitely less-discoverable, especially as time marches on... but I digress). And if you aren't disciplined to write good PR messages either, then who really cares what your git history looks like at that point.

I work with and have worked with a lot of engineers with this general mindset - "the real information is in a meeting doc" or whatever - and it honestly sucks. Systems are less reliable, work is of poorer quality, lots of unnecessary work gets done, etc. It's a bad way to do engineering, and there's no other way to put it.


Its posts like this that ensure I’ll have a job for years to come. Comments are worthless too, I mean, just read the code!


No, you just write useless commit messages and haven't had to maintain a project that's more than 2 years old.


This is a ragebait post.


It's a marketing post.


Said like someone who's never had to do a git bisect


Some kind of commit message is useful. When I'm figuring out which point from this morning I want to roll back to, having them tagged as "blah" or "wtf is this?" helps.

But they're absolutely not worth spending a lot of time on. Write something and move on. I still commit a lot less than I should, and regularly regret not having committed, because I spent 4 years working at a place that required meaningful commit messages and that trained me out of committing early and often. Don't be that guy.

But definitely don't squash on merge. You lose all the advantages of git; you can't pull from other people's branches because their commits are going away, you can't automated bisect because you'll just land on your squashes. If you're going to squash then why even bother using git?


Tell me you are a scrub tier engineer without telling me you're a sctub tier engineer....




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

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

Search: