Git commands I run before reading any code
- pzmarzly - 35530 sekunder sedanJujutsu equivalents, if anyone is curious:
What Changes the Most
Who Built Thisjj 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
Where Do Bugs Clusterjj log --no-graph -r 'ancestors(trunk()) & ~merges()' \ -T 'self.author().name() ++ "\n"' \ | sort | uniq -c | sort -nr
Is This Project Accelerating or Dyingjj 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
How Often Is the Team Firefightingjj log --no-graph -r 'ancestors(trunk())' \ -T 'self.committer().timestamp().format("%Y-%m") ++ "\n"' \ | sort | uniq -c
Much more verbose, closer to programming than shell scripting. But less flags to remember.jj log --no-graph \ -r 'ancestors(trunk()) & committer_date(after:"1 year ago") & description(regex:"(?i)revert|hotfix|emergency|rollback")' - bsuvc - 28082 sekunder sedanI 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).
- joshstrange - 23225 sekunder sedanI 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.
- ivanjermakov - 1003 sekunder sedanWhen 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.
- ramon156 - 35069 sekunder sedan> 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?
- mattrighetti - 32886 sekunder sedanI have a summary alias that kind of does similar things
EDIT: props to https://github.com/GitAlias/gitalias# 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" - JetSetIlly - 34444 sekunder sedanSome 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.
- whstl - 29163 sekunder sedan> 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.
- icedchai - 24529 sekunder sedanI 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.
- blenderob - 23540 sekunder sedan> 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?
- croemer - 32765 sekunder sedanRather 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)
- jbethune - 2547 sekunder sedanSaved. 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.
- moritzwarhier - 10260 sekunder sedanInteresting 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.
- StableAlkyne - 20878 sekunder sedanBiggest 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!
- bullen - 27368 sekunder sedanDying 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?
- pwr1 - 9993 sekunder sedanSolid 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.
- konovalov-nk - 11983 sekunder sedanTo 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
- fzaninotto - 28849 sekunder sedanInstead of focusing on the top 20 files, you can map the entire codebase with data taken from git log using ArcheoloGit [1].
- cratermoon - 1048 sekunder sedanThis 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.
- seba_dos1 - 34591 sekunder sedan> 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).
- Cthulhu_ - 26848 sekunder sedanFor "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.
- arthurjj - 20701 sekunder sedanThese 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?
- gherkinnn - 35870 sekunder sedanThese are some helpful heuristics, thanks.
This list is also one of many arguments for maintaining good Git discipline.
- - 29235 sekunder sedan
- alaudet - 21732 sekunder sedanThis is good stuff. Why I never think of things like this is beyond me. Thanks
- giancarlostoro - 9771 sekunder sedan> 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.
- pscanf - 26586 sekunder sedanI just finished¹ 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.)
¹ Nothing is ever finished.
- nextlevelwizard - 10325 sekunder sedanThese 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
- niedbalski - 29237 sekunder sedanAges ago, google released an algorithm to identify hotspots in code by using commit messages. https://github.com/niedbalski/python-bugspots
- niedbalski - 29213 sekunder sedanAges ago google wrote an algorithm to detect hotspots by using commit messages, https://github.com/niedbalski/python-bugspots
- zdkaster - 12829 sekunder sedanCan't resist making it as a git command https://github.com/zdk/git-critique
- alkonaut - 30920 sekunder sedanTrusting 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).
- Ultcyber - 10550 sekunder sedanNice set of commands! I would suggest using --all flag with git log though - scans through all branches and not just the current one
- tetromino_ - 18764 sekunder sedanOut 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.
- nola-a - 28938 sekunder sedanFor more insights on Git, check out https://github.com/nolasoft/okgit
- guilhermeasper - 21414 sekunder sedanThese 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).
- md224 - 14647 sekunder sedanThe 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?
- yonatan8070 - 21034 sekunder sedanMy 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.
- traceroute66 - 34516 sekunder sedan> 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.
- mikaoelitiana - 21653 sekunder sedanI created a small TUI based on the article https://github.com/mikaoelitiana/git-audit
- siva7 - 8919 sekunder sedanThanks. What a great Skill for my Claude
- baquero - 27672 sekunder sedanI put it into a gist :)
https://gist.github.com/aeimer/8edc0b25f3197c0986d3f2618f036...
- - 32834 sekunder sedan
- ML0037 - 8495 sekunder sedani’ll try to use the in an hook and test them with Claude. Thank you !
- progx - 15924 sekunder sedanBefore, I ask AI "is this project maintained" done.
- xyst - 2773 sekunder sedanmight 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.
- aa-jv - 33158 sekunder sedanGreat tips, added to notes.txt for future use ..
Another one I do, is:
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.$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 ... - therealdeal2020 - 25515 sekunder sedansuperficial. 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
- aidenn0 - 20789 sekunder sedanWhat's the subversion equivalents to these commands?
- tom-blk - 25644 sekunder sedanNice! Will probably adopt this, seems to give a great overview!
- drob518 - 15198 sekunder sedanNice timing. I was just today needing some of the info that these commands surface. Serendipitous!
- heliumtera - 16722 sekunder sedanSo you value more rushed descriptions of changes than actual changes. Nice
- jayd16 - 19368 sekunder sedanNo 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.
- gpvos - 6398 sekunder sedanAh yes, good old
I use it often.|sort |uniq -c |sort -nr |head -20 - kittikitti - 12367 sekunder sedanThis is a great list of commands to quickly understand a repository. Thank you for sharing.
- jlarocco - 13510 sekunder sedanI'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.
- user20251219 - 29168 sekunder sedanthank you - these are useful
- boxed - 32071 sekunder sedanJust 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?
- atlgator - 20038 sekunder sedanStep 6: grep the thread count on the squash-merge debate to determine if the team has unresolved interpersonal conflict.
- - 22198 sekunder sedan
- yieldcrv - 22226 sekunder sedanblog posts are just comments that would have been torn apart if only posted on a forum, now masquerading as important universal edicts
- stackedinserter - 23247 sekunder sedanThis should be renamed to "Git commands that I run as a new hire to get metrics I'll forget on day 2".
- TacticalCoder - 24114 sekunder sedan> 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.
- lpribis - 28318 sekunder sedanI 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?).
Bus factor: obviously none. The top 4186 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
Buggy files: Intel comes out on top of GPU drivers this time (twice). Along with KVM for x86(64), the main allocator, and BTRFS.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
*GCC*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.cMost changed files: IR autovectorization code, riscv heuristics tables, and C++ template handling (pt.c is "paramaterized types").
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.152 gcc/tree-vect-stmts.cc 145 gcc/config/riscv/riscv.cc 131 gcc/tree-vect-loop.cc 116 gcc/cp/pt.cc
*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.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.cThis 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.
Files with bug commits: Very similar distribution to most changed files. Not enough datapoints in this one to draw any big conclusions.3298 Olivier Fourdan 530 Anonymous 319 Xfce Bot 121 Jasper HuijsmansI 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.
- avazhi - 17383 sekunder sedanMore AI slop.
Wtf is happening to this website
- tracerbits - 24868 sekunder sedan[dead]
- T3RMINATED - 33066 sekunder sedan[dead]
- strimoza - 28068 sekunder sedan[dead]
- T3RMINATED - 33171 sekunder sedan[dead]
- youre-wrong3 - 30172 sekunder sedan[flagged]
- yayadarsh - 15444 sekunder sedangit commands I run before reading any code:
git rm -rf .
Nördnytt! 🤓