URI:
       [HN Gopher] Git commands I run before reading any code
       ___________________________________________________________________
        
       Git commands I run before reading any code
        
       Author : grepsedawk
       Score  : 1840 points
       Date   : 2026-04-08 08:53 UTC (18 hours ago)
        
  HTML web link (piechowski.io)
  TEXT w3m dump (piechowski.io)
        
       | gherkinnn wrote:
       | These are some helpful heuristics, thanks.
       | 
       | This list is also one of many arguments for maintaining good Git
       | discipline.
        
       | pzmarzly wrote:
       | Jujutsu equivalents, if anyone is curious:
       | 
       | What Changes the Most                   jj log --no-graph -r
       | 'ancestors(trunk()) & committer_date(after:"1 year ago")' \
       | -T 'self.diff().files().map(|f| f.path() ++ "\n").join("")' \
       | | sort | uniq -c | sort -nr | head -20
       | 
       | Who Built This                   jj log --no-graph -r
       | 'ancestors(trunk()) & ~merges()' \           -T
       | 'self.author().name() ++ "\n"' \           | sort | uniq -c |
       | sort -nr
       | 
       | Where Do Bugs Cluster                   jj log --no-graph -r
       | 'ancestors(trunk()) & description(regex:"(?i)fix|bug|broken")' \
       | -T 'self.diff().files().map(|f| f.path() ++ "\n").join("")' \
       | | sort | uniq -c | sort -nr | head -20
       | 
       | Is This Project Accelerating or Dying                   jj log
       | --no-graph -r 'ancestors(trunk())' \           -T
       | 'self.committer().timestamp().format("%Y-%m") ++ "\n"' \
       | | sort | uniq -c
       | 
       | How Often Is the Team Firefighting                   jj log --no-
       | graph \           -r 'ancestors(trunk()) &
       | committer_date(after:"1 year ago") &
       | description(regex:"(?i)revert|hotfix|emergency|rollback")'
       | 
       | Much more verbose, closer to programming than shell scripting.
       | But less flags to remember.
        
         | palata wrote:
         | To me, it makes jujutsu look like the Nix of VCSes.
         | 
         | Not meaning to offend anyone: Nix is cool, but adds complexity.
         | And as a disclaimer: I used jujutsu for a few months and went
         | back to git. Mostly because git is wired in my fingers, and git
         | is everywhere. Those examples of what jujutsu can do and not
         | git sound nice, but in those few months I never remotely had a
         | need for them, so it felt overkill for me.
        
           | Jenk wrote:
           | Tbf you wouldn't use/switch to jj for (because of) those kind
           | of commands, and are quite the outlier in the grand list of
           | reasons to use jj. However the option to use the revset
           | language in that manner is a high-ranking reason to use jj in
           | my opinion.
           | 
           | The most frequent "complex" command I use is to find commits
           | in my name that are unsigned, and then sign them (this is
           | owing to my workflow with agents that commit on my behalf but
           | I'm not going to give agents my private key!)
           | jj log -r 'mine() & ~signed()'              # or if yolo
           | mode...              jj sign -r 'mine() & ~signed()'
           | 
           | I hadn't even spared a moment to consider the git equivalent
           | but I would humbly expect it to be quite obtuse.
        
             | palata wrote:
             | Actually, signing was one of the annoying parts of jujutsu
             | for me: I sign with a security key, and the way jujutsu
             | handled signing was very painful to me (I know it can be
             | configured and I tried a few different ways, but it felt
             | inherent to how jujutsu handles commits (revisions?)).
        
               | arccy wrote:
               | The only reasonable way to use signing in jj is with the
               | sign-on-push config https://docs.jj-
               | vcs.dev/latest/config/#automatically-signing... rather
               | than as commits are made
        
               | Zambyte wrote:
               | Why? I have my signing behavior set to own and I haven't
               | noticed any issues, but I don't actually rely on
               | signatures for much.
        
               | singron wrote:
               | If you need to type in a password to unlock your keychain
               | (e.g. default behavior for gpg-agent), then signing
               | commits one at a time constantly is annoying.
               | 
               | Does "own" try to sign working copy snapshot commits too?
               | That would greatly increase the number and frequency of
               | signatures.
        
               | Zambyte wrote:
               | Ah, I use my SSH key to sign my commits and I don't have
               | a password on my SSH key.
               | 
               | > Does "own" try to sign working copy snapshot commits
               | too?
               | 
               | Yes
        
           | mamcx wrote:
           | No, jj is super simple in daily use, in contrast with git
           | that is a constant chore (and any sane person use alias).
           | This include stuff that in git is a total mess of complexity
           | like dealing with rebases. So not judge the tool for this odd
           | case.
        
             | Exoristos wrote:
             | One rarely needs more from git than `git add -A && git
             | commit -m`.
        
               | tcoff91 wrote:
               | I rebase stacked diffs all the time so jj makes my life
               | so much easier because its rebasing is much more
               | ergonomic than git.
        
               | beanjuiceII wrote:
               | this seems very easy in git tho how much easier can it
               | get, do you have an example of each of them?
        
               | dpatterbee wrote:
               | Git rebases don't work if there are conflicts, jj doesn't
               | have this problem. Also idk if you can rebase onto
               | multiple parents with git but jj can do it.
        
               | aidos wrote:
               | Can you explain how conflicts are not conflicts?
               | 
               | If I change a line of code several times and rebase on to
               | a branch that changed the same lines of code, how are you
               | sure what the right one is?
        
               | sunnyps wrote:
               | JJ can save conflict related state with the change so
               | that you don't need to resolve a conflict in the middle
               | of a stack of changes for rebasing to continue for the
               | remaining changes. Concretely, it uses a "conflict
               | algebra" where it can track the impact of a conflict as
               | it propagates through the stack of rebased changes:
               | https://docs.jj-vcs.dev/latest/technical/conflicts/
        
               | waisbrot wrote:
               | That sounds like https://git-scm.com/book/en/v2/Git-
               | Tools-Rerere ?
        
             | palata wrote:
             | > in contrast with git that is a constant chore (and any
             | sane person use alias)
             | 
             | I don't use aliases, I guess I'm insane?
             | 
             | Also 99.9% of the time, git "just works" for me. If I need
             | to do something special once a year, I can search for it.
             | Like I would with jujutsu.
        
           | rjh29 wrote:
           | It's the dvorak of git... Maybe more efficient but
           | incompatible with everyone else and a very loud vocal
           | minority.
           | 
           | You can find this pattern again and again. How many redditors
           | say 120fps is essential for gaming or absolutely require a
           | mechanical keyboard?
        
             | SatvikBeri wrote:
             | It's totally compatible though, and that's a big selling
             | point. I use jj and nobody else at my work uses it and that
             | has never been an issue.
        
               | palata wrote:
               | I think the "incompatible" was more in the dvorak sense,
               | which I believe is that whenever you are on another
               | computer, it most likely won't have dvorak.
               | 
               | For jujutsu, it's fine on your own computer, but you
               | probably have to use git in the CI or on remote servers.
               | And you probably started with git, so moving to jujutsu
               | was an added effort (similar to dvorak).
        
               | FrankBooth wrote:
               | It doesn't support submodules. So no, not totally
               | compatible.
        
               | zhengyi13 wrote:
               | That's a feature, not a bug /s
        
               | herewulf wrote:
               | Reminds me of how I started using Git when it was up and
               | coming: It was the best Subversion client out there and
               | no one knew I was using it!
        
             | RankingMember wrote:
             | I don't even like using "natural" keyboards despite the
             | ergonomic advantage because it ruins my muscle memory when
             | I'm on the (much more prevalent) "regular" keyboard.
        
             | deno wrote:
             | I mean let's not be hasty. Mechanical keyboards used to be
             | just normal keyboards when computers were still computers.
        
               | rjh29 wrote:
               | That is a fair argument. I don't know why they dropped
               | out of favour - price? Noise?
        
               | lamasery wrote:
               | My guess would be price. Shoppers probably got more
               | sensitive to the price of a keyboard as the price of
               | computers dropped, and approximately none of them were
               | choosing between two computer-bundles at the store with
               | any regard for keyboard quality.
        
               | deno wrote:
               | Most people and companies just use the keyboard that
               | shipped with the computer. I don't think noise is as much
               | of an issue as people make it out be.
               | 
               | Marketing made up this story about linear switches being
               | for gamers. So now every mechanical keyboard needs to
               | make unnecessary noise and offer extra resistance for
               | harder bottom out or you're not a serious typist.
               | 
               | But that's not inherent to the keyboard. Linear switches
               | are not any louder than cheapo office high-profile
               | membrane.
        
             | palata wrote:
             | Yeah I think that dvorak is a good example, too.
             | 
             | I don't get the mechanical keyboard one, though. I am fine
             | with any keyboard, I just like my mechanical keyboard at
             | home. Just like I am fine with any chair, but ideally I
             | would have a chair I like at home.
             | 
             | 120fps I have no experience with, but I would imagine it's
             | closer to video quality. Once you're used to watching
             | everything in 4K, probably it feels frustrating to watch a
             | 1080p video. But when 4K did not exist, it was not a need.
             | I actively try to not get used to 4K because I don't want
             | to "create the need" for it :-).
        
             | bastardoperator wrote:
             | Looks like the Perl of Git too. Those commands are wild
             | compared to vanilla git.
        
           | buu700 wrote:
           | I don't know about jujutsu, but I've actually found that Nix
           | removes a lot of complexity. It's essentially just npm for
           | tooling.
           | 
           | Managing a flake.nix can be a bit more complex than a
           | package.json in practice, due to the flexibility of the
           | format and some quirks around Nix's default caching behavior,
           | but working with it is a breath of fresh air compared relying
           | on globally installed tools. Having said that, you might want
           | to check out Devbox. I haven't used it myself, but found it
           | recently and thought it looked like a nice abstraction over
           | raw Nix.
        
         | faangguyindia wrote:
         | I can't remember all of this, does anyone know of any LLM model
         | trained on CLI which can be run locally?
        
           | lamasery wrote:
           | If you copy those commands into a file and use that file to
           | prompt the "sh" LLM.
        
             | stingraycharles wrote:
             | That works until you need a small variation of any of these
             | commands and you're lost.
        
           | esafak wrote:
           | Not a model, but a product: warp.dev
        
           | fainpul wrote:
           | Try https://cheat.sh/
        
         | gib444 wrote:
         | Hah someone really looked at jq (?) and thought: "yes, more of
         | this everywhere". I feel jq is like marmite (edit: aka
         | vegemite, i.e. "you either love it or you hate it")
        
           | maleldil wrote:
           | It's really not that bad, although the jq comparison might be
           | apt. You have such primitives you need to understand, and
           | then everything just fits together nicely. I find this much
           | easier to write and understand than git's cryptic format
           | strings.
           | 
           | Disclaimer: I love jq too :)
        
           | plandis wrote:
           | It doesn't seem any more egregious than something like:
           | 
           | `git log --color --graph --pretty=format:'%Cred%h%Creset
           | -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold
           | blue)<%an>%Creset' --abbrev-commit --`
           | 
           | Which is something I see a lot of people alias in Git for
           | viewing logs.
        
         | stingraycharles wrote:
         | I don't understand how people can remember all these custom
         | scripting languages. I can't even remember most git flags, I'm
         | ecstatic when I remember how to iterate over arrays in "jq", I
         | can't fathom how people remember these types of syntaxes.
        
           | mgfist wrote:
           | Same, but now with AI I don't have to remember that anymore
        
             | awesome_dude wrote:
             | For now - the law of enshittification means that the
             | free/cheap access to AI will be curtailed soon enough.
        
               | mgfist wrote:
               | Pretty much any OS locally runnable LLM can generate this
               | stuff.
        
           | Cthulhu_ wrote:
           | I don't, I will google things and fiddle, then put it in a
           | git alias (with a comment on what it does and / or where I
           | got it from) and push it to my private dotfiles repo, taking
           | it with me between computers and projects.
        
           | crispyambulance wrote:
           | I am convinced that the vast majority of professionals simply
           | don't bother to remember and, ESPECIALLY WITH GIT, just look
           | stuff up every single time the workflow deviates from their
           | daily usage.
           | 
           | At this point perhaps a million person-years have been
           | sacrificed to the semantically incoherent shit UX of git. I
           | have loathed git from the beginning but there's effectively
           | no other choice.
           | 
           | That said, the OP's commands are useful, I am copying them
           | (because obviously I won't ever memorize them).
        
             | weedhopper wrote:
             | I've recently been looking into some tools that provide
             | quick or painless help like pop up snippets with
             | descriptions and cheat sheets, got any recommendations?
        
               | rusted_gear wrote:
               | I've found tldr to be useful
               | 
               | https://github.com/tldr-pages/tldr
        
               | arcanemachiner wrote:
               | Navi is good for generating personal cheatsheets:
               | 
               | https://github.com/denisidoro/navi
               | 
               | But for Git, I can't recommend lazygit enough. It's an
               | incredible piece of software:
               | 
               | https://github.com/jesseduffield/lazygit
        
               | alwillis wrote:
               | Cheaters: https://brettterpstra.com/projects/cheaters
        
             | freedomben wrote:
             | > _I am convinced that the vast majority of professionals
             | simply don 't bother to remember and, ESPECIALLY WITH GIT,
             | just look stuff up every single time the workflow deviates
             | from their daily usage._
             | 
             | I wrote a cheat sheet in my notes of common commands, until
             | they stuck in my head and I haven't needed it now for a
             | decade or more. I also lean heavily on aliases and "self-
             | documenting" things in my .bashrc file. Curious how others
             | handle it. A search every time I need to do something would
             | be too much friction for me to stand.
        
               | dheera wrote:
               | I just use Claude Code as a terminal for git these days.
               | It writes up better commit messages than I would write
               | anyway. No more "git commit -m fix"
        
               | freedomben wrote:
               | indeed, I held off for a while but finally caved because
               | I got sick of seeing commits with `git commit -m .`
               | littered in there. These are personal projects so I'm the
               | only one dev-ing on them, but still so nice to have
               | commit messages.
        
               | selcuka wrote:
               | That could work if Claude Code made the code changes, but
               | if you made them and only asked Claude to commit them,
               | how does it know "why" you made those changes? Does it
               | have access to your bug tracking system, for example?
        
               | awesome_dude wrote:
               | If Claude was used in the creation of the change, there's
               | usually some dialogue for Claude to use.
               | 
               | FWIW i use Claude to help with code changes, then give
               | the diff to Gemini to review/ create meaningful commit
               | messages
        
               | bluGill wrote:
               | I refuse to have alises and other custom commands. Either
               | it is useful for everyone and so I make a change to the
               | upstream project (I have never done this), or it won't
               | exist next time I change my system so there is no point.
               | I do have some custom tools that I am working on that
               | haven't been released yet, but the long term goal is
               | either delete them or release them to more people who
               | will use them so I know it will be there next time I use
               | a different system.
        
               | irishcoffee wrote:
               | > I refuse to have alises and other custom commands.
               | 
               | I am the same way, and have caught much flack for it over
               | the years.
               | 
               | But when I sit down at a foreign system (foreign in the
               | sense that I haven't used it before) because something is
               | broken and my help was requested, I don't have any need
               | to lean on aliases.
               | 
               | I worked with someone once that had a very impressive
               | bashrc, and it was very effective for them... on their
               | workstation. Plop them in front of a production system,
               | they can't even remember how to remount / rw because
               | they've been using an alias for so long.
               | 
               | This is also why I learned vi, having started with emacs
               | 30 years ago initially, as it was first taught to me. I
               | know it'll be there, and I know how to use it.
        
               | tcoff91 wrote:
               | You don't need aliases when you have fzf fuzzy history
               | search with ctrl-r
        
             | alwillis wrote:
             | > At this point perhaps a million person-years have been
             | sacrificed to the semantically incoherent shit UX of git. I
             | have loathed git from the beginning but there's effectively
             | no other choice.
             | 
             | Yes! We mostly wouldn't tolerate the complexity and the
             | terrible UX of a tool we use everyday--but there's enough
             | Stockholm Syndrome out there where most of us are willing
             | to tolerate it.
        
               | TeMPOraL wrote:
               | Unless you're aware that such powerful commands are
               | something you need once in a blue moon, and then you're
               | grateful that the tool is flexible enough to allow them
               | in the first place.
               | 
               | Git may be sharp and unwieldy, but it's also one of the
               | decreasing amount of _tools_ we still use - the trend of
               | turning tools into toys consumed the regular user market
               | and is eating into tech software as well.
        
               | crispyambulance wrote:
               | Tools, done right, are a joy to use and allow you to be
               | expressive and precise while also saving you labor. Good
               | tools promote mastery and creative inquiry.
               | 
               | Git is NOT that.
               | 
               | Git is something you use to get stuff done, until it
               | becomes an irritating obstacle course of incidental
               | complexity.
        
               | irishcoffee wrote:
               | Hg is a joy to use compared to git. Sure wish hg had won.
        
               | skydhash wrote:
               | Why should there be tolerance? You look it up once, then
               | write a script or an alias if it's part of your workflow.
               | Or made a note if it's worth that. I use magit and I get
               | quick action and contextual help at every step of my
               | interaction with git.
        
             | dec0dedab0de wrote:
             | I just use my ide integrations for git. I absolutely love
             | the way pycharm/jetbrains does it, and I'm starting to be
             | ok with how vscode does. Remembering git commands besides
             | the basics is just pointless. If I need to do something
             | that the gui doesn't handle, I'll look it up and put it in
             | a script.
        
             | awesome_dude wrote:
             | The relevant XKCD comic https://xkcd.com/1597/
             | 
             | FWIW I too was once a "memorised a few commands and that
             | was it" type of dev, then I read 3 chapters of the Git book
             | https://git-scm.com/book/en/v2 (well really two, the first
             | chapter was a "these are things you already know") and wow
             | did my life with git change.
        
             | ngruhn wrote:
             | I don't even think git cli UX is that bad. Didn't git
             | pioneer this sub-command style? Much better than like e.g.
             | ffmpeg. Sure some aspects are confusing. I still don't
             | understand why `checkout` is both for changing branches and
             | clearing uncommitted changes. But overall I think the tool
             | is amazing. I've not observed a bug in git once.
        
               | jcynix wrote:
               | > Didn't git pioneer this sub-command style?
               | 
               | No, various other tools used it before git, e.g. openssl.
        
             | kelvinjps wrote:
             | That's why I really like lazygit, I don't need to remember
             | much because all the keymaps are shown in the UI. I like
             | those kinds of Ui like whichkeys in neovim, or helix, or
             | Doom Emacs.
        
             | neonstatic wrote:
             | I think this is where LLMs shine. I experience the same
             | difficulty with a lot of command line tools, .e.g find is a
             | mystery to me after all these years. Whatever the syntax
             | is, it just doesn't stick in my memory. Since recently I
             | just tell the model what search I want and it gives me the
             | command.
        
           | dewey wrote:
           | You research it once, use it and then remember that it has
           | "ancestor" in the command somewhere and then use ctrl + R to
           | dig up something from your shell history.
        
           | robrain wrote:
           | If I look something up twice, I record it in Obsidian. If I
           | need it more than a couple of times, I'll probably make an
           | alias, a script or a mask [1] file. Autocomplete and
           | autosuggest are essential to my workflow. And good history
           | search.
           | 
           | [1] https://github.com/jacobdeichert/mask
        
           | TheRealPomax wrote:
           | If you don't have to codedive new projects all the time,
           | there's zero reason to memorize these. If your job is to look
           | at new codebases all the time, you probably learn to remember
           | these commands pretty quickly.
        
           | SoftTalker wrote:
           | Yeah especially with git. All I know is pull, add, commit,
           | push. Everything else I have to look up.
        
           | usrbinbash wrote:
           | > I don't understand how people can remember all these custom
           | scripting languages.
           | 
           | We can't.
           | 
           | Why do you think the `man` command exists?
        
           | drob518 wrote:
           | Nobody does. One person figures it out, then writes a blog
           | post, and we all Google for it. Even git's man pages are long
           | and sometimes cryptic.
        
           | Fokamul wrote:
           | You add them into your GIT config file as shortcuts?
           | 
           | If you have multiple machines (/must have), just apply your
           | user config to current machine?
        
           | dzaima wrote:
           | jj's template and revset languages are very simple
           | syntactically, so once you're comfortable with the few things
           | you do use often it's just a question of learning about the
           | other existing functions (even if only enough to know to look
           | them up), which slot right in and compose well with
           | everything else you know (unlike flags which typically have
           | each their own system).
           | 
           | Or, perhaps better yet, defining your own functions/helpers
           | as you go for things you might care about, which, by virtue
           | of having been named you, are much easier to remember (and
           | still compose nicely).
        
           | limaoscarjuliet wrote:
           | Some things are idioms that one repeats so often they just
           | stick, e.g. I use "grep.... | cut -c x-y | sort | uniq -c |
           | sort -nr" to quickly grep frequency of some events from a log
           | file.
           | 
           | Don't feel bad - no one remembers them all, we just remember
           | a few idioms we use...
        
           | NoSalt wrote:
           | So, how does one iterate over an array in jq? Asking for a
           | friend.
        
           | gspr wrote:
           | You and me both. Git is just so prevalent and fundamental to
           | so much these days that I forced myself to use only a cheat
           | sheet lying on my desk until I could comfortably use a
           | reasonably productive subset by memory. Little did I know
           | that that would make my colleagues think I'm some sort of git
           | sage.
           | 
           | But jq I use maybe once a week, and it just won't stick. Same
           | for any git features beyond basic wrangling of the history
           | tree (but, on the flip side, that basic wrangling has
           | eliminated 99% of the times I have to look things up).
        
           | TeMPOraL wrote:
           | People naturally remember what they use frequently. For
           | things they use infrequently, they search on-line and/or
           | _read the friendly manual_.
           | 
           | And yes, I'm also ecstatic when I manage to iterate over
           | anything in `jq` without giving up and reaching for online
           | reference. For `git`, functionality I use divides neatly into
           | "things I do at least every week or two" and "things that
           | make me reach for the git book every single time".
           | 
           | I mean, that was true until ~year or so. Now, I just have an
           | LLM on speed dial. `howto do xyz in $tool`, `wtf is git
           | --blah`, `oneliner for frobbing the widget`, etc.
        
         | socalgal2 wrote:
         | a project isn't dying because of no commits. Rather it's stable
         | 
         | I often feel I need to setup bots to make superfluous commits
         | just to make it look like my useful and stable repos are
         | "active"
         | 
         | One example (not mine) a a qr-code generator library. Hasn't
         | been updated in 10 years. It's perfect as is. It just provides
         | the size and the bits. You convert those bits to any
         | representation you want. It has no need to be updated
        
           | wredcoll wrote:
           | It's rare, I think, for a project to have such a well defined
           | and singular purpose that has not changed in 10 years nor
           | have any bugs been discovered or its dependencies changed
           | underneath it.
           | 
           | It's not impossible, of course, but if I saw even a qr
           | library that hadn't changed in 10 years I would worry that it
           | wouldn't build on current systems (due to dependencies) and
           | that nobody was actually using it (due to lag of bug
           | reports).
        
             | latexr wrote:
             | I have several of those projects. I avoid dependencies as
             | much as possible, striving to only use things which I know
             | ship with my target OS. I code for a level of correctness
             | and longevity. That benefits everyone, including myself.
             | 
             | A QR (or barcode) library is exactly the type of thing I'd
             | assume would still work fine, since there's nothing new to
             | do, the parsing rules don't change, it's a static, known,
             | solved problem.
        
               | robinsonb5 wrote:
               | > A QR (or barcode) library is exactly the type of thing
               | I'd assume would still work fine, since there's nothing
               | new to do, the parsing rules don't change, it's a static,
               | known, solved problem.
               | 
               | I agree with you - and yet the barcode library I used
               | recently for a variable-data-printing project was last
               | updated 13 hours ago, despite having been around since
               | 2008!
        
             | xp84 wrote:
             | Well said. Even an awesome library with no bugs that has no
             | external dependencies still depends on the stdlib. For a
             | while, before we were using containers, we even had the
             | issue on Mac dev machines especially, where a half dozen
             | Rubygems would crash while building its C extensions if
             | your Mac OS version wasn't just what the author expected,
             | due to changes in the compiler shipped by Apple. So a MacOS
             | major update might on its own functionally break a gem,
             | even if the gem itself was designed well and you were using
             | the same Ruby version.
        
           | latexr wrote:
           | > a project isn't dying because of no commits. Rather it's
           | stable
           | 
           | Agreed. Assuming there are no open issues and PRs. When I
           | find a project, if the date of the last commit is old, I next
           | look at the issues and PRs. If there are simple-to-deal-with
           | issues (e.g. a short question or spam) and easy-to-merge PRs
           | (e.g. fixing a typo in the README) which have been left
           | lingering for years, it's probably abandoned. Looking at the
           | maintainer's GitHub activity graph should provide more clues.
           | 
           | > I often feel I need to setup bots to make superfluous
           | commits just to make it look like my useful and stable repos
           | are "active"
           | 
           | I have never done it, but a few times thought about making a
           | "maintenance" release to bump the version number and release
           | date, especially since I often use a variant of calendar
           | versioning.
        
           | saila wrote:
           | This might be true for libraries or utilities that have a
           | well-defined scope and no dependencies, but that's not what
           | the article is focused on. When considering a company's main
           | product, it's usually _never_ done and patterns of activity--
           | and especially _changes_ in those patterns--can give you
           | insight into potential issues.
        
           | fishpen0 wrote:
           | In a real company? A private codebase at a minimum should
           | still be getting regular security patching and dependency
           | updates. Always eventually one of those updates requires some
           | level of refactor. If I see a project with no commits, I run
           | away.
        
         | newsoftheday wrote:
         | I don't want to program git, I want to get stuff done so I
         | would reject using that tool and do what the article author did
         | running tried and true pipeable Linux/UNIX commands. It's also
         | the same reason why I dislike Gradle and use Maven, I don't
         | want to program my build I want to define and run my build.
        
           | nine_k wrote:
           | But the git commands in the article is also programming of
           | the same kind, just using more terse, more obscure language.
           | All the shell pipelines are sort, uniq, and grep.
           | 
           | A language that properly maps to the data model, and has
           | readable identifiers is a boon. Git is a database, a database
           | needs a proper query language.
        
         | dcre wrote:
         | Saw all the replies crying over how verbose these are, clicked
         | through to TFA expecting to see simpler commands. Nope, they're
         | basically the same thing, just slightly shorter. I would never
         | memorize either the jj or git versions if I planned to use them
         | regularly; I'd make aliases.
        
           | WolfeReader wrote:
           | This is the only sane reply on this entire comment tree.
           | 
           | To me, the verbosity of both Git and JJ commands to do these
           | things are an indication that neither of these tools are
           | meant to do them.
        
         | cynicalsecurity wrote:
         | Not interested, thank you.
        
         | NamlchakKhandro wrote:
         | Didn't ask for it thanks
        
       | ramon156 wrote:
       | > The 20 most-changed files in the last year. The file at the top
       | is almost always the one people warn me about. "Oh yeah, that
       | file. Everyone's afraid to touch it."
       | 
       | The most changed file is the one people are afraid of touching?
        
         | mememememememo wrote:
         | Yes. Because the fear is butressed with necessity. You have to
         | edit the file, and so does everyone else and that is a recipe
         | for a lot of mess. I can think back over years of files like
         | this. Usually kilolines of impossible to reason about
         | doeverything.
        
         | dewey wrote:
         | I've just tried this, and the most touched files are also the
         | most irrelevant or boring files (auto generated, entry-point of
         | the service etc.) in my tests.
        
           | nulltrace wrote:
           | Yeah same thing happens with lockfiles and CI configs. You
           | end up filtering out half the list before it tells you
           | anything useful.
        
           | pydry wrote:
           | I just tried it too and it basically just flagged a handful
           | of 1500+ line files which probably ought to be broken up
           | eventually but arent causing any serious problems.
        
             | Cthulhu_ wrote:
             | If it's (like in my case) dependency management,
             | localization or config files, breaking them up will likely
             | only cause more issues. Make sure that it's an actual
             | improvement before breaking things up.
        
         | szszrk wrote:
         | Could be also that a frequently edited file had most
         | opportunity to be broken. And it was edited by the most random
         | crowd.
        
         | rbonvall wrote:
         | Just like that place that's so crowded nobody goes there
         | anymore.
        
         | mchaver wrote:
         | Definitely not in my experience. The most changed are the
         | change logs, files with version numbers and readmes. I don't
         | think anyone is afraid of keeping those up to date.
        
         | jbjbjbjb wrote:
         | This command needs a warning. Using this command and drawing
         | too many conclusions from it, especially if you're new, will
         | make you look stupid in front of your team mates.
         | 
         | I ran this on the repo I have open and after I filtered out the
         | non code files it really can only tell me which features we
         | worked on in the last year. It says more about how we decided
         | to split up the features into increments than anything to do
         | with bugs and "churn".
        
           | Pay08 wrote:
           | Good thing that the article contains that warning, then.
        
             | jbjbjbjb wrote:
             | Not really strong enough in a post about what to do in a
             | codebase you're not familiar with. In that situation you're
             | probably new to the team and organisation and likely to get
             | off on the wrong foot with people if you assume their code
             | "hurts".
        
               | hamburglar wrote:
               | The post is "here's what I do", not "here's what you
               | should do and then confront the team about the results."
               | It's just showing you a quick way to get some insights.
               | It's not even guaranteeing it's accurate, just showing
               | you some things you might be able to draw some quick
               | conclusions on.
               | 
               | I'm not sure why HN attracts this need to poke holes in
               | interesting observations to "prove" they aren't actually
               | interesting.
        
               | jbjbjbjb wrote:
               | It's a bit reductive to call it poking holes. The author
               | shared his valuable knowledge and I shared mine.
        
               | hamburglar wrote:
               | You said this analysis "isn't strong enough" for an
               | inadvisable scenario you completely invented.
        
           | Eldt wrote:
           | Better for people to know they're just blindly copying tools
           | and parroting their output as if it's automatically
           | meaningfully. Any warning against that should be built into
           | the individual, for their own sake
        
             | thiisguy wrote:
             | Right? Some of these comments feel "you gave me commands to
             | run and I should be able to turn my brain off to interpret
             | the outputs". These aren't newbie commands so the
             | assumption would be that you kinda know what you're doing
             | at least a little bit. If not, then don't run them...
             | similar to how you should approach all commands/things from
             | the internet
        
           | mayama wrote:
           | These commands are just about what files to start looking at
           | to understand new codebase.
        
           | functional_dev wrote:
           | I found it interesting, that Git itself has built in
           | similarity notion... when it packs objects, it groups files
           | by path+size, runs delta cmpression to find which are close.
           | 
           | Very different from just counting commits -
           | https://vectree.io/c/delta-compression-heuristics-and-
           | packfi...
        
         | KptMarchewa wrote:
         | In my case, it's .github/CODEOWNERS.
         | 
         | Nobody is afraid of changing it.
        
           | mayama wrote:
           | Why does github owners need frequent change? Do members in
           | you team change so often?
        
         | jollyllama wrote:
         | Yeah, the truth is going to be a lot more subtle than this.
        
         | furyofantares wrote:
         | The LLM that wrote the copy is an idiot.
        
           | jamwil wrote:
           | This is such obvious LLM slop.
        
         | berkes wrote:
         | Plotting Churn against Complexity is far more useful than
         | merely churn.
         | 
         | It shows places that are problematic much better. High churn,
         | low complexity: fine. Its recognized and optimizef that this is
         | worked on a lot (e.g. some mapping file, a dsl, business rules
         | etc). Low churn high complexity: fine too. Its a mess, but no-
         | one has to be there. But both? Thats probably where most bugs
         | originate, where PRs block, where test coverage is poor and
         | where everyone knows time is needed to refactor.
         | 
         | In fact, quite often I found that a teams' call "to rewrite the
         | app from scratch" was really about those few high-churn-high-
         | complexity modules, files or classes.
         | 
         | Complexity is a deep topic, but even simple checks like how
         | nested smt is, or how many statements can do.
        
         | zikani_03 wrote:
         | pom.xml and package.json came up on couple of separate projects
         | I ran the commands on. Which makes sense because the versions
         | get bumped rather frequently. I guess context matters, as
         | usual.
        
         | agumonkey wrote:
         | Maybe it's a start to find conflict-prone regions ?
         | 
         | otherwise you're right, it could be a long linear list of
         | appends where people are happy to contribute.
        
       | seba_dos1 wrote:
       | > If the team squashes every PR into a single commit, this output
       | reflects who merged, not who wrote.
       | 
       | Squash-merge workflows are stupid (you lose information without
       | gaining anything in return as it was easily filterable at
       | retrieval anyway) and only useful as a workaround for people not
       | knowing how to use git, but git stores the author and committer
       | names separately, so it doesn't matter who merged, but rather
       | whether the squashed patchset consisted of commits with multiple
       | authors (and even then you could store it with Co-authored-by
       | trailers, but that's harder to use in such oneliners).
        
         | theshrike79 wrote:
         | Can you explain to me (an avid squash-merger) what extra
         | information do you gain by having commits that say "argh, let's
         | see if this works", "crap, the CI is failing again, small fix
         | to see if it works", "pushing before leaving for vacation" in
         | the main git history?
         | 
         | With a squash merge one PR is one commit, simple, clean and
         | easy to roll back or cherry-pick to another branch.
        
           | seba_dos1 wrote:
           | These commits reaching the reviewer are a sign of either not
           | knowing how to use git or not respecting their time. You
           | clean things up and split into logical chunks when you get
           | ready to push into a shared place.
        
             | zaphirplane wrote:
             | What are examples of better ones. I don't get the let me
             | show the world my work and I'm not a fan of large PR
        
               | duskdozer wrote:
               | if you mean better messages, it's not really that. those
               | junk messages _should_ be rewritten and if the commits
               | don 't stand alone, merged together with rebase. it's the
               | "logical chunks" the parent mentioned.
               | 
               | it's hard to say fully, but unless a changeset is quite
               | small or otherwise is basically 0% or 100%, there are
               | usually smaller steps.
               | 
               | like kind of contrived but say you have one function that
               | uses a helper. if there's a bug in the function, and it
               | turns out to fix that it makes a lot more sense to change
               | the return type of the helper, you would make commit 1 to
               | change the return type, then commit 2 fix the bug. would
               | these be separate PRs? probably not to me but I guess it
               | depends on your project workflow. keeping them in
               | separate commits even if they're small lets you bisect
               | more easily later on in case there was some unforseen or
               | untested problem that was introduced, leading you to
               | smaller chunks of code to check for the cause.
        
               | orsorna wrote:
               | If the code base is idempotent, I don't think showing
               | commit history is helpful. It also makes rebases more
               | complex than needed down the line. Thus I'd rather squash
               | on merge.
               | 
               | I've never considered how an engineer approaches a
               | problem. As long as I can understand the fundamental
               | change and it passes preflights/CI I don't care if it was
               | scryed from a crystal ball.
               | 
               | This does mean it is on the onus of the engineer to
               | explain their change in natural language. In their own
               | words of course.
        
               | seba_dos1 wrote:
               | Commits don't show "how an engineer approaches a
               | problem". Commits are the unit of change that are
               | supposed to go into the final repository, purposefully
               | prepared by the engineer and presented for review. The
               | only thing you do by squashing on merge is to
               | artificially limit the review unit to a single commit to
               | optimize the workflow towards people who don't know how
               | to use git. Personally I don't think it's a good thing to
               | optimize for.
        
               | orsorna wrote:
               | Preserving commit history pre-merge only seems useful if
               | I had to revert or rebase onto an interstitial commit.
               | This is at odds with treating PRs as atomic changes to
               | the code base.
               | 
               | I might have not stated my position correctly. When I
               | mean "squash on merge", I mean the commit history is
               | fully present in the PR for full scrutiny. Sometimes
               | commits may introduce multiple changes and I can view
               | commit ranges for each set of changes. But it takes the
               | _summation_ of the commits to illustrate the change the
               | engineer is proposing. The _summation_ is an atomic
               | change, thus scrutinizing terms post-merge is
               | meaningless. Squashing preserves the summation but rids
               | of the terms.
               | 
               | Versioned releases on main are tagged by these
               | summations, not their component parts.
        
               | OkayPhysicist wrote:
               | If you don't care about how the problem was solved, why
               | are you reviewing it at all?
        
             | yokoprime wrote:
             | Haha, good luck working with a team with more than 2
             | people. A good reviewer looks at the end-state and does not
             | care about individual commits. If im curious about a
             | specific change i just look at the blame.
        
               | hhjinks wrote:
               | You review code not to verify the actual output of the
               | code, but the code itself. For bugs, for maintainability.
               | Commit hygiene is part of that.
        
               | seba_dos1 wrote:
               | I have no troubles working on big FLOSS projects where
               | reviews usually happen at the commit level :)
        
               | theshrike79 wrote:
               | So if a PR consists of 20 commits, they review every
               | single commit linearly without looking at the end result
               | first?
        
               | seba_dos1 wrote:
               | Yes, and in some projects 20 commits is not even a big
               | PR, more like "regular sized". The LKML's first page is
               | now full of PRs with around 20 commits, here's a random
               | one as an example: https://lore.kernel.org/netdev/2026040
               | 8121252.2249051-1-dhow...
               | 
               | And here's a slightly smaller one which isn't about
               | "miscellaneous fixes": https://lore.kernel.org/netdev/202
               | 60408122027.80303-1-xuanzh...
               | 
               | Some of these commits even get reviewed by different
               | maintainers before being merged, which is common when a
               | patchset touches several subsystems at once.
        
               | tasuki wrote:
               | > A good reviewer looks at the end-state and does not
               | care about individual commits.
               | 
               | Then I must be a bad reviewer. In a past job, I had a
               | colleague who meticulously crafted his commits - his PRs
               | were a joy to review because I could go commit by commit
               | in logical chunks, rather than wading through a single 3k
               | line diff. I tried to do the same for him and hope I
               | succeeded.
        
               | theshrike79 wrote:
               | And then someone comments on a thing, they change it and
               | force-push another "clean" history on top and all of your
               | work is wasted because the PR is now completely different
               | =)
        
               | KptMarchewa wrote:
               | Split the PR rather than force me to wade through your
               | commit history. Use graphite or something else that
               | allows you to stack PRs.
        
               | jlokier wrote:
               | Why is it "wade through" if there are 10 clearly distinct
               | but dependent commits, but comfortable if it's 10 stacked
               | PRs instead? They are basically the same thing, presented
               | ever so slightly differently.
               | 
               | I think in most teams I've worked with, the majority of
               | developers (> 85%) barely undestand what Git is doing or
               | what things mean inside GitHub, have never seen commit
               | history as a graph, have never run something like "git
               | log --oneline --graph --decorate" or "--format", and have
               | never heard of "git range-diff" which is very useful for
               | following commit/PR/unit changes.
               | 
               | Personally I review using "git" itself, so I see the
               | graph structure either way, and there's little difference
               | between stacked PRs, commit chains in a single PR, or
               | even feature branches, from that point of view. Even
               | force-push branch updatea aren't difficult to review,
               | because of the reflog and "git range-diff". The
               | differences are mainly in what kinds of behaviour the
               | web-based tooling promotes in the rest of the team, which
               | does matter, and depends on the team.
               | 
               | I agree with you if you're using Graphite instead of
               | GitHub. Having a place to give feedback and/or approval
               | on the individual "units" (commits in a PR, or PRs in a
               | stack) is useful, grouping dependent but distinct changes
               | is useful, and diff'd commit evolution within each unit
               | PR in response to back-end-forth review feedback is
               | useful in some collaborative settings. Though, if you
               | know "git range-diff" and reflog, that shows diff'd
               | commit evolution quite well.
               | 
               | In GitHub, people are confused by stacked PRs both
               | conceptually and due to the GitHub UX around them. Most
               | times when I've posted a stacked PR to a GitHub project,
               | other people didn't realise it was stacked, and
               | occasinally someone else has merged the tip of a stack
               | made by me, and been surprised to see all the dependent
               | PRs merged automatically as a side effect. Usually before
               | they get to reviewing those other PRs :-)
               | 
               | People understand commit sequences in a PR, though I've
               | rarely seen people treat the individual commits as units
               | for review when using GitHub, unfortunately. In the Linux
               | kernel world where Git was born, the PR flow is
               | completely different from GitHub: Their system tends to
               | result in feedback on individual commits. It also
               | encourages better quality feedback, with less nitpicking,
               | and better quality commits.
        
               | mgfist wrote:
               | Why are those not just separate PRs? Or if they really
               | needed to be merged at once - they should still be
               | separate PRs but on a feature branch
        
               | seba_dos1 wrote:
               | Why have PRs - groups of commits to pull - then if all
               | you need is a single patch file?
        
               | mgfist wrote:
               | You can, but most of us work in Github and having a PR to
               | dump commits to is very easy and convenient. Then, when
               | you get some feedback on your PR, you can dump more
               | commits and it's very easy for the reviewer to see what
               | has changed since the last time they reviewed it.
               | 
               | I feel like what you're arguing is that you should clean
               | up your commits before anyone else sees them. Fair. But
               | you could also clean it up right before merging to main.
               | It's not that different, except the latter is much less
               | annoying, particularly when going back and forth with
               | people.
               | 
               | I know this is a very github centric workflow, but that's
               | where most engineers work now, and it's nice and easy.
               | This wouldn't work for eg: contributing to linux, but
               | that's not what most of us do.
        
               | awesome_dude wrote:
               | This is where the "Trunk based development" people live -
               | I personally believe that commits should be atomic,
               | because git bisect on smaller meaningful commits is a
               | hang of a lot better than a monster 90 file change commit
        
               | jfengel wrote:
               | Sometimes I have to go back and fix a bug that appeared
               | during another branch. Having the original commits helps
               | me bisect it.
               | 
               | Not often, but given that it costs me nothing to have it
               | all in my tree, I'd rather have it than not.
        
             | croemer wrote:
             | What if the shared place is the place where you run a bunch
             | of CI? Then you push your work early to a branch to see the
             | results, fix them etc.
        
               | seba_dos1 wrote:
               | You can do whatever you want with stuff nobody else looks
               | at. I do too.
               | 
               | I meant "shared place" as an open review request or a
               | shared branch rather than shared underlying
               | infrastructure. Shared by people's minds.
        
               | mr_mitm wrote:
               | You can always force-push a cleaned up version of your
               | branch when you are ready for review, or start a new one
               | and delete the WIP one.
        
               | theshrike79 wrote:
               | I hate (and fear) force-pushing and "cleaning up" git
               | history as much as other people dislike squash-merging =)
               | 
               | It just feels wrong to force push, destroying stuff that
               | used to be there.
               | 
               | And I don't have the time or energy to bisect through my
               | shitty PR commits and combine them into something clean
               | looking - I can just squash instead.
        
               | seba_dos1 wrote:
               | Nothing is destroyed by a force push. It just overwrites
               | a single pointer, and even keeps its old value in reflog.
               | 
               | Things that aren't referenced by anything anymore will
               | eventually get garbage collected and actually destroyed,
               | but you can just keep a reference somewhere to prevent
               | that from happening if you need. Or even disable garbage
               | collection completely.
               | 
               | Looks like people's fears about git come just from not
               | knowing what it does.
        
               | Noumenon72 wrote:
               | You can't use the remote reflog to revert what you force
               | pushed, can you? But I agree that having your local
               | reflog means you're never totally lost. I still just make
               | a branch before major edits so I can go back.
        
               | croemer wrote:
               | You can, but instead you can also just squash merge in
               | one click. And avoid that people merge there dozens of
               | fixes if you allow anything but squash merge.
        
             | theshrike79 wrote:
             | Why would the reviewer look at the commit messages instead
             | of the code?
             | 
             | 1. Open PR page in whatever tool you're using
             | 
             | 2. Read title + description to see what's up
             | 
             | 3. Swap to diff and start reading through the changes
             | 
             | 4. Comment and/or approve
             | 
             | I've never heard anyone bothering to read the previous
             | commit messages for a second, why would they care?
        
               | seba_dos1 wrote:
               | Because it's a useful abstraction. If you only look at
               | PRs and don't ever care about commits, why are they even
               | being sent to reviewer in the first place? Just send a
               | diff file.
               | 
               | Having atomic commits lets you actually benefit from
               | having them. Suddenly you don't have to perform weird
               | dances with interconnected PRs with dependencies as "PR
               | too big" is not such a problem anymore as long as commits
               | are digestible; you can have things property bisectable;
               | you can preserve shared authorship; you can range-diff
               | and have a better view on what and how changed between
               | review passes, and so on...
               | 
               | The unit of change is commit, and PRs group commits you
               | want someone to pull. If you don't want or need any of
               | that, you're just sending a patch file in a needlessly
               | elaborate way.
        
               | Anon1096 wrote:
               | > If you only look at PRs and don't ever care about
               | commits, why are they even being sent to reviewer in the
               | first place? Just send a diff file.
               | 
               | This is in fact what hg does with amending changesets and
               | yes it works far better. Keep PRs small and atomic and
               | you never need to worry about what happens intra-pr. If
               | you need bigger units of work that's what stacking is
               | for.
        
               | seba_dos1 wrote:
               | Stacking is good for expressing dependencies, but isn't
               | helpful when you need to make several distinct changes
               | that aren't necessarily needed unless you take them all
               | in. What's the value in having a separate PR that
               | introduces a framework that you later use in another PR
               | when you may not actually want to merge it if the latter
               | one doesn't end up being merged as well?
               | 
               | A PR is a group of commits, just utilize that when you
               | need it.
        
               | ipsento606 wrote:
               | >Swap to diff and start reading through the changes
               | 
               | this forces the reviewer to view the entire diff at once,
               | which can greatly increase the cognitive load vs. being
               | able to view diffs of logical units of work
               | 
               | for tiny PRs it may not matter, but for substantial PRs
               | it can matter a lot
        
               | jfultz wrote:
               | In some cases, reviewing PR diffs commit-by-commit (and
               | with the logs as the narration of the diff-by-diff story)
               | is a substantial improvement over reviewing the entire PR
               | diff. Concrete examples...
               | 
               | * A method or function that has code you realize needs to
               | be shared...the code may need to be moved and also
               | modified to accommodate its shared purpose. Separating
               | the migration from any substantive modifications allows
               | you to review the migration commit with the assistance of
               | git's diff.colorMoved feature. It becomes easier to
               | understand what changes are due to the migration, and
               | what changes were added for more effective sharing.
               | 
               | * PRs sometimes contain mechanical work that is easy to
               | review in isolation. Added or removed arguments, function
               | renames, etc. No big deal if it's two or three instances,
               | but if it's dozens or hundreds of instances, it's easier
               | for the humans to review all of those consistent changes
               | together, rather than having them mixed in with other
               | things one has to reason about.
               | 
               | * Sometimes a flow of commits can help follow a difficult
               | chain of reasoning. PR developer claims that condition X
               | can never occur, but the code is complex enough that it's
               | difficult to verify. However, by transforming the code in
               | targeted ways that are possible to reason about, the
               | complexity might be reducible to the point where the
               | claim becomes obvious. One frequent example I see of this
               | is of function/method arguments that are actually
               | unnecessary, but it wasn't obvious until after some code
               | transformations.
        
           | Aachen wrote:
           | If someone uses git commits like the save function of their
           | editor and doesn't write messages intended for reading by
           | anyone else, it makes sense to want to hide them
           | 
           | For other cases, you lose the information about why things
           | are this way. It's too verbose to //comment on every like
           | with how it came to be this way but on (non-rare in total,
           | but rare per line) occasion it's useful to see what the
           | change was that made the line be like this, or even just who
           | to potentially ask for help (when >1 person worked on a
           | feature branch, which I'd say is common)
        
             | seba_dos1 wrote:
             | > If someone uses git commits like the save function of
             | their editor
             | 
             | I use it like that too and yet the reviewers don't get to
             | see these commits. Git has very powerful tools for
             | manipulating the commit graph that many people just don't
             | bother to learn. Imagine if I sent a patchset to the Linux
             | Kernel Mailing List containing such "fix typo", "please
             | work now", "wtf" patches - my shamelessness has its limits!
        
               | Aachen wrote:
               | Seems like a lot of extra effort (save, add, commit, come
               | up with some message even if it's a prayer to work now)
               | only to undo it again later and create a patch or
               | alternate history out of the final version. Why bother
               | with the intermediate commits if you're not planning for
               | it to be part of the history?
        
               | skydhash wrote:
               | If the team is using a PR workflow, the PR is a working
               | place to produce one single commit. The individual
               | commits are just timestamped changes and comments. Think
               | of it as the equivalent of annotated diff in mailing list
               | conversation.
        
               | thi2 wrote:
               | Because I might want to go back to this current messy
               | state but I don't want to commit it like this (hardcoded
               | test strings, debug logs, cutted corners to see if
               | something works, you name it).
               | 
               | I simply commit something like "WIP: testing xy" and if
               | its working and properly implemented i can
               | squash/rebase/edit the commit message and force push it
               | to my feature branch. Using a Git client like Gitkraken
               | makes this incredibly easy, takes seconds.
               | 
               | This way I can leverage version control without
               | committing bogus states to the final PR.
        
               | seba_dos1 wrote:
               | Git is a version control system. It does not care about
               | what it versions.
               | 
               | When I work on something, I commit often and use the
               | commit graph as a undo tool on steroids. I can see what I
               | tried, I can cherry-pick or revert stuff while
               | experimenting, I can leave promising but unfinished stuff
               | to look at later, or I can just commit to have a simple
               | way to send stuff to CI, or a remote backup synced
               | between machines.
               | 
               | Once I'm done working on something, it's time to take a
               | step back, look at the big picture, see how many changes
               | my experiments have actually yielded, separate them,
               | describe and decide whether they go to review together or
               | split in some way, as sometimes working on a single thing
               | requires multiple distinct changes (one PR with multiple
               | commits), but sometimes working in a single session
               | yields fixes for multiple unrelated issues (several PRs).
               | Only then it gets presented to the reviewer.
               | 
               | It just happens that I can do both these distinct jobs
               | with a single tool.
        
               | bguebert wrote:
               | Sometimes its nice to have a history like that because
               | then maybe you are thinking of trying the thing they
               | tried that wouldn't work and it would save you some time
               | trying it if you can tell from those commits that it
               | didn't work.
        
           | tasuki wrote:
           | You gain the extra information by having reasonable commit
           | messages rather than the ones you mentioned. To fix CI you
           | force push.
           | 
           | Can you explain to me what an avid squash-merger puts into
           | the commit message of the squashed commit composed of commits
           | "argh, let's see if this works", "crap, the CI is failing
           | again, small fix to see if it works", and "pushing before
           | leaving for vacation" ?
        
             | theshrike79 wrote:
             | The squashed commit from the PR -> main will have a clean
             | title + description that says what was added.
             | 
             | Usually pretty close to what the PR title + description are
             | actually, just without the videos and screenshots.
             | 
             | Example:
             | 
             | feat(ui): Add support for tagging users
             | 
             | * Users can be tagged via the user page * User tags visible
             | in search results (configurable)
             | 
             | etc..
             | 
             | I don't need to spend extra time cleaning up my git commits
             | and force-pushing on the PR branch, losing context for code
             | reviews etc. Nor does anyone have to see my shitty angry
             | commits when I tried to figure out why Playwright tests ran
             | on my machine and failed in the CI for 10 commits.
        
           | thi2 wrote:
           | Why are those commits ending in the PR? Just unprofessional
           | to work like that.
        
           | joshstrange wrote:
           | > "argh, let's see if this works", "crap, the CI is failing
           | again, small fix to see if it works", "pushing before leaving
           | for vacation"
           | 
           | These are all bad commits IMHO. Aside from the CI one, I
           | understand that message. I have commits like that on personal
           | projects but for professional projects I'd be frustrated if
           | people were committing messages like that.
           | 
           | Personally I'm a "one commit" type of guy, I don't like
           | committing things in a broken state even on a side branch
           | unless I have to (to share the code or test a CI).
           | Occasionally I will make multiple commits at the very end to
           | make review easier or once I have everything working but I
           | want to try something different but I have a bunch of options
           | of saving code that don't involving committing:
           | 
           | - Stash
           | 
           | - Shevle (IDEA)
           | 
           | - Backblaze
           | 
           | - Time Machine
           | 
           | - Local History (IDEA)
           | 
           | The idea of committing WIP before leaving for a vacation just
           | feels so wrong to me.
           | 
           | I once worked for someone who wanted developers to commit
           | code before the end of every day as a safety measure. His
           | reasoning was in case the developer's computer died or
           | similar. I found that silly at the time and still do now.
           | That's what backups are for, I dislike when people use git as
           | a backup like that in a professional setting.
        
           | psalaun wrote:
           | git bisect gets more useful because it will pin a smaller set
           | of changes
        
           | BeetleB wrote:
           | Trivial and not too silly example:
           | 
           | Part of new feature you had working in an intermediate
           | commit, but broke somewhere along the way and is not working
           | in your last commit when you squashed.
           | 
           | If you catch it early enough, I suppose it's in your reflog,
           | but otherwise you're screwed.
           | 
           | It sounds like a silly example, but I bet most developers
           | have run into this at _some_ point.
           | 
           | With mercurial/jujutsu, you get the best of both worlds: The
           | "argh, let's see if this works" commits are what I call
           | "microcommits", and the squashed versions are the real/public
           | commits. With jujutsu, you get both. Your log shows only the
           | "real" commits (equivalent of squashing all the commits
           | between that and the prior "real" commit). But if you want to
           | drill down into the microcommits, the information is always
           | there.
           | 
           | Let's acknowledge the reality. Many people use git not just
           | for version control, but for backup ("Let me commit this so I
           | don't lose it"). Let's ensure the VC tool supports both and
           | doesn't force you to pick one over the other.
        
         | filcuk wrote:
         | Having the tree easy to filter doesn't matter if it returns
         | hundreds of commits you have to sift through for no reason.
        
           | seba_dos1 wrote:
           | Having the commit graph easy to filter means exactly that you
           | don't have to sift through hundreds of commits for no reason.
           | What else did you think it would mean?
        
         | arnorhs wrote:
         | The author is talking about the case where you have coherent
         | commits, probably from multiple PRs/merges, that get merged
         | into a main branch as a single commit.
         | 
         | Yeah, I can imagine it being annoying that sqashing in that
         | case wipes the author attribution, when not everybody is doing
         | PRs against the main branch.
         | 
         | However, calling all squash-merge workflows "stupid" without
         | any nuance.. well that's "stupid" :)
        
           | seba_dos1 wrote:
           | I don't think there's much nuance in the "I don't know
           | --first-parent exists" workflow. Yes, you may sometimes
           | squash-merge a contribution coming from someone who can't use
           | git well when you realize that it will just be simpler for
           | everyone to do that than to demand them to clean their stuff
           | up, but that's pretty much the only time you actually have a
           | good reason to do that.
        
             | skydhash wrote:
             | Do people actually share PR as in different people
             | contributing to the same branch?
             | 
             | Also I can understand not squashing if the contribution
             | comes from outside the organization. But in that case, I
             | would expect a cleaned up history. But if every
             | contribution is from members of the team, who can merge
             | their own PR, squash merge is an easy way to get a clean
             | history. Especially when most PR should be a single commit.
        
               | l72 wrote:
               | We do. If we are building out a feature, none of its code
               | is merged into main until it is complete (if this is a
               | big feature, we milestone into mergeable and releasable
               | units).
               | 
               | The feature is represented by a Story in Jira and a
               | feature branch for that story. Subtasks in jira are
               | created and multiple developers can pick up the different
               | subtasks. There is a personal branch per subtasks, and
               | PRs are put up against the feature branch. Those subtasks
               | are code reviewed, tested, and merged into the feature
               | branch.
               | 
               | In the end, it is the feature branch that is merged (as a
               | single merge commit and complete unit) into main, and may
               | well have had contributions from multiple people.
        
               | skydhash wrote:
               | I get your POV, but I've always considered that long-
               | lived branches in the canonical repo (the one in the
               | forge) other than the main one should be directly related
               | to deployable artifacts. Anything else should be short-
               | lived.
               | 
               | There can be experiment on the side that warrants your
               | approach, but the amounts of merge going back and forth
               | would make this hard to investigate (especially when
               | blaming) I would prefer to have one single commit with a
               | message that describe every contribution.
        
               | juped wrote:
               | Somewhat Linux-like. You could probably improve it purely
               | from a git perspective by letting subtask dependencies be
               | many-to-many (the commit graph _is_ a dependency graph),
               | but what you have is probably best for your whole Jira
               | workflow.
        
             | l72 wrote:
             | I really, really wish git changed two defaults:
             | * git merge ALWAYS does a merge and git pull ALWAYS does a
             | fast forward.       * git log --first-parent is the
             | default. Have a git log --deep if you want to go down into
             | branches.
             | 
             | If you use a workflow that always merges a PR with a merge
             | commit, then git log --first-parent gives you a very nice
             | linear history. I feel like if this was the default, so
             | many arguments about squashing or rebasing workflows
             | wouldn't be necessary to get our "linear history", everyone
             | would just be doing merges and be happy with it. You get a
             | clean top level history and you can dig down into the
             | individual commits in a merge if you are bisecting for a
             | bug.
        
               | juped wrote:
               | I agree.
               | 
               | I set merge.ff = false and alias ff to merge --ff-only. I
               | don't use pull but I do have pull.ff = only set, just in
               | case someday I do.
               | 
               | The graph log and the first-parent log serve different
               | purposes and possibly shouldn't be the same command
               | conceptually; this varies by user preference but the
               | first-parent log is more of a "good default", generally.
               | Merges do say "Merge" at the start, after all.
               | 
               | This is what I advise people to do in consulting
               | engagements, too, it's not one of my personal quirks.
        
           | duskdozer wrote:
           | I think the point is that if you have to squash, the PR-maker
           | was already gitting wrong. They should have "squashed" on
           | their end to one or more smaller, logically coherent commits,
           | and then submitted that result.
        
             | skydhash wrote:
             | It's not "having to squash". The intent was already for a
             | PR to be a single commit. I could squash it on my end and
             | merge by rebasing, but any alteration would then need to be
             | force-pushed. So I don't bother. I squash-merge when it's
             | ready and delete the branch.
        
         | mcpherrinm wrote:
         | Squash merge is the only reasonable way to use GitHub:
         | 
         | If you update a PR with review feedback, you shouldn't change
         | existing commits because GitHub's tools for showing you what
         | has changed since your last review assume you are pushing new
         | commits.
         | 
         | But then you don't want those multiple commits addressing PR
         | feedback to merge as they're noise.
         | 
         | So sure, there's workflows with Git that doesn't need
         | squashing. But they're incompatible with GitHub, which is at
         | least where I keep my code today.
         | 
         | Is it perfect? No. But neither is git, and I live in the world
         | I am given.
        
           | mgfist wrote:
           | Yes, I think people who are anti squash merge are those who
           | don't work in Github and use a patch based system or
           | something different. If you're sending a patch for linux, yes
           | it makes sense that you want to send one complete, well
           | described patch. But Github's tooling is based around the
           | squash merge. It works well and I don't know anyone in real
           | life who has issues with it.
           | 
           | And to counter some specific points:
           | 
           | * In a github PR, you write the main commit msg and
           | description once per PR, then you tack on as many commits as
           | you want, and everyone knows they're all just pieces of work
           | towards the main goal of the eventually squashed commit
           | 
           | * Forcing a clean up every time you make a new commit is not
           | only annoying extra work, but it also overwrites history that
           | might be important for the review of that PR (but not
           | important for what ends up in main branch).
           | 
           | * When follow up is requested, you can just tack on new
           | commits, and reviewers can easily see what new code was added
           | since their last review. If you had to force overwrite your
           | whole commit chain for the PR, this becomes very annoying and
           | not useful to reviewers.
           | 
           | * In the end, squash merge means you clean up things once,
           | instead of potentially many times
        
             | goosejuice wrote:
             | Forcing a single commit per PR is the issue imo. It's a
             | lazy solution. Rebase locally into sensible commits that
             | work independently and push with lease. Reviewers can reset
             | to remote if needed.
        
           | l72 wrote:
           | If your goal here is to have linear history, then just use a
           | merge commit when merging the PR to main and always use `git
           | log --first-parent`. That will only show commits directly on
           | main, and gives you a clean, linear history.
           | 
           | If you want to dig down into the subcommits from a merge,
           | then you still can. This is useful if you are going back and
           | bisecting to find a bug, as those individual commits may hold
           | value.
           | 
           | You can also cherry pick or rollback the single merge commit,
           | as it holds everything under it as a single unit.
           | 
           | This avoids changing history, and importantly, allows stacked
           | PRs to exist cleanly.
        
             | mcpherrinm wrote:
             | Git bisect is one of the important reasons IMO to always
             | squash-merge pull requests: Because the unit of review is
             | the pull request.
             | 
             | I think this is all Github's fault, in the end, but I think
             | we need to get Github to change and until then will keep
             | using squash-merges.
        
               | juped wrote:
               | No.
               | 
               | The cases where bisect fails you are, basically, ones
               | where it lands on a merge that does too much - you now
               | have to manually disentangle the side that did too much
               | to find out exactly what interaction caused the
               | regression. But this is on the rarer side because it's
               | rare for an _interaction_ to be what caused the
               | regression, it 's more common that it's a _change_ -
               | which will be in a non-merge commit.
               | 
               | The squash merge workflow means _every single commit_ is
               | a merge that does too much. Bisect can 't find anything
               | useful for you by bisection anymore, so you have to get
               | lucky about how much the merge did, unenriched by any of
               | the history that you deleted.
        
               | olejorgenb wrote:
               | git bisect --first-parent
        
         | lamasery wrote:
         | Squash-merge is entirely fine for small PRs. Cleaning up the
         | commits in advance (probably to just squash them to one or two
         | anyway) is extra work, and anything that discourages people
         | from pushing often (to get the code off their local machine)
         | needs to be well-justified. Just review the (smallish!) total
         | outcome of all the commits and squash after review. A few well-
         | placed messages on the commit, attached to relevant lines, are
         | more helpful and less work than cleaning up the commit history
         | of a smallish PR.
         | 
         | For really large PRs, I'm more inclined to agree with you, but
         | those should probably have _their own_ small-PR-and-squash-
         | merge flow that naturally cleans up their git history, anyway.
         | 
         | I categorically disagree that squash-merge is "stupid" but
         | agree there are many ways to skin this cat.
        
         | LinXitoW wrote:
         | How does not squash merging deal with the fact that branches
         | disappear when merging? What I mean is that the information
         | "this commit happened in the context of this PR or this
         | overarching goal" goes missing. When you squash, you use the
         | one central unit of information management in Git: the commit.
        
         | 6thbit wrote:
         | Calling squash stupid sounds like a case of Dunning-Kruger.
         | 
         | If you've worked on a large team without squashing and without
         | increasing frustration I'd be greatly interested to hear about
         | it.
        
       | traceroute66 wrote:
       | > The 20 most-changed files in the last year. The file at the top
       | is almost always the one people warn me about.
       | 
       | What a weird check and assumption.
       | 
       | I mean, surely most of the "20 most-changed files" will be README
       | and docs, plus language-specific lock-files etc. ?
       | 
       | So if you're not accounting for those in your git/jj syntax
       | you're going to end up with an awful lot of false-positive noise.
        
         | theshrike79 wrote:
         | Why would you touch the README file hundreds of times a year?
         | 
         | You're right about package.json, pnpm-lock etc though, but
         | those are easy to filter out if the project in question uses
         | them.
        
           | traceroute66 wrote:
           | > Why would you touch the README file hundreds of times a
           | year?
           | 
           | You're right, perhaps I should have said CHANGELOG etc.
           | 
           | Although some projects e.g. bump version numbers in README or
           | add extra one-liner examples ....
        
           | raxxorraxor wrote:
           | Some readme files include changelogs. But aside from that I
           | think this can still net some useful information. I like to
           | look at the most recently changed files in a repo as well.
        
         | jbjbjbjb wrote:
         | It's easy enough to filter those out with grep. It still is
         | relatively meaningless. If the team incrementally adds things
         | then it's just going to show what additions were made. It isn't
         | churn at all.
        
         | grepsedawk wrote:
         | Fair point. I skip lockfiles, changelogs, and generated code.
         | The first application file on the list is the one that matters.
         | Should have been explicit about that in the post.
        
       | JetSetIlly wrote:
       | Some nice ideas but the regexes should include word boundaries.
       | For example:
       | 
       | git log -i -E --grep="\b(fix|fixed|fixes|bug|broken)\b" --name-
       | only --format='' | sort | uniq -c | sort -nr | head -20
       | 
       | I have a project with a large package named "debugger". The
       | presence of "bug" within "debugger" causes the original command
       | to go crazy.
        
         | grepsedawk wrote:
         | Good catch, that's better
        
         | nozzlegear wrote:
         | This needs a small tweak to work on macOS, where git uses the
         | POSIX version of grep (which doesn't support `\b`). You need to
         | use the Perl Regexp option by switching -E with -P:
         | 
         | git log -i -P --grep="\b(fix|fixed|fixes|bug|broken)\b" --name-
         | only --format='' | sort | uniq -c | gsort -nr | head -20
        
         | j2kun wrote:
         | Similarly, we have a technical concept called "rollback" that
         | is unrelated to a reverted commit.
        
       | aa-jv wrote:
       | Great tips, added to notes.txt for future use ..
       | 
       | Another one I do, is:                   $alias gss='git for-each-
       | ref --sort=-committerdate'              $gss
       | ce652ca83817e83f6041f7e5cd177f2d023a5489 commit
       | refs/heads/project-feature-development
       | ce652ca83817e83f6041f7e5cd177f2d023a5489 commit
       | refs/remotes/origin/project-feature-development
       | 1ef272ea1d3552b59c3d22478afa9819d90dfb39 commit
       | refs/remotes/origin/feature/feature-removal-from-good-state
       | c30b4c67298a5fa944d0b387119c1e5ddaf551f1 commit
       | refs/remotes/origin/feature/feature-removal
       | eda340eb2c9e75eeb650b5a8850b1879b6b1f704 commit
       | refs/remotes/origin/HEAD
       | eda340eb2c9e75eeb650b5a8850b1879b6b1f704 commit
       | refs/remotes/origin/main
       | 3f874b24fd49c1011e6866c8ec0f259991a24c94 commit
       | refs/heads/project-bugfix-emergency         ...
       | 
       | This way I can see right away which branches are 'ahead' of the
       | pack, what 'the pack' looks like, and what is up and coming for
       | future reference ... in fact I use the 'gss' alias to find out
       | whats going on, regularly, i.e. "git fetch --all && gss" - doing
       | this regularly, and even historically logging it to a file on
       | login, helps see activity in the repo without too much digging. I
       | just watch the hashes.
        
       | mattrighetti wrote:
       | I have a summary alias that kind of does similar things
       | # summary: print a helpful summary of some typical metrics
       | summary = "!f() { \         printf \"Summary of this
       | branch...\n\"; \         printf \"%s\n\" $(git rev-parse
       | --abbrev-ref HEAD); \         printf \"%s first commit
       | timestamp\n\" $(git log --date-order --format=%cI | tail -1); \
       | printf \"%s latest commit timestamp\n\" $(git log -1 --date-order
       | --format=%cI); \         printf \"%d commit count\n\" $(git rev-
       | list --count HEAD); \         printf \"%d date count\n\" $(git
       | log --format=oneline --format=\"%ad\" --date=format:\"%Y-%m-%d\"
       | | awk '{a[$0]=1}END{for(i in a){n++;} print n}'); \
       | printf \"%d tag count\n\" $(git tag | wc -l); \         printf
       | \"%d author count\n\" $(git log --format=oneline --format=\"%aE\"
       | | awk '{a[$0]=1}END{for(i in a){n++;} print n}'); \
       | printf \"%d committer count\n\" $(git log --format=oneline
       | --format=\"%cE\" | awk '{a[$0]=1}END{for(i in a){n++;} print
       | n}'); \         printf \"%d local branch count\n\" $(git branch |
       | grep -v \" -> \" | wc -l); \         printf \"%d remote branch
       | count\n\" $(git branch -r | grep -v \" -> \" | wc -l); \
       | printf \"\nSummary of this directory...\n\"; \         printf
       | \"%s\n\" $(pwd); \         printf \"%d file count via git ls-
       | files\n\" $(git ls-files | wc -l); \         printf \"%d file
       | count via find command\n\" $(find . | wc -l); \         printf
       | \"%d disk usage\n\" $(du -s | awk '{print $1}'); \         printf
       | \"\nMost-active authors, with commit count and %%...\n\"; git
       | log-of-count-and-email | head -7; \         printf \"\nMost-
       | active dates, with commit count and %%...\n\"; git log-of-count-
       | and-day | head -7; \         printf \"\nMost-active files, with
       | churn count\n\"; git churn | head -7; \       }; f"
       | 
       | EDIT: props to https://github.com/GitAlias/gitalias
        
         | duskdozer wrote:
         | Curious - why write it as a function in presumably .gitconfig
         | and not just a git-summary script in your path? Just seems like
         | a lot of extra escapes and quotes and stuff
        
           | mattrighetti wrote:
           | It's a very old config that I copied from someone many years
           | ago, agree that it's a bit hard to parse visually.
        
           | Cthulhu_ wrote:
           | Not the poster, but one theory: so you only need to copy one
           | file. Portability.
        
             | mr_mitm wrote:
             | Looks like the above assumes a POSIX shell, so one could
             | argue a dedicated script would actually be more portable.
        
         | TonyStr wrote:
         | Looks nice. Unfortunately I don't have log-of-count-and-email,
         | log-of-count-and-day or churn
        
           | petey283 wrote:
           | +1 Same.
           | 
           | Edit. https://github.com/mattrighetti/dotfiles/blob/master/.g
           | itcon...
        
         | ape4 wrote:
         | You could make a local `man` page.
        
         | not_kurt_godel wrote:
         | I was going to say, the OP's assertion that "they" are typing
         | all these commands out by hand each time without an alias is
         | just one of many tells that this post is AI slop. Nobody that
         | proficient with shell commands should be typing any of those by
         | hand more than once or twice without aliasing for reuse.
        
       | croemer wrote:
       | Rather than using an LLM to write fluffy paragraphs explaining
       | what each command does and what it tells them, the author should
       | have shown their output (truncated if necessary)
        
         | markus_zhang wrote:
         | I also feel this reads like an AI slop, but at least I learned
         | 5 commands. Not too bad.
        
       | boxed wrote:
       | Just looking at how often a file changes without knowing how big
       | the file is seems a bit silly. Surely it should be changes/line
       | or something?
        
         | grepsedawk wrote:
         | Sure, normalizing by size would be more precise. But this is a
         | quick gut check to know which files to look at first, not a
         | metric.
        
       | alkonaut wrote:
       | Trusting the messages to contain specific keywords seems
       | optimistic. I don't think I used "emergency" or "hotfix" ever.
       | "Revert" is some times automatically created by some tools (E.g.
       | un-merging a PR).
        
         | ziml77 wrote:
         | For the stuff I've worked on, if you want to know about
         | bugfixes and emergency releases, you'd go to Jira where those
         | values are formalized as fields. Someone else in the comments
         | here had a suggestion which just looks for the word "fix" which
         | would definitely capture some bugfix releases, but is more
         | likely to catch fixes that were done during development of a
         | feature.
        
       | niedbalski wrote:
       | Ages ago, google released an algorithm to identify hotspots in
       | code by using commit messages.
       | https://github.com/niedbalski/python-bugspots
        
       | niedbalski wrote:
       | Ages ago google wrote an algorithm to detect hotspots by using
       | commit messages, https://github.com/niedbalski/python-bugspots
        
       | user20251219 wrote:
       | thank you - these are useful
        
       | whstl wrote:
       | _> One caveat: squash-merge workflows compress authorship. If the
       | team squashes every PR into a single commit, this output reflects
       | who merged, not who wrote. Worth asking about the merge strategy
       | before drawing conclusions._
       | 
       | In my experience, when the team doesn't squash, this will reflect
       | the messiest members of the team.
       | 
       | The top committer on the repository I maintain has 8x more
       | commits than the second one. They were fired before I joined and
       | nobody even remembers what they did. Git itself says: not much,
       | just changing the same few files over and over.
       | 
       | Of course if nobody is making a mess in their own commits, this
       | is not an issue. But if they are, squash can be quite more
       | truthful.
        
       | nola-a wrote:
       | For more insights on Git, check out
       | https://github.com/nolasoft/okgit
        
       | fzaninotto wrote:
       | Instead of focusing on the top 20 files, you can map the entire
       | codebase with data taken from git log using ArcheoloGit [1].
       | 
       | [1]: https://github.com/marmelab/ArcheoloGit
        
       | lpribis wrote:
       | I was curious what information I could glean from these for some
       | popular repos. Caveat: I'm primarily an low-level embedded
       | developer so I don't interface with large open source projects at
       | the source level very often (other than occasionally the linux
       | kernel). I chose some projects at random that I use.
       | 
       | *Mainline linux*
       | 
       | Most changed files: pretty much what I expected for 1 and 2...
       | the "cutting edge" of Linux development over other OSes -- bpf
       | and containers. The bpf verifier and AMD GPU driver might get a
       | boost in this list due to sheer LoCs in those files (26K and 14K
       | respectively). An intel equivalent of amdgpu_dm is #21 in the
       | list (drivers/gpu/drm/i915/display/intel_display.c) and nvidia is
       | nowhere to be seen (presumably due to out-of-tree
       | modules/blobs?).                   186 kernel/bpf/verifier.c
       | 174 fs/namespace.c         162
       | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c         161
       | kernel/sched/ext.c         159 fs/f2fs/f2fs.h
       | 
       | Bus factor: obviously none. The top 4                   10399
       | Christoph Hellwig -> I only know his name because of drama last
       | year regarding rust bindings to DMA subsystem          8481 Mauro
       | Carvalho Chehab -> I also know his name from the classic "Mauro,
       | shut the fuck up!" Linus rant          8413 Takashi Iwai ->
       | Listed as maintainer for sound subsystem, I think he manages ALSA
       | 8072 Al Viro -> His name is all over bunch of filesystem code
       | 
       | Buggy files: Intel comes out on top of GPU drivers this time
       | (twice). Along with KVM for x86(64), the main allocator, and
       | BTRFS.                   1477
       | drivers/gpu/drm/i915/intel_display.c         1406 MAINTAINERS
       | 1390 sound/pci/hda/patch_realtek.c         1102
       | drivers/gpu/drm/i915/i915_drv.h          943 arch/x86/kvm/x86.c
       | 928 mm/page_alloc.c          871
       | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c          862
       | drivers/gpu/drm/i915/i915_reg.h          840 fs/btrfs/inode.c
       | 
       | *GCC*
       | 
       | Most changed files: IR autovectorization code, riscv heuristics
       | tables, and C++ template handling (pt.c is "paramaterized
       | types").                   152 gcc/tree-vect-stmts.cc         145
       | gcc/config/riscv/riscv.cc         131 gcc/tree-vect-loop.cc
       | 116 gcc/cp/pt.cc
       | 
       | Buggy files: DWARF debuginfo generation, x86 heuristics tables,
       | RS6000(?!) heuristic tables. I had to look up RS6000, it's an IBM
       | instruction set from the 90s lol. cp-tree.h is an interesting
       | file, it seems be the main C(++) AST datastructures.
       | 1017 gcc/dwarf2out.c         885 gcc/config/i386/i386.c
       | 796 gcc/cp/cp-tree.h         740 gcc/config/rs6000/rs6000.c
       | 720 gcc/cp/pt.c
       | 
       | *xfwm4* Most changed files: the list is dominated by *.po
       | localizations. I filtered these out. Even after this, I
       | discovered there is very little active development in the last
       | few years. If I extend to 4 years ago, I get: 1. src/client.c -
       | Realizing this project is too "small" to glean much from this.
       | client.c is just the core X client management code. Makes sense.
       | 2. src/placement.c - Other core window management code.
       | 
       | This has not told me much other than where most of the
       | functionality of this project lies.
       | 
       | Bus factor: Pretty huge. Not really an issue in this case due to
       | lack of development I guess.                   3298  Olivier
       | Fourdan          530  Anonymous          319  Xfce Bot
       | 121  Jasper Huijsmans
       | 
       | Files with bug commits: Very similar distribution to most changed
       | files. Not enough datapoints in this one to draw any big
       | conclusions.
       | 
       | I think these massive open projects (excl xfwm) are generally
       | pretty consistent code quality across the heavily trodden areas
       | because of the amount of manpower available to refactor the pain
       | points. I've yet to see an example of "god help you if you have
       | to change that file" in e.g. linux, but I have of course seen
       | that situation many times in large proprietary codebases.
        
         | grepsedawk wrote:
         | Big projects tend to self-correct. These commands hit
         | differently on private codebases with 3-10 contributors, where
         | high-churn usually means one person patching the same thing
         | repeatedly.
        
         | croemer wrote:
         | This is better than the post itself. Showing real output from a
         | real repo.
        
       | bsuvc wrote:
       | I love how the author thinks developers write commit messages.
       | 
       | All joking aside, it really is a chronic problem in the corporate
       | world. Most codebases I encounter just have "changed stuff" or
       | "hope this works now".
       | 
       | It's a small minority of developers (myself included) who
       | consider the git commit log to be important enough to spend time
       | writing something meaningful.
       | 
       | AI generated commit messages helps this a lot, if developers
       | would actually use it (I hope they will).
        
         | sigmoid10 wrote:
         | Only two of the five insights are based on commit messages and
         | the author acknowledges that they won't work in projects
         | without message discipline. But the remaining ones will give
         | you valuable insights even into the most lazy project
         | department.
        
         | itmitica wrote:
         | I love how the commentator thinks a developer makes decisions
         | based on commit messages.
         | 
         | Random, subjective, or written in a state of mental exhaustion
         | commit messages.
         | 
         | I also love the switcheroo the author made: git not logs. But
         | hey :)
        
         | 8cvor6j844qw_d6 wrote:
         | > AI generated commit messages
         | 
         | git log --oneline and a sprinkle of your personal sauce on
         | .claude goes a long way :)
        
         | mikepurvis wrote:
         | In codebases where PRs are squashed on merge, the commit
         | messages on the main branch end up being the PR body
         | description text, and that's actually reviewed so tends to be
         | much better I find.
        
           | bob1029 wrote:
           | And in every codebase I've been in charge of, each PR has one
           | or more issue # linked which describe every possible
           | antagonizing detail behind that work.
           | 
           | I understand this isn't inline with traditional git scm, but
           | it's a very powerful workflow if you are OK with some
           | hybridization.
        
             | bikelang wrote:
             | I personally find this to be a substantially better
             | pattern. That squashed commit also becomes the entire
             | changeset - so from a code archeology perspective it
             | becomes much easier to understand what and why. Especially
             | if you have a team culture that values specific PRs that
             | don't include unrelated changes. I also find it thoroughly
             | helpful to be able to see the PR discussions since the link
             | is in the commit message.
        
               | mikepurvis wrote:
               | I agree, much as it's a loss for git as a distributed
               | system (though I think that ship sailed long ago
               | regardless). As far as unrelated changes, I've been
               | finding that another good LLM use-case. Like hey Claude
               | pull this PR <link> and break it up into three new
               | branches that individually incorporate changes A, B, and
               | C, and will cleanly merge in that order.
               | 
               | One minor nuisance that can come up with GitHub in
               | particular when using a short reference like #123 is that
               | that link breaks if the repo is forked or merged into
               | something else. For that reason, I try to give full-url
               | references at least when I'm manually inserting them, and
               | I wish GitHub would do the same. Or perhaps add some
               | hidden metadata to the merge commit saying "hey btw that
               | #123 refers to <https://github.com/fancy-org/omg-
               | project/issues/123>"
        
           | tormeh wrote:
           | I've seen it be the concatenated individual git commit
           | messages way too often. Just a full screen scroll of "my
           | hands are writing letters" and "afkifrj". Still better than
           | if we had those commits individually of course, but dear god.
           | 
           | The gold standard is rebased linear unsquashed history with
           | literary commits, but I'll take merged and squashed PR
           | commits with sensible commit messages without complaint.
        
         | ramijames wrote:
         | This is a team lead/CTO problem. A good leader will be explicit
         | in their expectations that developers write good commit
         | messages. I've certainly had good leaders that expect this.
        
           | PUSH_AX wrote:
           | I think it's a stretch to measure leadership quality on
           | something so minor, a lot of teams find them pretty useless
           | no matter how good they are.
        
             | freedomben wrote:
             | It's a stretch to lay at the CTOs feet, but not the team
             | lead or even Head/VP of Engineering IMHO. It's also easy to
             | "enforce" if you're already doing peer review (which you
             | definitely should be, even if not required for compliance).
        
             | two_tasty wrote:
             | I partially disagree. Technical leadership at the micro/mid
             | level should be able to set and enforce standards like "you
             | must have semi-meaningful or meaningful commit messages."
             | If and only if they set those standards, and the team does
             | not follow them, then we can say that either the leadership
             | is lacking, or there is a structural barrier/disincentive
             | to following the rules. Within that framework, I do think
             | using process-smells like this is valid for judging
             | technical leadership.
             | 
             | To the point of other commenters however, I wouldn't lay
             | something this micro at the foot of the CTO in all but the
             | smallest of organizations.
        
             | munksbeer wrote:
             | I don't agree. These things actually matter. A developer
             | who isn't told otherwise is just going to do whatever they
             | feel like, so if there is nothing or no-one enforcing the
             | standards, then the failure isn't on the individual
             | developer, it is on the team lead. Someone needs to be
             | setting the standards.
             | 
             | In the company I work for, there is a team that has
             | isolated itself to some extent from other teams and works
             | at a furious pace to keep their particular section of the
             | business happy. We're lucky enough that they spun up their
             | own repo to do their work on, so they don't actually impact
             | other teams, but if the quality of the commit messages is
             | anything to go by, I am 100% certain they're going to end
             | up in a huge mess, if they aren't already. The team lead
             | encourages this, and certainly doesn't care about commit
             | messages etc.
             | 
             | Developers who care about other developers tend to write
             | better quality code, because they care what other
             | developers think of them. If you care about other
             | developers, you will most likely write decent quality
             | commit messages too.
             | 
             | I have seen over many years the types of developers who
             | only care about moving their own code into production as
             | fast as possible and getting to the next thing. There is a
             | very high correlation with a mess at the end, which they
             | inevitably won't have to tidy up because they'll be doing
             | the next thing. These types of developers hate owning stuff
             | in production, so they don't do it, so they don't actually
             | care how maintainable their "clever" code is. I am very
             | certain that a number of people reading this will be those
             | types of developers.
        
             | xp84 wrote:
             | Useless? So you never use "git annotate" or your IDE to see
             | who wrote a line of code whose purpose puzzles you, and go
             | to the commit message to see what they were trying to
             | accomplish? This is invaluable to me as long as commit
             | messages are clear.
             | 
             | As a manager, one of the first things I do is make sure
             | that the PR titles (the PR text becomes the commit messages
             | in squash-merging workflows) at minimum begin with a ticket
             | number. Then we can later read both the intention and the
             | commentary on it.
        
               | PUSH_AX wrote:
               | > Useless? So you never use "git annotate" or your IDE to
               | see who wrote a line of code whose purpose puzzles you,
               | and go to the commit message to see what they were trying
               | to accomplish?
               | 
               | Personally no, the code is the "truth". If I need more
               | I'm going to open a dialog with the author, not spend
               | time trying to interpret a 7 word commit message, "good"
               | or otherwise.
        
               | macintux wrote:
               | The code can only convey what is being done (and then, in
               | some cases, only superficially). It can't convey what
               | decisions were made, what alternatives were discarded,
               | what business motivations may have led to that code.
               | 
               | And for old enough code, the author may not be available,
               | or more likely doesn't remember.
        
               | PUSH_AX wrote:
               | Fine, but none of that is in a normal commit message,
               | lets be real...
        
               | mgfist wrote:
               | Which circles back to why it's important for leadership
               | to tackle this
        
               | PUSH_AX wrote:
               | Yes, but not in the form of commit messages, the parent
               | comment described things better suited to jira tickets,
               | documentation etc.
               | 
               | It feels like we're trying really hard to stretch the
               | utility of commit messages here...
        
               | macintux wrote:
               | Mainly I was pushing back on: the code is the "truth"
               | 
               | I don't feel that is an accurate statement for any
               | complex system.
        
               | PUSH_AX wrote:
               | I don't like complex systems, and I work hard not to
               | create them.
        
               | mgfist wrote:
               | Sure but code can't capture everything. Maybe with enough
               | comments I guess, but not code alone. For example, code
               | won't tell you that this feature was timeboxed hence this
               | edgecase was not supported
        
               | hluska wrote:
               | And a commit message would convey that?
        
               | cratermoon wrote:
               | You'll at least need the discipline to include the ticket
               | ID in the message. Links to documentation are ok, but
               | they will likely rot and even if they don't the content
               | may change such that it no longer accurately reflects the
               | commit changes.
        
               | wreath wrote:
               | And what of the original author is not there anymore?
        
               | PUSH_AX wrote:
               | The world will not end. I'll get there.
        
               | agateau wrote:
               | The code is the present truth, the commit messages can
               | inform you about how it got turned into this truth.
               | Interestingly, I recently wrote a short article about
               | this: https://agateau.com/2026/on-commit-messages/
        
               | cratermoon wrote:
               | Your argument on conventional commits is something I've
               | come to agree with. There are even tools that can
               | generate release notes from conventional commits, and
               | they are premised on the same mistake.
        
               | alt_422568 wrote:
               | > you never use "git annotate" or your IDE to see who
               | wrote a line of code whose purpose puzzles you, and go to
               | the commit message to see what they were trying to
               | accomplish? This is invaluable to me as long as commit
               | messages are clear.
               | 
               | You're thinking like someone with a mature understanding
               | of version control. Plenty of developers seem set on
               | going their whole careers using git like beginners.
        
           | ryandrake wrote:
           | Yes, and a culture problem, too. I guess I've been blessed
           | that I've mostly only worked for "grown up" companies, but
           | I've never encountered a workplace where people didn't write
           | useful commit messages. At _least_ one line description of
           | the work done, but often multiple lines of valuable context.
           | Only the junior devs had to be told to do it, but once they
           | got into the habit, everyone understood why we do it and it
           | was no big deal.
           | 
           | If I joined a company where people committed their code with
           | "stuff" or "made some changes" or "asdfhlfo;ejfo;ae," that
           | would be a red flag that I might have joined the wrong
           | company, and I'd start to wonder what else the developers
           | here do carelessly.
        
             | lossyalgo wrote:
             | Good commit messages would be nice but honestly I would be
             | over the moon if our pull requests would be approved within
             | a week without having to ping one or more people.
        
             | scottyah wrote:
             | Some of my favorite are the perhaps well-meaning but
             | totally misguided log of what files they changed.
        
             | ramijames wrote:
             | Indeed. If you can't spend two minutes (MAX) writing a
             | sentence or two explaining what the commit is for, then
             | what are we doing as developers? Commits are for future you
             | and your future team. They are a tool. Please, use them.
        
             | godelski wrote:
             | The same goes for code comments though people are much more
             | vocal about their disdain. It's ironic given how frequent
             | AI is used to generate docs. But docs are much better
             | written by the person who wrote the code, the person who
             | has all the context.
             | 
             | These things never take much time but people dismiss them
             | because of that. Because each commit and each comment in
             | isolation isn't very valuable but they are very helpful in
             | aggregate. I'm not sure why this bias exists though, since
             | the same is true for lines of code. It's also true about a
             | ton of things. All the little things add up. Just because
             | it's little now doesn't mean it's not important
        
             | asdfman123 wrote:
             | > I'd start to wonder what else the developers here do
             | carelessly
             | 
             | More likely you'd already know by this point because it
             | would be staring you in the face
        
           | berkes wrote:
           | I once tutored an intern. Who thought he was The Best
           | Programmer On Earth (didn't we all at that age?). He refused
           | to use revision control, it slowed him down.
           | 
           | So we told him to commit at least once every day, with a
           | relevant commit message, or else fail his internship.
           | 
           | He worked 21 more days. There were 21 commits: "17:00, time
           | to go home".
        
             | vntok wrote:
             | This reads like the intern was left to his own devices and
             | his output not checked at all for three weeks straight.
             | Actual tutoring would have surfaced the issue after 1 or 2
             | days tops.
        
           | drums8787 wrote:
           | I particularly love when the "CTO" is also the main offender.
        
             | jillesvangurp wrote:
             | I am a CTO and I actually have very little patience for
             | people that obsess over minor formatting issues (use a
             | linter if you care), commit messages, and other fringe
             | issues. If that's the biggest issue you have in a team,
             | amazing. You are doing great. But you probably have bigger
             | issues. The focus of the CTO is on the big picture stuff.
             | Like staying on top of technical debt and correcting people
             | when they keep on adding more of it. And making sure people
             | learn from their mistakes, focus on the important things
             | first, etc.
             | 
             | The thing with commit messages is that they are mostly
             | never going to get a lot of scrutiny. But there are
             | exceptions to this; especially if there are audits involved
             | or external contributors. And of course when making a pull
             | request to an OSS project, it is good form to make a bit of
             | an effort. It depends on the context. I tend to focus more
             | on diffs and pull requests. Not on the cryptic one liners
             | that may or may not describe some of the changes. The right
             | unit of change is a pull request, not individual commits.
             | 
             | And all this of course was when I was still able to keep on
             | top of the massive volume of change. With AI that's simply
             | no longer the case and the volume of change is only going
             | to increase over time. Human reviews are now the main
             | bottleneck to getting code merged. AIs probably should be
             | doing a lot of the reviewing, gatekeeping testing, vetting,
             | etc. Especially when AIs also produce most of the change.
             | It's likely a lot of things will slip through unless you
             | get your house in order on guard rails and process that
             | your AI agents need to follow. As a CTO, guarding quality
             | without becoming a human bottleneck is now the main
             | challenge and removing bottlenecks responsibly is part of
             | the job.
             | 
             | BTW. making AI tools write good commit messages is actually
             | be a bit expensive. Many AI tools default to just
             | summarizing the first message of a chat session under the
             | assumption that just one thing changed over the course of a
             | session. Making the AI look at the actual diff is of course
             | possible and not that hard (just ask). And it definitely
             | yields better descriptions when you do that. But it also
             | takes more time and the token cost goes up as well. I'm not
             | sure that's actually worth the expense in tokens. I tend to
             | not bother with this. But again; depends on the context.
        
               | sunnyps wrote:
               | > The thing with commit messages is that they are mostly
               | never going to get a lot of scrutiny. But there are
               | exceptions to this; especially if there are audits
               | involved or external contributors. And of course when
               | making a pull request to an OSS project, it is good form
               | to make a bit of an effort. It depends on the context. I
               | tend to focus more on diffs and pull requests. Not on the
               | cryptic one liners that may or may not describe some of
               | the changes. The right unit of change is a pull request,
               | not individual commits.
               | 
               | Why do you think OSS projects have a high bar for change
               | descriptions? It's because some things matter for the
               | long run.
               | 
               | Also, it's pretty clear from the context of this
               | discussion that it's about the descriptions on pull
               | requests (or other units of change like CLs) and not
               | individual commits that get squashed in a PR/CL.
               | 
               | > BTW. making AI tools write good commit messages is
               | actually be a bit expensive. Many AI tools default to
               | just summarizing the first message of a chat session
               | under the assumption that just one thing changed over the
               | course of a session. Making the AI look at the actual
               | diff is of course possible and not that hard (just ask).
               | And it definitely yields better descriptions when you do
               | that. But it also takes more time and the token cost goes
               | up as well. I'm not sure that's actually worth the
               | expense in tokens. I tend to not bother with this. But
               | again; depends on the context.
               | 
               | All coding agents do that these days - they just run git
               | diff and figure out what the change is when writing the
               | commit message. Are you saying that writing a better
               | change description is not worth the pennies it costs in
               | tokens?
        
           | hbn wrote:
           | One of the best developers I work with commits everything
           | with the message "changes"
           | 
           | (This is not an endorsement to do that, he's a good developer
           | in spite of his shitty commit messages)
        
             | mewpmewp2 wrote:
             | Obviously a very unpopular opinion, but I guess for my own
             | sake it's hard to write commit messages, because for me
             | it's that I have never really even found use of other
             | people commit messages, and I rarely even attempt to.
             | Ultimately code is code and I don't care about how it got
             | to how it is. I got same issue with documentation and
             | comments or really anything that isn't building stuff. I
             | don't like writing it, don't like reading it either...
             | ADHD?
             | 
             | So, before AI came and saved me from writing commit
             | messages I had alias that ran the whole git add . && git
             | commit -m ... && git push with a fixed commit message. But
             | of course we had squashing so PR title was the one to
             | eventually go there, so maybe that part is fine. But all my
             | side projects had just that.
        
               | titanomachy wrote:
               | As long as there's some record, whether it's PR or
               | commit. At Google and Meta there's no distinction, each
               | commit is a PR (approximately) and has a description and
               | discussion linked to it. I've found this really valuable
               | for understanding a piece of code, maybe it's just five
               | lines but of there's 200 words of discussion giving you
               | more context on why it is that way.
        
           | ygouzerh wrote:
           | It can be even enforced using hooks/pipelines that will check
           | that the message follow Conventional Commits as well
        
         | grepsedawk wrote:
         | Only two of the five depend on commit messages. Churn,
         | authorship, and velocity work regardless. Even teams with
         | terrible hygiene write "fix" when something breaks.
        
           | KronisLV wrote:
           | > Even teams with terrible hygiene write "fix" when something
           | breaks.
           | 
           | They might not include anything but the Jira ticket number,
           | if the environment is truly lacking.
        
           | SoftTalker wrote:
           | As noted, authorship does not if commits are squashed, which
           | seems to be common (I never do it).
        
         | heinrichhartman wrote:
         | I personally use git commit -m "." for: "Just snapshots this
         | state real quick" on a feature branch.
         | 
         | main branch is advanced on PR level, with squashed commits.
         | 
         | So the "." should never make it to main, and have PR
         | description as commit message.
        
         | stronglikedan wrote:
         | It's because the vast majority of commit messages are never
         | read by anyone, and there's other ways to fund out what
         | happened in the handful of cases where you would need to.
        
           | scottyah wrote:
           | git blame's are amazing, and rely on good comments.
        
           | mkehrt wrote:
           | I read commit messages all the time to figure out what a
           | change was about.
           | 
           | For small personal projects I often write one phrase messages
           | with `-m`, but if you're working with other people you should
           | be writing good commit messages.
        
         | travisgriggs wrote:
         | Our small team has a lot of commit messages like this. For a
         | while, we had a guy on the team who had come from a site that
         | expected more. The pet peeve he brought along was that commit
         | messages end with a period (my guess is that someone at their
         | previous work place had reasoned that forcing periods
         | encouraged developers to actually write meaningful sentences).
         | When I look at that period of development, I see lots of
         | messages like "stuff changed." And "more stuff changed." And
         | then it goes back to just "stuff changed" around the time they
         | moved on.
        
           | gcarvalho wrote:
           | > my guess is that someone at their previous work place had
           | reasoned that forcing periods encouraged developers to
           | actually write meaningful sentences
           | 
           | I have actually seen proper capitalization and correct
           | conventional-commit types to correlate very well with the
           | author being intentional and the patch being of good quality.
           | 
           | e.g.
           | 
           | - (a) chore: update some_module to include new_func
           | 
           | - (b) feat: Add new_func to handle XYZ case
           | 
           | Where:
           | 
           | (a) is not a chore, as it changes functionality, is
           | uncapitalized and is so low-signal I can probably write a 10
           | line script to reliably generate similar titles.
           | 
           | (b) is using the correct "feat" commit type, capitalized and
           | describe what this is for. I expect the body to explain
           | "why", as well, and not to reiterate the "how" in natural
           | language.
           | 
           | This is just my experience, but I've seen commit messages
           | where people actually put in some effort to usually come with
           | a good patch, and vice-versa.
        
         | lopis wrote:
         | If developers don't write commit messages, that's a culture
         | problem. At my company we demand that of each other.
        
           | hn_throwaway_99 wrote:
           | Totally agree. One thing I really like about HN is it reminds
           | you that _nobody 's_ individual experience is indicative of
           | the industry at large.
           | 
           | The parent comment stated "Most codebases I encounter just
           | have "changed stuff" or "hope this works now"." I worked at 6
           | tech companies in my career and a slew of contracting gigs,
           | and I literally never encountered the problem of commit
           | messages being uninformative. Most of the companies developed
           | strict rules for commit comments like always including an
           | issue number (with occasional [NO-ISSUE] tags allowed for
           | minor changes) or something like Conventional Commits,
           | https://www.conventionalcommits.org/en/v1.0.0/ .
        
         | yreg wrote:
         | > It's a small minority
         | 
         | Is it really a small minority? I have never worked on a project
         | that didn't have commit messages that at least tried to be
         | descriptive (sometimes people fail at it but its very different
         | to an outright "changed stuff").
         | 
         | I don't remember any friend mentioning to me them encountering
         | a work project where the messages were totally neglected
         | either.
        
           | brabel wrote:
           | Never seen that in any company I worked at either and I can't
           | believe professional developers seem to think that it would
           | be ok to write meaningless commit messages. That's just so
           | sloppy.
        
         | harryquach wrote:
         | Commit messages are often squashed after merging a feature
         | branch
        
         | kelnos wrote:
         | Bad commit messages always fail PR review for me. It requires
         | will and discipline, but it's not that hard.
        
         | loremium wrote:
         | tbh I'm not convinced that a git log history should be treated
         | as a group journal because it's not.
         | 
         | relying on git commit messages assumes they're correct by
         | convention since there is no technical constraint to enforce
         | it. and it assumes no work in progress commits, sometimes it's
         | just necessary to hit the save button real quick or move a
         | workspace from one device to another.
         | 
         | my point is: git is a way of storing and loading files at its
         | core.
        
         | max8539 wrote:
         | Sometimes it could be just a ticket number/title
        
           | bartvk wrote:
           | I think that's pretty great, actually. You can look that up
           | to see more info about the commit.
        
         | ElijahLynn wrote:
         | And in a squash and merge workflow, which are most teams I've
         | been on the past 8 years, it really is the title of the pull
         | request or merge request. That is what really matters.
         | 
         | And I really like that because it leaves room to let the
         | developer do whatever kind of commit messages they want to that
         | makes sense to them. Because nobody's really ever going to read
         | those again after it squashed and merged.
        
           | skinner927 wrote:
           | - fix - fix fr - fix frfr - plz - omg why - never gonna give
           | you up - never gonna let you down - add missing curly braces
        
           | tkzed49 wrote:
           | Every time I hear about commit messages on HN, this is my
           | first thought. I can't imagine not working in a squash
           | workflow. No matter how good your commit messages are, I do
           | not want to read all of them. The squashed commit will direct
           | me to the original PR in case I need more detail.
        
         | AStrangeMorrow wrote:
         | I also like meaningful commit names. But am sometimes guilty of
         | "hope this works now" commits, but they always follow a first
         | fix that it turns out didn't cut it.
         | 
         | I work on a lot of 2D system, and the only way to debug is
         | often to plot 1000s of results and visually check it behaves as
         | expected. Sometimes I will fix an issue, look at the results,
         | and it seems resolved (was present is say 100 cases) only to
         | realize that actually there are still 5 cases where it is still
         | present. Sure I could amend the last commit, but I actually
         | keep it as a trace of "careful this first version mostly did
         | the job but actually not quite"
        
         | aftbit wrote:
         | We have a hard division between "Core" repos (those which are
         | deployed to production / customer sites) and everything else.
         | The expectation in Core repos is that everything goes through a
         | PR process where the pull request message is intended to
         | explain the what and why of the change (perhaps with reference
         | to a ticket, but with the key information restated in the PR),
         | and goes through a review just like the code. Changes are then
         | either squashed with that as the commit message or (if they're
         | larger and benefit from a clear separation of commits), may be
         | rebased with `git rebase -i` assuming the final PR body ends up
         | in one of the commit messages.
         | 
         | Non-Core repos are absolute free-form anything goes. You can
         | commit 8 times a day without a PR as long as you're not
         | deploying to production. This is excellent for things like test
         | harnesses, CI/CD nonsense, one-off experiments, demos,
         | prototypes, etc.
         | 
         | My last Core commit had something like 20 to 1 ratio between
         | lines of commit message to lines of code (small change touching
         | something deep that required a lot of explanation). My last
         | non-Core commit message was "hope this works" (it did not).
        
         | renegade-otter wrote:
         | Many organizations squash their commit messages from PR, where
         | most commits actually happen. Unless everyone is committing to
         | trunk all the time, which almost never happens on a real job, I
         | highly doubt the value of this.
         | 
         | Showing my Git ignorance here, of course - does
         | "ancestors(trunk)" pull in all the commit messages?
        
       | baquero wrote:
       | I put it into a gist :)
       | 
       | https://gist.github.com/aeimer/8edc0b25f3197c0986d3f2618f036...
        
       | bullen wrote:
       | Dying or stabilizing?
       | 
       | Most good projects end up solving a problem permanently and if
       | there is no salary to protect with bogus new features it is then
       | to be considered final?
        
       | Cthulhu_ wrote:
       | For "what changes the most", in my project it's package.json /
       | lock (because of automatic dependency updates) and translation /
       | localization files; I'd argue that's pretty normal and healthy.
       | 
       | For the "bus factor", there's one guy and then there's me, but I
       | stopped being a primary contributor to this project nearly two
       | years ago, lol.
        
       | pscanf wrote:
       | I just finished1 building an experimental tool that tries to
       | figure out if a repo is slopware or not just by looking at it's
       | git history (plus some GitHub activity data).
       | 
       | The takeaway from my experiment is that you can really tell a lot
       | by how / when / what people commit, but conclusions are very hard
       | to generalize.
       | 
       | For example, I've also stumbled upon the "merge vs squash" issue,
       | where squashes compress and mostly hide big chunks of history, so
       | drawing conclusions from a squashed commit is basically just wild
       | guessing.
       | 
       | (The author of course has also flagged this. But I just wanted to
       | add my voice: yeah, careful to generalize.)
       | 
       | 1 Nothing is ever finished.
        
       | tom-blk wrote:
       | Nice! Will probably adopt this, seems to give a great overview!
        
       | therealdeal2020 wrote:
       | superficial. If I have to unfuck the backend 10 times a week in
       | our API adapter, then these commands will show me constantly
       | changing the API adapter, although it's the backend team
       | constantly fixing their own bugs
        
       | icedchai wrote:
       | I wouldn't trust "commit counts." The quality and content of a
       | "commit" can vary widely between developers. I have one guy on my
       | team who commits only working code that has been thoroughly
       | tested locally, another guy who commits one line changes that
       | often don't work, only to be followed by fixes, and more fixes.
       | His "commits" have about 1/100th of the value of the first guy.
        
         | fpoling wrote:
         | The author does not look at counter values but rather at how
         | the values changes. That reveals dynamics.
        
           | icedchai wrote:
           | My comment still seems relevant? Do frequent commits to
           | correct mistakes imply more "value" than infrequent, but well
           | tested, commits, or what? I don't think it is a reliable
           | signal.
        
       | TacticalCoder wrote:
       | > The 20 most-changed files in the last year. The file at the top
       | is almost always the one people warn me about. "Oh yeah, that
       | file. Everyone's afraid to touch it."
       | 
       | I've got my Emacs set up to display next to every file that is
       | versioned the number of commits that file has been modified in
       | (for the curious: using a modified all-the-icons-ivy-rich +
       | custom elisp code + custom Bash scripts I wrote and it's trickier
       | than it seems to do in a way that doesn't slows everything down).
       | For example in the menu to open a file or open a recently visited
       | file etc.: basically in every file list, in addition to its size,
       | owner, permissions, etc. I also add the number of commits if it's
       | a versioned file.
       | 
       | I like the fix/bug/broken search in TFA to see where the bugs
       | gather.
        
       | blenderob wrote:
       | > Is This Project Accelerating or Dying > > git log
       | --format='%ad' --date=format:'%Y-%m' | sort | uniq -c
       | 
       | If the commit frequency goes down, does it really mean that the
       | project is dying? Maybe it is just becoming stable?
        
         | Sharlin wrote:
         | Something something Red Queen's race
        
         | dan-bailey wrote:
         | Projects become more stable with time? Since when?
        
         | onion2k wrote:
         | Technically you're correct that change frequency doesn't
         | necessarily mean dead, but the number of projects that are
         | receiving very few updates because they're 'done' is a fraction
         | of a fraction of a percent compared to the number that are just
         | plain dead. I'm certain you can use change frequency as a proxy
         | and never be wrong.
        
           | Supermancho wrote:
           | > I'm certain you can use change frequency as a proxy and
           | never be wrong.
           | 
           | I (largely) wrote a corporate application 8 years ago, with 2
           | others. There was one change 2 years ago from another dev.
           | 
           | Lots of programs are functionally done in a relatively short
           | amount of time.
           | 
           | "Accelerating or Dying" sounds like private equity's lazy way
           | to describe opportunity, not as a metric to describe
           | software.
        
             | onion2k wrote:
             | That sort of project exists in an ocean of abandoned and
             | dead projects though. For every app that's finished and
             | getting one update every few years there are _thousands_ of
             | projects that are utterly broken and undeployable, or
             | abandoned on Github in an unfinished state, or sitting on
             | someone 's HDD never be to touched again. Assuming a low
             | change frequency is a proxy for 'dead' is _almost_ always
             | correct, to the extent that it 's a reasonable proxy for
             | dead.
             | 
             | I know people win the lottery every week, but I also
             | believe that buying a lottery ticket is _essentially_ the
             | same as losing. It 's the same principle.
        
               | goosejuice wrote:
               | With respect, this is a myopic view. Not all software is
               | an "app" or a monolith. If you use a terminal, you are
               | directly using many utilities that by this metric are
               | considered dying or dead.
        
         | stackedinserter wrote:
         | Or you hired someone who squashes or doesn't commit every
         | single change.
        
         | ziml77 wrote:
         | That was my question too. I have plenty of projects I've worked
         | on where they rarely get touched anymore. They don't need new
         | features and nothing is broken.
        
           | SoftTalker wrote:
           | Is it fair to say they are being "worked on" if nothing is
           | being done?
        
             | duckmysick wrote:
             | Sometimes you need to bump a dependency version, adjust the
             | code to a changed API endpoint, or update a schema. Even if
             | the core features stay the same, there's some expected
             | maintenance. I'd still call that being worked on, in a
             | sense that _someone_ has to do it.
        
         | heresie-dabord wrote:
         | For this command in particular, one can add a cheap bar chart
         | with awk:
         | 
         | git log --format='%ad' --date=format:'%Y-%m' | sort | uniq -c |
         | awk '{printf $2" "; for (i=1;i<=$1;i++){printf "-";} print "";
         | }'
        
           | zikani_03 wrote:
           | This is a neat trick for a quick visual presentation, thanks!
        
         | goosejuice wrote:
         | Yeah, this one demonstrates a particularly pernicious view of
         | software development. One where growth, no matter how
         | artificial, is the only sign of success.
         | 
         | If you work with service oriented software, the projects that
         | are "dying" may very well be the most successful if it's a key
         | component. Even from a business perspective having to write
         | less code can also be a sign of success.
         | 
         | I don't know why this was overlooked when the churn metric is
         | right there.
        
           | BeetleB wrote:
           | Bad memories at my former big tech company.
           | 
           | Whenever we initiated a new (internal) SW project, it had to
           | go through an audit. One of the items in the checklist for
           | any dependency was "Must have releases in the last 2 years"
           | 
           | I think the rationale was the risk of security
           | vulnerabilities not being addressed, but still ...
        
       | stackedinserter wrote:
       | This should be renamed to "Git commands that I run as a new hire
       | to get metrics I'll forget on day 2".
        
       | joshstrange wrote:
       | I ran these commands on a number of codebases I work on and I
       | have to say they paint a very different picture than the reality
       | I know to be true.
       | 
       | > git shortlog -sn --no-merges
       | 
       | Is the most egregious. In one codebase there is a developer's
       | name at the top of the list who outpaced the number 2 by almost
       | 3x the number of commits. That developer no longer works at the
       | company? Crisis? Nope, the opposite. The developer was a net-
       | negative to the team in more ways than one, didn't understand the
       | codebase very well at all, and just happened to commit every time
       | they turned around for some reason.
        
         | fenaer wrote:
         | So that person, on one central codebase at a company I work
         | for, is me.
         | 
         | Assuming I'm not ego-mad, I like to think this is because I
         | built the project from the ground up before handing it over to
         | the rest of the team.
         | 
         | These days other people commit more often than I do, but my
         | name is still dominant, and probably will be for some time.
        
           | joshstrange wrote:
           | I'm not saying more commits = bad developer. In my example
           | that happened to be the case but not because they had a lot
           | of commits but because they were bad at their job. I was just
           | trying to warn that taking these git snippets at face-value
           | does not paint the full picture.
           | 
           | If someone came to me and said "I ran these and I see XXX was
           | the most prolific committer and they left X months ago, what
           | will be do???" I'd have to work hard not to laugh.
           | 
           | Since these snippets are self-described as ways to get
           | familiar with the code/projects I wanted to provide the
           | counter point. Most of those snippets do not at all paint the
           | real picture and for all the repos I tested it on they paint
           | the opposite of reality.
           | 
           | I know these codebases like the back of my hand, the
           | purported purpose of these snippets is to better understand
           | the codebase, I can tell you they don't work for anything I
           | tested them on. Maybe they work for other codebases but the
           | sample size I have access to says they don't work for me.
        
             | troyvit wrote:
             | I haven't finished the article yet but I think your point
             | is an important one, and that's to run the commands with a
             | context in mind. The article seems to be coming from the
             | perspective of somebody who is brand new to the project,
             | and as your experience indicates, interviewing teams and
             | leads before running those commands might add more
             | understanding to what they're telling you.
        
         | Aperocky wrote:
         | Also - be careful of automated workflow that uses a single
         | persons credential.. skews this by a lot.
        
           | kevstev wrote:
           | Once word got out that a report was going up to a department
           | head around commit frequency, a few of us started to make
           | "backup commits" to boost our stats. Whether it be dev server
           | config files (just in case!), local dev setups, whatever..
           | just something that changed enough on its own but would
           | produce a steady stream of commits, while having some
           | potential use case, however unlikely it was to actually be
           | needed.
           | 
           | Modern problems require modern solutions and all...
        
             | joshstrange wrote:
             | Been there. At a company where KPIs became all the rage
             | they asked each department to come up with KPIs to report
             | on. The eng/dev department pushed back a bit saying there
             | aren't any easy KPIs to surface and anything we did would
             | either be trivial to game and/or would result in a bunch of
             | extra work to track (like needing to add a ton of metadata
             | to various tickets/processes to tie it all together). They
             | didn't care and we settled on a bunch of BS metrics that we
             | all knew were BS and trivial to game.
        
         | kmacdough wrote:
         | Everything in context. This is one of many reasons I'm a
         | proponent of squash-and-merge. If a change really needs more
         | than one permanent commit, it should probably be split up or if
         | absolutely necessary should be on a feature branch maintaining
         | similar process. Under this process, feature branches are not
         | squashed.
         | 
         | This leaves developers to commit locally and comment as much or
         | little as they like.
        
         | dgunay wrote:
         | Yeah. I am the top committer at my current workplace, but I'd
         | say that a majority of that gap is because my particular
         | workflow results in many smaller commits than my coworkers.
        
         | perlgeek wrote:
         | I think OP's context is: they get called to help troubled
         | projects. Often the people that hired them might not know where
         | exactly the trouble comes from.
         | 
         | If you look at a code base that's not really in trouble, these
         | commands don't reveal the source of the trouble, because there
         | might be none.
        
         | maest wrote:
         | I suspect OP never actually ran these commands and this article
         | was brainstormed and written by an LLM.
        
       | yieldcrv wrote:
       | blog posts are just comments that would have been torn apart if
       | only posted on a forum, now masquerading as important universal
       | edicts
        
       | alaudet wrote:
       | This is good stuff. Why I never think of things like this is
       | beyond me. Thanks
        
       | mikaoelitiana wrote:
       | I created a small TUI based on the article
       | https://github.com/mikaoelitiana/git-audit
        
         | vladsanchez wrote:
         | You beat me to it! I envisioned creating some aliases but you
         | exceeded it by building a TUI. Good job Claude! LOL ;)
        
       | guilhermeasper wrote:
       | These commands are very useful, but adapting them to the codebase
       | makes a huge difference.
       | 
       | For most, I added some filters and slightly changed the regex,
       | and it showed the reality of the codebase (I already knew the
       | reality, I just wanted to see if it matched, and it did).
        
       | yonatan8070 wrote:
       | My team usually uses "Squash and merge" when we finish PRs, so I
       | feel that would skew the results significantly as it hides 99% of
       | the commit messages inside the long description of the single
       | squashed merge commit.
        
       | StableAlkyne wrote:
       | Biggest life changer for me has been:
       | 
       | git clone --depth 1 --branch $SomeReleaseTag $SomeRepoURL
       | 
       | If you only want to build something, it only downloads what you
       | need to build it. I've probably saved a few terabytes at this
       | point!
        
       | aidenn0 wrote:
       | What's the subversion equivalents to these commands?
        
       | arthurjj wrote:
       | These were interesting but I don't know if they'd work on most or
       | any of the places I've worked. Most places and teams I've worked
       | at have 2-3 small repos per project. Are most places working with
       | monorepos these days?
        
         | abustamam wrote:
         | I can't speak for most, but the past few places I consulted or
         | worked at used monorepos.
        
           | BigTTYGothGF wrote:
           | Jesus I've seen what you've done for others and want that for
           | myself.
        
             | abustamam wrote:
             | ?
        
       | atlgator wrote:
       | Step 6: grep the thread count on the squash-merge debate to
       | determine if the team has unresolved interpersonal conflict.
        
       | jayd16 wrote:
       | No searching the codebase/commits for "fuck" and shit"? That will
       | give you an idea what what was put in under stressful
       | circumstances like a late night during a crunch.
        
       | tetromino_ wrote:
       | Out of curiosity, I ran the 5 command on my project's public git
       | tree. The only informative one was #4 ("Is This Project
       | Accelerating or Dying") - it showed cliffs when significant
       | pieces of logic were decoupled and moved to other repos.
        
       | avazhi wrote:
       | More AI slop.
       | 
       | Wtf is happening to this website
        
         | gpvos wrote:
         | Most often, what is happening is that people are groundlessly
         | accusing others of writing AI slop.
        
           | twoodfin wrote:
           | This is 100% AI slop. It's really not obvious to you?
           | 
           | Look at the rest of this blog:
           | 
           | https://piechowski.io/post/
           | 
           | Almost no posts since 2020, then a swarm of LLM-style
           | clickbait titles...
           | 
           | Oh wait, the 2020 one also has a clickbait title... and it
           | was substantially rewritten in 2026!!
        
             | alexhans wrote:
             | I'd be curious to see if my blog posts/titles feel like AI
             | slop to you.
             | 
             | https://alexhans.github.io/
             | 
             | No need to read them, just a vibe check would be
             | insightful. It's weird how branding, even before AI had a
             | lot of the same catchy patterns, and now it's hard to
             | define what is the right prose (engineers might want one
             | thing and other role families others) and sometimes you're
             | trying to write almost with the "everyone else bag in mind"
             | because that's the personal connections you link your
             | "here's what I often repeat in written form".
        
             | gpvos wrote:
             | Maybe it is. But the comments complaining about it are
             | worse than the posts themselves. And as I wrote, many of
             | them are wrong. Downvote or ignore, and move on, please.
        
       | heliumtera wrote:
       | So you value more rushed descriptions of changes than actual
       | changes. Nice
        
       | progx wrote:
       | Before, I ask AI "is this project maintained" done.
        
       | yayadarsh wrote:
       | git commands I run before reading any code:
       | 
       | git rm -rf .
        
       | drob518 wrote:
       | Nice timing. I was just today needing some of the info that these
       | commands surface. Serendipitous!
        
       | md224 wrote:
       | The last sentence of the article is "Here's what the rest of the
       | week looks like." and then it just stops. Am I missing something?
        
         | lkakitani wrote:
         | It is probably referring to the article linked in the "codebase
         | audit" text
        
         | dgb23 wrote:
         | It's phrased in a confusing way, seems to be a mistake. It
         | becomes clearer when you click the link in the sentence before.
        
       | jlarocco wrote:
       | I'm so used to magit, it seems kind of primitive to pipe git
       | output around like this.
       | 
       | Anyway, I can glean a lot of this information in a few minutes
       | scrolling through and filtering the log in magit, and it doesn't
       | require memorizing a bunch of command line arguments.
        
       | zdkaster wrote:
       | Can't resist making it as a git command
       | https://github.com/zdk/git-critique
        
       | kittikitti wrote:
       | This is a great list of commands to quickly understand a
       | repository. Thank you for sharing.
        
       | konovalov-nk wrote:
       | To me all of these are symptoms of the problem that I outlined in
       | my recent blog post:
       | https://news.ycombinator.com/item?id=47606192
       | 
       | and it touches in detail what exactly commit standards should be,
       | and even how to automate this on CI level.
       | 
       | And then I also have idea/vision how to connect commits to actual
       | product/technical/infra specs, and how to make it all granular
       | and maintainable, and also IDE support.
       | 
       | I would love to see any feedback on my efforts. If you decide to
       | go through my entire 3 posts I wrote, thank you
        
       | Ultcyber wrote:
       | Nice set of commands! I would suggest using --all flag with git
       | log though - scans through all branches and not just the current
       | one
        
       | nextlevelwizard wrote:
       | These are actually fun to run. Just checked from work who makes
       | most commits and found I have as many commits in past 2 years as
       | 3 next people.
       | 
       | That probably isn't a good sign
        
       | moritzwarhier wrote:
       | Interesting ideas, but some to me seem very overgeneralizef,
       | e.g.:
       | 
       | > How Often Is the Team Firefighting
       | 
       | > git log --oneline --since="1 year ago" | grep -iE
       | 'revert|hotfix|emergency|rollback
       | 
       | > Crisis patterns are easy to read. Either they're there or
       | they're not.
       | 
       | I disagree with the last two quoted sentences, and also, they
       | sound like an LLM.
        
         | dgunay wrote:
         | This one was funny to me because sure, it was accurate for my
         | particular codebase, but also anyone paying attention to the
         | company Slack would already know how often fires happen.
        
       | pwr1 wrote:
       | Solid list. I'd add git log --all --oneline --graph pretty early
       | on -- gives you a quick sense of how active different branches
       | are and whether this is a "one person commits everything" project
       | or actually distributed. Helped me a ton on a job where I
       | inheritied a monolith with like 4 years of history.
       | 
       | The git blame tip is underrated. People treat it like a gotcha
       | tool but its maybe the fastest way to find the PR/ticket that
       | explains a weird decision.
        
       | giancarlostoro wrote:
       | > One caveat: squash-merge workflows compress authorship. If the
       | team squashes every PR into a single commit, this output reflects
       | who merged, not who wrote. Worth asking about the merge strategy
       | before drawing conclusions.
       | 
       | I abhor squash merging for this and a few other reasons. I
       | literally have to go out of my way to re-check out a branch.
       | Someone who wants to use my current branch cannot do so if I
       | merge my changes a month later, because the squash rewrites
       | history, and now git is very confused. I don't get the obsession
       | with "cleaning up the history" as if we're all always constantly
       | running out of storage over 2 more commits.
        
         | stetrain wrote:
         | For me the benefit is that I can revert or cherry-pick things
         | one entire PR at a time, and I don't have to care if the author
         | implemented their PR with a bunch of small "work in progress"
         | commits.
         | 
         | And GitHub at least sets the author of the squashed commit as
         | the one who opened the PR, not the one who merged it.
         | 
         | I can definitely see where it wouldn't work well for other
         | workflows but I've had it work well on several teams and it
         | seems easier than trying to get everyone to clean up their
         | commits into nice, clean, well-titled histories before putting
         | up a PR.
        
         | ball_of_lint wrote:
         | You don't have to rewrite the source branch to squash merge?
         | 
         | I wouldn't describe it as "cleaning up the history". And the
         | goal isn't to save space, it's to keep a linear history where
         | things ought to be working at each commit (to enable tools like
         | git bisect and similar).
         | 
         | I personally don't ensure everything is working every time I
         | commit - That's what CI is for. The exact process I work
         | through while writing a PR shouldn't impact other people's
         | workflows, so when I merge back into a central branch it should
         | really only reveal the granularity at which I assert 'this code
         | is working and good', which is NOT every intermediate commit I
         | make. Squash merge is a way to do that that fits nicely with
         | existing engineering workflows, like code review.
        
       | siva7 wrote:
       | Thanks. What a great Skill for my Claude
        
       | ML0037 wrote:
       | i'll try to use the in an hook and test them with Claude. Thank
       | you !
        
       | gpvos wrote:
       | Ah yes, good old                   |sort |uniq -c |sort -nr |head
       | -20
       | 
       | I use it often.
        
       | xyst wrote:
       | might be useful if there's an established commit message
       | formatting. But for a majority of Fortune 500 to small businesses
       | that I have worked for this is not the case. Usually you see shit
       | like this:
       | 
       | On main:
       | 
       | 2020-01-01: "Changes"
       | 
       | 2020-01-05: "Changes"
       | 
       | 2020-01-06: "merge <ref to jira/gh issue>"
       | 
       | 2020-01-07: "revert <ref to unrelated jira/gh issue from 2 yrs
       | ago>"
       | 
       | Then there's the people that include merge commits despite
       | agreeing on rebasing.
       | 
       | Occasionally see sprinkles of decent, consistently formatted
       | commit messages.
       | 
       | I think this is only useful on medium to large _open source_
       | projects. Clearly established CONTRIBUTING.md/README.md and
       | commit formatting/merging guide.
        
       | jbethune wrote:
       | Saved. Very useful. Normally I just dig around the Github UI to
       | see what I can glean from contributor graphs and issues but these
       | git commands are a pretty elegant solution as well.
        
       | cratermoon wrote:
       | This is the premise of the excellent book _Your Code as a Crime
       | Scene_. The history and structure of the codebase reveals a
       | wealth of information.
        
       | ivanjermakov wrote:
       | When at work we migrated to monorepo, there was an implicit
       | decision to drop commit history. I was the loudest one to make
       | everyone understand how important it is.
        
       | kelnos wrote:
       | I really wanted to like this. The author presents a well-thought-
       | out rationale for what conclusions to draw, but I'm skeptical.
       | Commit counts aren't a great signal: yes, the person with the
       | highest night be the person who built it or knows the most about
       | it, but that could also be the person who is sloppy with commits
       | (when they don't squash), or someone who makes a lot of mistakes
       | and has to go back and fix them.
       | 
       | The grep for bugs is not particularly comprehensive: it will pick
       | up some things that aren't bugs, and will miss a bunch of things
       | too.
       | 
       | The "project accelerating or dying" seems odd to me. By
       | definition, the bulk of commits/changes will be at the very
       | beginning of history. And regardless, "stability" doesn't mean
       | "dying".
        
       | fmbb wrote:
       | > One caveat: squash-merge workflows compress authorship. If the
       | team squashes every PR into a single commit, this output reflects
       | who merged, not who wrote. Worth asking about the merge strategy
       | before drawing conclusions.
       | 
       | Well isn't it typical that the person who wrote is also the
       | person that merged? I have never worked in a place where that is
       | not the norm for application code.
       | 
       | Even if you are one of those insane teams that do not squash
       | merge because keeping everyone's spelling fixes and "try CI
       | again" commits is important for some reason, you will still not
       | see who _wrote_ the code, you will only see who committed the
       | code. And if the person that wrote the code is not also the
       | person that merges the code, I see no reason to trust that the
       | person making commits is also the person writing the code.
        
       | ianberdin wrote:
       | Well, 70% of my commits are "123".
        
       | pvtmert wrote:
       | The best is: You know that you have a major issue when the data
       | (especially ones around commit messages) is empty or noisy.
       | 
       | Plus, adding an extra point: When you run git log --oneline
       | --graph and the pattern on the left is more complex than the
       | Persian carpet patterns or Ancient Egyptian writings in the Great
       | Pyramid of Giza, you know it's engineering & process quality
       | issue than the code itself...
        
       | jwpapi wrote:
       | Thats why I'm visting HN.
       | 
       | Thank you.
        
       | youknownothing wrote:
       | I like the mindset, it reminds me of "Your code as a crime scene"
       | by Adam Tornhill:
       | https://www.adamtornhill.com/articles/crimescene/codeascrime...
       | 
       | Also, very tangentially, to the notion of the Developer's Legacy
       | Index: https://www.javaadvent.com/2021/12/using-jgit-to-analyse-
       | the...
        
         | suprjami wrote:
         | Nice to see a fellow Tornhill fan. I loved his early C
         | articles.
        
       | lavp wrote:
       | I made a bash function to turn these commands into a one page
       | diagnostics report so that you can use this in your `.bashrc`:
       | 
       | Diagnostics function, colorized (I tried to add guards so it is
       | portable with terminals that do not support color):
       | git_diag() {         local since="${1:-1 year ago}"         local
       | root repo branch              # --- patterns ---         local pa
       | ttern="${GIT_DIAG_PATTERN:-fix|bug|broken|hotfix|incident|issue|p
       | atch}"         local
       | firefight_pattern="revert|hotfix|emergency|rollback"
       | # --- colors ---         local GREP_COLOR_MODE='never'         if
       | [[ -z "${NO_COLOR:-}" ]] && [[ -t 1 ]] && [[ "${TERM:-}" !=
       | "dumb" ]] && [[ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]];
       | then           local BLACK=$(tput setaf 0)           local
       | RED=$(tput setaf 1)           local GREEN=$(tput setaf 2)
       | local YELLOW=$(tput setaf 3)           local BLUE=$(tput setaf 4)
       | local MAGENTA=$(tput setaf 5)           local CYAN=$(tput setaf
       | 6)           local WHITE=$(tput setaf 7)           local
       | BOLD=$(tput bold)           local DIM=$(tput dim 2>/dev/null ||
       | true)           local RESET=$(tput sgr0)
       | GREP_COLOR_MODE='always'         else           local BLACK=''
       | RED='' GREEN='' YELLOW='' BLUE='' MAGENTA='' CYAN='' WHITE=''
       | local BOLD='' DIM='' RESET=''         fi              local
       | TITLE="$CYAN"         local COLOR_COUNT="$CYAN"         local
       | COLOR_FILE="$YELLOW"              if ! root="$(git rev-parse
       | --show-toplevel 2>/dev/null)"; then           printf 'git_diag:
       | not inside a Git repository\n' >&2           return 1         fi
       | repo="${root##*/}"         branch="$(git branch --show-current
       | 2>/dev/null)"         branch="${branch:-DETACHED}"
       | _git_diag_fmt_count() {           local count_color="$1"
       | local text_color="$2"                awk -v
       | count_color="$count_color" -v text_color="$text_color" -v
       | reset="$RESET" '{             c=$1             $1=""
       | sub(/^ +/, "")             printf "  %s%10d%s  %s%s%s\n",
       | count_color, c, reset, text_color, $0, reset           }'
       | }              printf '%s%sGit repo diagnostics%s\n' "$BOLD"
       | "$TITLE" "$RESET"         printf '%s%-11s%s %s\n' "$BOLD" "Repo:"
       | "$RESET" "$repo"         printf '%s%-11s%s %s\n' "$BOLD"
       | "Branch:"    "$RESET" "$branch"         printf '%s%-11s%s %s\n'
       | "$BOLD" "Timeframe:" "$RESET" "$since - now"         printf
       | '\n\n'              printf '%s%s1) Most changed files%s\n'
       | "$BOLD" "$TITLE" "$RESET"         git log --since="$since"
       | --format='' --name-only \           | awk 'NF' \           | sort
       | \           | uniq -c \           | sort -nr \           | head
       | -n 10 \           | _git_diag_fmt_count "$COLOR_COUNT"
       | "$COLOR_FILE"              printf '\n%s%s2) Top contributors%s\n'
       | "$BOLD" "$TITLE" "$RESET"         git shortlog -sn --no-merges
       | --since="$since" \           | head -n 10 \           | awk -v
       | count_color="$COLOR_COUNT" -v reset="$RESET" '{
       | printf "  %s%10d%s  %s\n", count_color, $1, reset, substr($0,
       | index($0,$2))             }'              printf '\n%s%s3)
       | Bug/fix hotspots%s %s(pattern: %s)%s\n' "$BOLD" "$TITLE" "$RESET"
       | "$DIM" "$pattern" "$RESET"         git log --since="$since"
       | --format='' --name-only -i -E --grep="$pattern" \           | awk
       | 'NF' \           | sort \           | uniq -c \           | sort
       | -nr \           | head -n 10 \           | _git_diag_fmt_count
       | "$COLOR_COUNT" "$COLOR_FILE"              printf '\n%s%s4) Commit
       | count by month%s\n' "$BOLD" "$TITLE" "$RESET"         git log
       | --since="$since" --format='%ad' --date=format:'%Y-%m' \
       | | sort \           | uniq -c \           | sort -k2r \
       | | awk -v count_color="$COLOR_COUNT" -v mag="$MAGENTA" -v
       | reset="$RESET" '             {               data[NR,1] = $2
       | data[NR,2] = $1               if (length($1) > max) max =
       | length($1)             }             END {               for (i =
       | 1; i <= NR; i++) {                 printf "  %s%10s%s  %s%*d
       | commits%s\n",                   mag, data[i,1], reset,
       | count_color, max, data[i,2], reset               }             }
       | '              printf '\n%s%s5) Firefighting commits%s
       | %s(pattern: %s)%s\n' "$BOLD" "$TITLE" "$RESET" "$DIM"
       | "$firefight_pattern" "$RESET"         git log --since="$since" -i
       | -E \           --grep="$firefight_pattern" \
       | --date=short \           --pretty=format:'%ad %h %s' \
       | | head -n 10 \           | awk -v mag="$MAGENTA" -v dim="$DIM" -v
       | reset="$RESET" '{               date=$1               hash=$2
       | $1=$2=""               sub(/^  */, "")               printf "
       | %s%-10s%s  %s%-12s%s  %s\n",                 mag, date, reset,
       | dim, hash, reset,                 $0             }' \           |
       | GREP_COLORS='ms=01;31' grep --color="$GREP_COLOR_MODE" -i -E
       | "$firefight_pattern"       }
       | 
       | Uncolorized diagnostics function (same, but without the colors):
       | git_diag() {         local since="${1:-1 year ago}"         local
       | pattern="${GIT_DIAG_PATTERN:-fix|bug|broken|hotfix|incident|issue
       | |patch}"         local root repo branch              if !
       | root="$(git rev-parse --show-toplevel 2>/dev/null)"; then
       | printf 'git_diag: not inside a Git repository\n' >&2
       | return 1         fi              repo="${root##*/}"
       | branch="$(git branch --show-current 2>/dev/null)"
       | branch="${branch:-DETACHED}"              _git_diag_fmt_count() {
       | awk '{             c=$1             $1=""             sub(/^ +/,
       | "")             printf "  %10d  %s\n", c, $0           }'
       | }              printf
       | '============================================================\n'
       | printf 'Git repo diagnostics\n'         printf '%-11s%as\n'
       | 'Repo:'      "$repo"         printf '%-11s%s\n' 'Branch:'
       | "$branch"         printf '%-11s%s\n' 'Timeframe:' "$since"
       | printf '=========================================================
       | ===\n\n'              printf '1) Most changed files (top 10)\n'
       | git log --since="$since" --format='' --name-only \           |
       | awk 'NF' \           | sort \           | uniq -c \           |
       | sort -nr \           | head -n 10 \           |
       | _git_diag_fmt_count              printf '\n2) Top 10 contributors
       | (no merges, since %s)\n' "$since"         git shortlog -sn --no-
       | merges --since="$since" \           | head -n 10 \           |
       | _git_diag_fmt_count              printf '\n3) Bug/fix hotspots
       | (top 10, matching: %s)\n' "$pattern"         git log
       | --since="$since" --format='' --name-only -i -E --grep="$pattern"
       | \           | awk 'NF' \           | sort \           | uniq -c \
       | | sort -nr \           | head -n 10 \           |
       | _git_diag_fmt_count              printf '\n4) Commit count by
       | month (since %s)\n' "$since"         git log --since="$since"
       | --format='%ad' --date=format:'%Y-%m' \           | sort \
       | | uniq -c \           | sort -k2r \           | awk '
       | {               data[NR,1] = $2               data[NR,2] = $1
       | if (length($1) > max) max = length($1)             }
       | END {               for (i = 1; i <= NR; i++) {
       | printf "  %10s  %*d commits\n", data[i,1], max, data[i,2]
       | }             }           '              printf '\n5) 10 most
       | recent firefighting commits (revert|hotfix|emergency|rollback)\n'
       | git log --since="$since" -i -E \
       | --grep='revert|hotfix|emergency|rollback' \
       | --date=short \           --pretty=format:'%ad %h %s' \
       | | head -n 10 \           | awk '{               date=$1
       | hash=$2               $1=$2=""               sub(/^  */, "")
       | printf "  %-10s  %-12s  %s\n", date, hash, $0             }' \
       | | GREP_COLORS='ms=01;31' grep --color=always -i -E
       | 'revert|hotfix|emergency|rollback'       }
        
       | sigmonsays wrote:
       | I have a strong suspicion this is AI slop. I also think this
       | article draws way too many conclusions from a git log.
        
       | Yondle wrote:
       | Hey guys this was just meant to give you inspiration, its not a
       | set of rules. How about use what works for you (:
        
       | RickHull wrote:
       | Thanks for this. My updated relevant portion of ~/.gitconfig:
       | [alias]             st = status             ci = commit
       | co = checkout             br = branch             df = diff
       | dfs = diff --stat             dfc = diff --cached             dfh
       | = diff --histogram             dfn = diff --name-status
       | rs = restore             rsc = restore --staged             last
       | = log -1 HEAD             lg = log --graph --decorate --oneline
       | --abbrev-commit             cm = commit -m             ca =
       | commit --amend             cane = commit --amend --no-edit
       | who = shortlog -sn --no-merges HEAD             dmg = log
       | --oneline -i -E --grep='(incident|outage|downtime|rollback|revert
       | |mitigate|mitigation|hotfix|broke|prod)' --since='1 year ago'
       | bugs = log --oneline -i -E --grep='(bug|bugfix|fix|fixed|fixes|de
       | fect|regression|hotfix|broke)' --since='1 year ago'
       | bugfiles = !git log --name-only --format='' -i -E --grep='(bug|bu
       | gfix|fix|fixed|fixes|defect|regression|hotfix|broke)' --since='1
       | year ago' | sort | uniq -c | sort -nr             monthly = !git
       | log --since='1 year ago' --format='%ad' --date=format:'%Y-%m' |
       | sort | uniq -c             churn = !git log --format='' --name-
       | only --diff-filter=AM --since='1 year ago' | sort | uniq -c |
       | sort -nr | head -20
        
       ___________________________________________________________________
       (page generated 2026-04-09 03:00 UTC)