[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-73262":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":27,"discoverSource":28},73262,"git-who","sinclairtarget\u002Fgit-who","sinclairtarget","Git blame for file trees","",null,"Go",2681,58,7,3,0,2,27.31,"MIT License",false,"master",true,[],"2026-06-12 02:03:11","![logo](.\u002Fassets\u002Fgitwho_logo.svg)\n\n`git-who` is a command-line tool for answering that eternal question:\n\n> _Who wrote this code?!_\n\nUnlike `git blame`, which can tell you who wrote a _line_ of code, `git-who`\ntells you the people responsible for entire components or subsystems in a\ncodebase. You can think of `git-who` sort of like `git blame` but for file\ntrees rather than individual files.\n\n\n![demo](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fc0281f57-374b-4b3a-a21d-8d0262c3e46b)\n\n\n## Demo\nThis README contains comprehensive documentation. For an overview, see [Who\nWill Maintain Vim? A Demo of Git\nWho](https:\u002F\u002Fsinclairtarget.com\u002Fblog\u002F2025\u002F03\u002Fwho-will-maintain-vim-a-demo-of-git-who\u002F).\n\n## Installation\n### Precompiled Binaries\nSee [releases](https:\u002F\u002Fgithub.com\u002Fsinclairtarget\u002Fgit-who\u002Freleases).\n\n### Package Managers\n[![Packaging status](https:\u002F\u002Frepology.org\u002Fbadge\u002Fvertical-allrepos\u002Fgit-who.svg)](https:\u002F\u002Frepology.org\u002Fproject\u002Fgit-who\u002Fversions)\n\n#### Mac OS\n```\n$ brew install git-who\n```\n\n### Docker\nSee the [section on Docker](#using-docker) below.\n\n### go install command\n\nThis method requires that you have Go installed.\n\n```bash\ngo install github.com\u002Fsinclairtarget\u002Fgit-who@latest\n```\n\n### From Source\nBuilding from source requires that you have Go, Ruby, and the `rake` Ruby gem\ninstalled. Note that these are _only_ required when building from source; you\ncan download and run one of the binary releases without installing any of these\ntools.\n\n```\n$ git clone git@github.com:sinclairtarget\u002Fgit-who.git\n$ cd git-who\n$ rake\n$ .\u002Fgit-who --version\n```\n\n## Usage\n_(In the following examples, `git-who` is invoked as `git who`. This will work\nautomatically as long as Git can find `git-who` in your PATH. See the [Git\nAlias](#git-alias) section for more details.)_\n\n`git who` has three subcommands. Each subcommand gives you a different view of\nauthorship in your Git repository.\n\n### The `table` Subcommand\nThe `table` subcommand is the default subcommand. You can invoke it explicitly\nas `git who table` or implicitly just as `git who`.\n\nThe `table` subcommand prints a table summarizing the contributions of every\nauthor who has made commits in the repository:\n\n```\n~\u002Fclones\u002Fcpython$ git who\n┌─────────────────────────────────────────────────────┐\n│Author                            Last Edit   Commits│\n├─────────────────────────────────────────────────────┤\n│Guido van Rossum                  2 mon. ago   11,213│\n│Victor Stinner                    1 week ago    7,193│\n│Fred Drake                        13 yr. ago    5,465│\n│Georg Brandl                      1 year ago    5,294│\n│Benjamin Peterson                 4 mon. ago    4,724│\n│Raymond Hettinger                 1 month ago   4,235│\n│Serhiy Storchaka                  3 days ago    3,366│\n│Antoine Pitrou                    10 mon. ago   3,180│\n│Jack Jansen                       18 yr. ago    2,978│\n│Martin v. Löwis                   9 yr. ago     2,690│\n│...3,026 more...                                     │\n└─────────────────────────────────────────────────────┘\n```\n\nYou can specify a path to filter the results to only commits that\ntouched files under the given path:\n```\n~\u002Frepos\u002Fcpython$ git who Tools\u002F\n┌─────────────────────────────────────────────────────┐\n│Author                            Last Edit   Commits│\n├─────────────────────────────────────────────────────┤\n│Guido van Rossum                  8 mon. ago      820│\n│Barry Warsaw                      1 year ago      279│\n│Martin v. Löwis                   9 yr. ago       242│\n│Victor Stinner                    1 month ago     235│\n│Steve Dower                       1 month ago     228│\n│Jeremy Hylton                     19 yr. ago      178│\n│Mark Shannon                      4 hr. ago       131│\n│Serhiy Storchaka                  2 mon. ago      118│\n│Erlend E. Aasland                 1 week ago      117│\n│Christian Heimes                  2 yr. ago       114│\n│...267 more...                                       │\n└─────────────────────────────────────────────────────┘\n```\n\nYou can also specify a branch name, tag name, or any \"commit-ish\" to\nfilter the results to commits reachable from the specified commit:\n```\n~\u002Fclones\u002Fcpython$ git who v3.7.1\n┌─────────────────────────────────────────────────────┐\n│Author                            Last Edit   Commits│\n├─────────────────────────────────────────────────────┤\n│Guido van Rossum                  6 yr. ago    10,986│\n│Fred Drake                        13 yr. ago    5,465│\n│Georg Brandl                      8 yr. ago     5,291│\n│Benjamin Peterson                 6 yr. ago     4,599│\n│Victor Stinner                    6 yr. ago     4,462│\n│Raymond Hettinger                 6 yr. ago     3,667│\n│Antoine Pitrou                    6 yr. ago     3,149│\n│Jack Jansen                       18 yr. ago    2,978│\n│Martin v. Löwis                   9 yr. ago     2,690│\n│Tim Peters                        10 yr. ago    2,489│\n│...550 more...                                       │\n└─────────────────────────────────────────────────────┘\n```\n\nRevision ranges also work. This shows the commits made after the release\nof 3.10.9 up to the release of 3.11.9:\n```\n~\u002Fclones\u002Fcpython$ git who v3.10.9..v3.11.9\n┌─────────────────────────────────────────────────────┐\n│Author                            Last Edit   Commits│\n├─────────────────────────────────────────────────────┤\n│Miss Islington (bot)              9 mon. ago    2,551│\n│Victor Stinner                    9 mon. ago      367│\n│Serhiy Storchaka                  9 mon. ago      304│\n│Erlend Egeberg Aasland            2 yr. ago       202│\n│Christian Heimes                  2 yr. ago       200│\n│Mark Shannon                      1 year ago      157│\n│Irit Katriel                      10 mon. ago     135│\n│Nikita Sobolev                    10 mon. ago     126│\n│Pablo Galindo Salgado             1 year ago      117│\n│Pablo Galindo                     9 mon. ago       97│\n│...574 more...                                       │\n└─────────────────────────────────────────────────────┘\n```\n\nJust like with `git` itself, when there is ambiguity between a path name\nand a commit-ish, you can use `--` to clarify the distinction. The\nfollowing command will show you contributions to the file or directory\ncalled `foo` even if there is also a branch called `foo` in your repository (or\neven if the file\u002Fdirectory was previously committed but has since been deleted):\n```\n$ git who -- foo\n```\n\n#### Options\nThe `-m`, `-c`, `-l`, and `-f` flags allow you to sort the table by different\nmetrics.\n\nThe `-m` flag sorts the table by the \"Last Edit\" column, showing who\nedited the repository most recently. The `-c` flag sorts the table by first\nedit, so that the authors who committed to the repository earliest are at the\ntop.\n\nThe `-l` flag sorts the table by number of lines modified, adding some more\ncolumns:\n\n```\n$ git who -l\n┌──────────────────────────────────────────────────────────────────────────────┐\n│Author                          Last Edit   Commits   Files        Lines (+\u002F-)│\n├──────────────────────────────────────────────────────────────────────────────┤\n│Guido van Rossum                2 mon. ago   11,213  14,135     1.3m \u002F 793,252│\n│Antoine Pitrou                  10 mon. ago   3,180   3,868  944,685 \u002F 776,587│\n│Jack Jansen                     18 yr. ago    2,978   5,887  836,527 \u002F 691,078│\n│Benjamin Peterson               4 mon. ago    4,724   6,957  690,740 \u002F 781,700│\n│Georg Brandl                    1 year ago    5,294   9,139  644,620 \u002F 640,217│\n│Martin v. Löwis                 9 yr. ago     2,690   4,557  570,632 \u002F 389,794│\n│Victor Stinner                  1 week ago    7,193  11,382  464,474 \u002F 460,396│\n│Brett Cannon                    1 month ago   2,022   2,841  305,631 \u002F 283,178│\n│Serhiy Storchaka                3 days ago    3,366   9,955  335,209 \u002F 208,899│\n│Christian Heimes                1 year ago    1,553   4,191  339,706 \u002F 178,947│\n│...3,022 more...                                                              │\n└──────────────────────────────────────────────────────────────────────────────┘\n```\n\nThe `-f` flag sorts the table by the number of files modified.\n\nThere is also an `-n` option can be used to print more rows. Passing `-n 0`\nprints all rows.\n\nRun `git-who table --help` to see additional options for the `table` subcommand.\n\n### The `tree` Subcommand\nThe `tree` subcommand prints out a file tree showing files in the working tree\njust like [tree](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FTree_(command)). Each node in the\nfile tree is annotated with information showing which author contributed the most\nto files at or under that path.\n\nHere is an example showing contributions to the Python parser. By default,\ncontributions will be measured by number of commits:\n```\n~\u002Frepos\u002Fcpython$ git who tree Parser\u002F\nParser\u002F.........................Guido van Rossum (182)\n├── lexer\u002F......................Pablo Galindo Salgado (5)\n│   ├── buffer.c................Lysandros Nikolaou (1)\n│   ├── buffer.h................Lysandros Nikolaou (1)\n│   ├── lexer.c\n│   ├── lexer.h.................Lysandros Nikolaou (1)\n│   ├── state.c\n│   └── state.h\n├── tokenizer\u002F..................Filipe Laíns (1)\n│   ├── file_tokenizer.c\n│   ├── helpers.c...............Lysandros Nikolaou (1)\n│   ├── helpers.h...............Lysandros Nikolaou (1)\n│   ├── readline_tokenizer.c....Lysandros Nikolaou (1)\n│   ├── string_tokenizer.c......Lysandros Nikolaou (1)\n│   ├── tokenizer.h.............Lysandros Nikolaou (1)\n│   └── utf8_tokenizer.c........Lysandros Nikolaou (1)\n├── Python.asdl.................Benjamin Peterson (14)\n├── action_helpers.c............Pablo Galindo Salgado (6)\n├── asdl.py.....................Benjamin Peterson (7)\n├── asdl_c.py...................Benjamin Peterson (42)\n├── myreadline.c\n├── parser.c....................Pablo Galindo Salgado (34)\n├── peg_api.c...................Lysandros Nikolaou (2)\n├── pegen.c.....................Pablo Galindo (33)\n├── pegen.h.....................Pablo Galindo Salgado (13)\n├── pegen_errors.c..............Pablo Galindo Salgado (16)\n├── string_parser.c.............Victor Stinner (10)\n├── string_parser.h.............Pablo Galindo Salgado (1)\n└── token.c.....................Pablo Galindo Salgado (2)\n```\n\nYou may notice that some files, like `lexer.c`, are not annotated.\nIf a file is not annotated, that is because the author who has\nmost contributed to that file is the same as the author who\nhas most contributed to the directory containing the file. This is\ndone to minimize visual noise.\n\nYou can force `git-who tree` to annotate every file using the `-a`\nflag (for \"all\"). This flag also prints all file paths that\nwere discovered while walking the commit history, including those no\nlonger in the working tree:\n\n```\n~\u002Frepos\u002Fcpython$ git who tree -a Parser\u002F\nParser\u002F.........................Guido van Rossum (182)\n├── lexer\u002F......................Pablo Galindo Salgado (5)\n│   ├── buffer.c................Lysandros Nikolaou (1)\n│   ├── buffer.h................Lysandros Nikolaou (1)\n│   ├── lexer.c.................Pablo Galindo Salgado (4)\n│   ├── lexer.h.................Lysandros Nikolaou (1)\n│   ├── state.c.................Pablo Galindo Salgado (2)\n│   └── state.h.................Pablo Galindo Salgado (1)\n├── pegen\u002F......................Pablo Galindo (30)\n│   ├── parse.c.................Pablo Galindo (16)\n│   ├── parse_string.c..........Pablo Galindo (7)\n│   ├── parse_string.h..........Pablo Galindo (2)\n│   ├── peg_api.c...............Pablo Galindo (3)\n│   ├── pegen.c.................Pablo Galindo (17)\n│   └── pegen.h.................Pablo Galindo (9)\n├── pgen\u002F.......................Pablo Galindo (8)\n│   ├── __init__.py.............Pablo Galindo (2)\n│   ├── __main__.py.............Pablo Galindo (5)\n│   ├── automata.py.............Pablo Galindo (4)\n│   ├── grammar.py..............Pablo Galindo (5)\n│   ├── keywordgen.py...........Pablo Galindo (3)\n│   ├── metaparser.py...........Pablo Galindo (2)\n│   ├── pgen.py.................Pablo Galindo (5)\n│   └── token.py................Pablo Galindo (4)\n├── tokenizer\u002F..................Filipe Laíns (1)\n│   ├── file_tokenizer.c........Filipe Laíns (1)\n│   ├── helpers.c...............Lysandros Nikolaou (1)\n│   ├── helpers.h...............Lysandros Nikolaou (1)\n│   ├── readline_tokenizer.c....Lysandros Nikolaou (1)\n│   ├── string_tokenizer.c......Lysandros Nikolaou (1)\n│   ├── tokenizer.h.............Lysandros Nikolaou (1)\n│   └── utf8_tokenizer.c........Lysandros Nikolaou (1)\n├── .cvsignore..................Martin v. Löwis (1)\n├── Makefile.in.................Guido van Rossum (10)\n├── Python.asdl.................Benjamin Peterson (14)\n├── acceler.c...................Guido van Rossum (17)\n├── action_helpers.c............Pablo Galindo Salgado (6)\n├── asdl.py.....................Benjamin Peterson (7)\n├── asdl_c.py...................Benjamin Peterson (42)\n├── assert.h....................Guido van Rossum (11)\n├── bitset.c....................Guido van Rossum (12)\n├── firstsets.c.................Guido van Rossum (13)\n├── grammar.c...................Guido van Rossum (20)\n...\n```\n(_The above output continues but has been elided for the purposes\nof this README._)\n\nNote that, whether or not the `-a` flag is used, commits that\nedited files not in the working tree will still count toward the total\ndisplayed next to ancestor directories of that file. In the above two examples,\nGuido van Rossum is shown as the overall highest committer to the `Parser\u002F`\ndirectory, though it takes listing the entire tree with the `-a` flag to see\nthat most of his commits were to files that have since been moved or deleted.\n\nLike with the `table` subcommand, you can specify a \"commit-ish\". This\nnext example shows changes to the `Parser\u002F` directory that happened\nafter the 3.10.9 release up to the 3.11.9 release.\n```\n~\u002Fclones\u002Fcpython$ git who tree v3.10.9..v3.11.9 -- Parser\u002F\nParser\u002F.................Pablo Galindo Salgado (52)\n├── Python.asdl.........Batuhan Taskaya (1)\n├── action_helpers.c....Matthieu Dartiailh (1)\n├── asdl_c.py...........Batuhan Taskaya (4)\n├── myreadline.c........Victor Stinner (1)\n├── parser.c\n├── pegen.c\n├── pegen.h\n├── pegen_errors.c......Miss Islington (bot) (8)\n└── string_parser.c.....Miss Islington (bot) (4)\n```\n\nIf a file isn't edited in any of the commits specified by the revision range,\nthen it won't appear in the output of `git who tree`, even if the file is in\nthe working tree. This can make `git who tree` useful for visualizing the\nchanges introduced by a branch.\n\n#### Options\nThe `tree` subcommand, like the `table` subcommand, supports the `-l`, `-f`,\n`-m`, and `-c` flags.\n\nThe `-l` flag will annotate each file tree node with the\nauthor who has added or removed the most lines at that path:\n\n```\n~\u002Frepos\u002Fcpython$ git who tree -l Parser\u002F\nParser\u002F.........................Pablo Galindo (72,917 \u002F 47,102)\n├── lexer\u002F......................Lysandros Nikolaou (1,668 \u002F 0)\n│   ├── buffer.c\n│   ├── buffer.h\n│   ├── lexer.c\n│   ├── lexer.h\n│   ├── state.c\n│   └── state.h.................Pablo Galindo Salgado (1 \u002F 0)\n├── tokenizer\u002F..................Lysandros Nikolaou (1,391 \u002F 0)\n│   ├── file_tokenizer.c\n│   ├── helpers.c\n│   ├── helpers.h\n│   ├── readline_tokenizer.c\n│   ├── string_tokenizer.c\n│   ├── tokenizer.h\n│   └── utf8_tokenizer.c\n├── Python.asdl.................Benjamin Peterson (120 \u002F 122)\n├── action_helpers.c\n├── asdl.py.....................Eli Bendersky (276 \u002F 331)\n├── asdl_c.py...................Victor Stinner (634 \u002F 496)\n├── myreadline.c................Guido van Rossum (365 \u002F 226)\n├── parser.c\n├── peg_api.c...................Victor Stinner (5 \u002F 46)\n├── pegen.c\n├── pegen.h\n├── pegen_errors.c\n├── string_parser.c\n├── string_parser.h\n└── token.c.....................Serhiy Storchaka (233 \u002F 0)\n```\n\nThe `-f` flag will pick authors based on number of files edited. The `-m` flag\nwill pick an author based on last modification time while the `-c` flag picks\nthe author who first edited a file.\n\nYou can limit the depth of the tree printed by using the `-d` flag. The depth\nis measured from the current working directory.\n\nThe `-a` flag has already been mentioned.\n\nRun `git who tree --help` to see all options available for the `tree` subcommand.\n\n### The `hist` Subcommand\nThe `hist` subcommand prints out a little bar chart \u002F timeline of commit\nactivity showing the history of contributions to the repository.\n\n```\n~\u002Fclones\u002Fcpython$ git who hist\n1990 ┤ #                                     Guido van Rossum (105)\n1991 ┤ ##                                    Guido van Rossum (445)\n1992 ┤ ###                                   Guido van Rossum (606)\n1993 ┤ #-                                    Guido van Rossum (200)\n1994 ┤ ###                                   Guido van Rossum (525)\n1995 ┤ ####-                                 Guido van Rossum (869)\n1996 ┤ ####---                               Guido van Rossum (961)\n1997 ┤ #######--                             Guido van Rossum (1,626)\n1998 ┤ #####------                           Guido van Rossum (1,205)\n1999 ┤ ###-----                              Fred Drake (755)\n2000 ┤ ####------------                      Fred Drake (973)\n2001 ┤ #####-----------------                Fred Drake (1,196)\n2002 ┤ ###--------------                     Guido van Rossum (543)\n2003 ┤ ##------------                        Raymond Hettinger (479)\n2004 ┤ ##--------                            Raymond Hettinger (460)\n2005 ┤ #----                                 Raymond Hettinger (171)\n2006 ┤ ###-------------                      Neal Norwitz (636)\n2007 ┤ ####------------                      Guido van Rossum (792)\n2008 ┤ ####--------------------              Georg Brandl (1,005)\n2009 ┤ #####-----------------------          Benjamin Peterson (1,107)\n2010 ┤ #####-------------------------------  Georg Brandl (1,088)\n2011 ┤ ####-----------------                 Victor Stinner (877)\n2012 ┤ ##------------------                  Antoine Pitrou (466)\n2013 ┤ ###--------------                     Victor Stinner (570)\n2014 ┤ ###----------                         Victor Stinner (594)\n2015 ┤ ###---------                          Victor Stinner (529)\n2016 ┤ ##-----------                         Victor Stinner (497)\n2017 ┤ ##--------                            Victor Stinner (404)\n2018 ┤ ##--------                            Victor Stinner (306)\n2019 ┤ ##----------                          Victor Stinner (467)\n2020 ┤ ###---------                          Victor Stinner (524)\n2021 ┤ ##----------                          Victor Stinner (260)\n2022 ┤ ##-------------                       Victor Stinner (366)\n2023 ┤ ###---------------                    Victor Stinner (556)\n2024 ┤ ##-----------------                   Serhiy Storchaka (321)\n2025 ┤ #                                     Bénédikt Tran (27)\n```\n\n(Git was only released in 2005, so clearly there has been some version control\nmetadata imported from another tool!)\n\nThe timeline shows the author who made the most commits in each year. The bar\nin the bar chart shows their contributions as a proportion of the total\ncontributions made in that year. (The `#` symbol shows the proportion\nof total commits by the \"winning\" author for that year.)\n\nLike with the other subcommands, you can filter the commits examined to just\nthose editing files under a given path:\n\n```\n~\u002Frepos\u002Fcpython$ git who hist iOS\u002F\nFeb 2024 ┤ #                                     Russell Keith-Magee (1)\nMar 2024 ┤ ####                                  Russell Keith-Magee (4)\nApr 2024 ┤ #-                                    Xie Yanbo (1)\nMay 2024 ┤\nJun 2024 ┤\nJul 2024 ┤ #                                     Russell Keith-Magee (1)\nAug 2024 ┤ ##                                    Russell Keith-Magee (2)\nSep 2024 ┤ #                                     Russell Keith-Magee (1)\nOct 2024 ┤\nNov 2024 ┤ #                                     Russell Keith-Magee (1)\nDec 2024 ┤ ###-                                  Russell Keith-Magee (3)\nJan 2025 ┤\n```\nThe printed timeline will begin with the date of the first commit modifying\nthat path.\n\nYou can also filter using a commit-ish. This shows the timeline of contributions\nsince Python's 3.12 release.\n```\n~\u002Fclones\u002Fcpython$ git who hist v3.12.0..\nMay 2023 ┤ ###---------                          Victor Stinner (28)\nJun 2023 ┤ #######--------------------           Victor Stinner (90)\nJul 2023 ┤ ######----------------------------    Victor Stinner (78)\nAug 2023 ┤ #######-------------------------      Victor Stinner (91)\nSep 2023 ┤ ############----------------------    Victor Stinner (157)\nOct 2023 ┤ #####---------------------------      Victor Stinner (68)\nNov 2023 ┤ ###---------------------              Serhiy Storchaka (40)\nDec 2023 ┤ ###-----------------------            Alex Waygood (32)\nJan 2024 ┤ ####-----------------------------     Serhiy Storchaka (43)\nFeb 2024 ┤ ####------------------------------    Serhiy Storchaka (42)\nMar 2024 ┤ #####---------------------------      Victor Stinner (59)\nApr 2024 ┤ ###---------------------------        Serhiy Storchaka (37)\nMay 2024 ┤ ##----------------------------------  Serhiy Storchaka (26)\nJun 2024 ┤ ####------------------------          Victor Stinner (48)\nJul 2024 ┤ ###------------------------           Sam Gross (32)\nAug 2024 ┤ ##-------------------                 Mark Shannon (24)\nSep 2024 ┤ ##---------------------------         Serhiy Storchaka (23)\nOct 2024 ┤ ###----------------------------       Victor Stinner (39)\nNov 2024 ┤ ##-----------------------             Serhiy Storchaka (27)\nDec 2024 ┤ ##------------------                  Bénédikt Tran (18)\nJan 2025 ┤ ##---------                           Bénédikt Tran (26)\n```\n\n#### Options\nThe `hist` subcommand supports the `-l` and `-f` flags but not the `-m` or `-c`\nflags:\n\n```\n~\u002Frepos\u002Fcpython$ git who hist -l iOS\u002F\nFeb 2024 ┤ ###############                       Russell Keith-Magee (406 \u002F 0)\nMar 2024 ┤ ####################################  Russell Keith-Magee (994 \u002F 32)\nApr 2024 ┤ #                                     Xie Yanbo (2 \u002F 2)\nMay 2024 ┤\nJun 2024 ┤\nJul 2024 ┤ #                                     Russell Keith-Magee (1 \u002F 1)\nAug 2024 ┤ #                                     Russell Keith-Magee (2 \u002F 0)\nSep 2024 ┤ #                                     Russell Keith-Magee (6 \u002F 0)\nOct 2024 ┤\nNov 2024 ┤ #####                                 Russell Keith-Magee (104 \u002F 28)\nDec 2024 ┤ ##################-                   Russell Keith-Magee (444 \u002F 52)\nJan 2025 ┤\n```\n\nRun `git who hist --help` for a full listing of the options supported by the\n`hist` subcommand.\n\n### Additional Options for Filtering Commits\nAll of the `git who` subcommands take these additional options that further\nfilter the commits that get counted.\n\nThe `--author` and `--nauthor` options allow you to specify authors to include\nor exclude. Both options can be specified multiple times to include or exclude\nmultiple authors.\n\nThe `--since` and `--until` options allow you to filter out commits before or\nafter a certain date respectively. These options each take a string that gets\npassed to `git log` to be interpreted. `git log` can handle some surprising\ninputs. See git-commit(1) for a description of what is possible.\n\nThe following example shows the paths edited by Guido van Rossum over the last\neight months:\n```\n~\u002Frepos\u002Fcpython$ git who tree -d 1 --since \"nine months ago\" --author \"Guido van Rossum\"\n.\u002F..................Guido van Rossum (11)\n├── .github\u002F........Guido van Rossum (2)\n├── Doc\u002F............Guido van Rossum (3)\n├── Include\u002F........Guido van Rossum (3)\n├── Lib\u002F............Guido van Rossum (1)\n├── Modules\u002F........Guido van Rossum (1)\n├── Objects\u002F........Guido van Rossum (1)\n├── PCbuild\u002F........Guido van Rossum (2)\n├── Programs\u002F.......Guido van Rossum (1)\n├── Python\u002F.........Guido van Rossum (4)\n├── Tools\u002F..........Guido van Rossum (1)\n├── configure\n└── configure.ac\n```\n\nIf you want to filter out all commits under a certain path or using a certain\nextension (i.e. ignore these files), you can do so using Git's \"exclude\"\n[pathspec\nmagic](https:\u002F\u002Fgit-scm.com\u002Fdocs\u002Fgitglossary#Documentation\u002Fgitglossary.txt-aiddefpathspecapathspec).\n\nThe following example counts all files under the `Parser\u002F` directory but\nexcludes `.c` files:\n```\n~\u002Fclones\u002Fcpython$ git who tree -- Parser ':!*.c'\nParser\u002F...................Benjamin Peterson (56)\n├── lexer\u002F................Pablo Galindo Salgado (1)\n│   ├── buffer.h..........Lysandros Nikolaou (1)\n│   ├── lexer.h...........Lysandros Nikolaou (1)\n│   └── state.h\n├── tokenizer\u002F............Lysandros Nikolaou (1)\n│   ├── helpers.h\n│   └── tokenizer.h\n├── Python.asdl\n├── asdl.py\n├── asdl_c.py\n├── pegen.h...............Pablo Galindo Salgado (14)\n└── string_parser.h.......Pablo Galindo Salgado (1)\n```\n\nGit supports other kinds of pathspec magic but the \"exclude\" pathspec magic is\nthe only one supported by `git who`.\n\n## Caching\n`git who` caches data on a per-repository basis under `XDG_CACHE_HOME` (this is\n`~\u002F.cache` if the environment variable is not set).\n\nYou can disable caching by setting `GIT_WHO_DISABLE_CACHE=1`.\n\n## Git Alias\nIf you install the `git-who` binary somewhere in your path, running `git who`\nwill automatically invoke it with no further configuration. This is a Git\nfeature.\n\nIf you install the binary using a different name or just like to be explicit\nyou can configure a Git alias in your global Git config like so:\n\n```\n[alias]\n    who = \"!git-who-executable-name\"\n```\n\nSee [here](https:\u002F\u002Fgit-scm.com\u002Fbook\u002Fen\u002Fv2\u002FGit-Basics-Git-Aliases) for more\ninformation about Git aliases.\n\n## Git Mailmap\nQuite often, people end up committing to a repository under different names or\nusing different email addresses. For example, someone might make a commit using\nthe name \"Nathan Smith\" and their work email address and then later make a\ncommit using the name \"Nate Smith\" and their personal email address.\n\nHow can you make sure that all of someone's commits are counted together\ninstead of being attributed to three or four different people with slightly\ndifferent names?\n\nGit already has a solution for this problem called [Git\nmailmap](https:\u002F\u002Fgit-scm.com\u002Fdocs\u002Fgitmailmap). If a `.mailmap` file is present\nin a Git repository, `git who` will respect it.\n\n## Git Blame Ignore Revs\nIf you have a `.git-blame-ignore-revs` file at the root of your repository,\n`git who` will skip all commits named in that file. The format of the file\nshould be identical to the format of the file expected by the\n`--ignore-revs-file` option of `git blame`.\n\nNote that `git who` will _not_ consult the value of `blame.ignoreRevsFile` in\nyour Git configuration. If there is a file named `.git-blame-ignore-revs` at\nthe root of your repository, `git who` will use it. Otherwise no commits will\nbe skipped.\n\n## Using Docker\nYou can run `git-who` as a Docker container without installing it on your\nsystem directly. Follow these steps to build and use the Docker image.\n\n### Building the Docker Image\nTo build the `git-who` Docker image, run the following command from the project root:\n\n```\ndocker build -t git-who -f docker\u002FDockerfile .\n```\n\nThis will create a Docker image named `git-who` that you can use to run the tool.\n\n### Running `git-who` via Docker\nTo use git-who without modifying your Git configuration, you can manually run:\n\n```\ndocker run --rm -it -v \"$(pwd)\":\u002Fgit -v \"$HOME\":\u002Froot git-who who\n```\n\n- `--rm`: Automatically remove the container after execution.\n- `-it`: Enable interactive mode (for a better experience with CLI tools).\n- `-v \"$(pwd):\u002Fgit\"`: Mounts the current Git repository into the container.\n- `-v \"$HOME:\u002Froot\"`: Ensures that user-specific configurations (e.g., SSH keys, Git settings) are available inside the container.\n\n### Setting Up a Git Alias\nTo make it easier to run `git-who`, you can add an alias to your Git\nconfiguration. Add the following lines to your `~\u002F.gitconfig` file:\n\n```\n[alias]\n    who = !zsh -c \"docker run --rm -it -v$(pwd):\u002Fgit -v$HOME:\u002Froot git-who who $*\"\n```\n\nThis allows you to run:\n\n```\ngit who\n```\n\nfrom any Git repository, and it will invoke git-who through Docker.\n\n## What Exactly Do These Numbers Mean?\n### Metrics\nThe number of **commits** shown for each author is the number of unique commits\nfound while walking the commit log. When supplying a path argument to `git\nwho`, the commits walked include only commits modifying the given path(s).\nHere, the rules described under the HISTORY SIMPLIFICATION section of the Git log\nman page apply—branches in the commit history that do not modify the given path(s)\nare pruned away.\n\nThe number of **files** shown for each author is the number of unique files\nmodified in commits by that author. If a file is renamed, it will count twice.\n\nThe number of **lines added** and **lines removed** shown for each author is\nthe number of lines added and removed to files under the supplied path(s) or to\nall files in the case of no path arguments. In Git, modifying a line counts as\nremoving it and then adding the new version of the line.\n\n### Merge Commits\nMerge commits are not counted toward any of these metrics. The rationale here\nis that merge commits represent a kind of overhead involved in managing the\ncommit graph and that all novel changes will already have been introduced to\nthe commit graph by the merge commit's ancestor commits.\n\nYou can supply the `--merges` flag to `git who` to change this behavior. The\n`--merges` flag forces `git who` to count merge commits toward the commit total\nfor each author. Merge commits are still ignored for the purposes of the file\ntotal or lines total.\n\n### Differences From `git blame`\nWhereas `git blame` starts from the code that exists in the working tree and\nidentifies the commit that introduced each line, `git who` instead walks some\nsubset of the commit log tallying contributions. This means that `git blame`\nand `git who`, in addition to operating on different levels (individual files\nvs file trees), tell you slightly different things.\n\nThis is best illustrated through an example. If Bob has made dozens of commits\nediting a file, but Alice recently formatted the file and made one big commit\nwith her style changes, `git blame` will attribute most of the lines in the\nfile to Alice. `git who`, on the other hand, will rank Bob as the primary\nauthor, at least when sorting by number of commits. In this case, `git who`\nseems better suited to answering the question, \"Who came up with the code in\nthis file?\"\n\nIf instead, Bob made the same commits but Alice came along later and completely\nrefactored the file, again in one big commit, `git blame` will correctly\nattribute most of the lines in the file to her, while `git who` will still list\nBob as the primary author. In this case, `git blame` seems to do a better job\nof answering, \"Who came up with the code in this file?\". That said, the various\nsubcommands and options of `git who` can give you the full picture of what has\nhappened here. `git who hist` in particular will show you that Bob was the\nprimary author until Alice took over.\n\nUltimately, neither tool quite answers what we want to know, which is \"Who came\nup with the code in this file?\", perhaps because the question is too ambiguous.\n`git blame` answers, \"Who last modified each line of code in this file?\" and\n`git who` answers, \"Who made the most modifications to this file \u002F this file\ntree?\"\n\n## Logo\nThe logo was designed by [AdrienDSlone](https:\u002F\u002Fgithub.com\u002FAdrienDSlone) and is\navailable under [this Creative\nCommons license](https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby-sa\u002F4.0\u002F).\n","`git-who` 是一个命令行工具，用于识别代码库中整个组件或子系统的责任人。与 `git blame` 只能显示单行代码的作者不同，`git-who` 能够提供文件树级别的责任归属信息，帮助团队更好地理解项目的历史和维护情况。该工具使用 Go 语言编写，支持多种安装方式包括 Homebrew、Docker 和从源码编译等。适用于需要快速了解大型代码库中各部分主要贡献者的场景，如开源项目的维护者分析、团队成员的工作量评估等。","2026-06-11 03:44:46","high_star"]