{"id":15631700,"url":"https://github.com/alessioalex/git-blame","last_synced_at":"2025-07-14T05:35:16.035Z","repository":{"id":17386697,"uuid":"20158841","full_name":"alessioalex/git-blame","owner":"alessioalex","description":"Shelling out to git blame in a streaming Node fashion.","archived":false,"fork":false,"pushed_at":"2017-08-14T03:49:01.000Z","size":19,"stargazers_count":6,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-06T19:51:30.827Z","etag":null,"topics":["blame","git","git-blame","javascript","nodejs"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alessioalex.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-05-25T16:07:58.000Z","updated_at":"2021-12-20T19:57:21.000Z","dependencies_parsed_at":"2022-09-24T15:53:56.186Z","dependency_job_id":null,"html_url":"https://github.com/alessioalex/git-blame","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/alessioalex/git-blame","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessioalex%2Fgit-blame","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessioalex%2Fgit-blame/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessioalex%2Fgit-blame/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessioalex%2Fgit-blame/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alessioalex","download_url":"https://codeload.github.com/alessioalex/git-blame/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessioalex%2Fgit-blame/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265246013,"owners_count":23734109,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blame","git","git-blame","javascript","nodejs"],"created_at":"2024-10-03T10:41:17.418Z","updated_at":"2025-07-14T05:35:16.002Z","avatar_url":"https://github.com/alessioalex.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# git-blame\n\nShelling out to [git blame](http://git-scm.com/docs/git-blame) in a streaming Node fashion.\n\n[![build status](https://secure.travis-ci.org/alessioalex/git-blame.png)](http://travis-ci.org/alessioalex/git-blame)\n\n## Usage\n\n```js\ngitBlame(repoPath, options)\n```\n\nExample:\n\n```js\nvar gitBlame = require('git-blame');\nvar path = require('path');\n\nvar repoPath = path.resolve(process.env.REPO || (__dirname + '/.git'));\nvar file = process.env.FILE || 'package.json';\nvar rev = process.env.REV || 'HEAD';\n\ngitBlame(repoPath, {\n  file: file,\n  rev: rev\n}).on('data', function(type, data) {\n  // type can be 'line' or 'commit'\n  console.log(type, data);\n}).on('error', function(err) {\n  console.error(err.message);\n  process.exit(1);\n}).on('end', function() {\n  console.log('±±±±±±±±±±±±±±±±±±');\n  console.log(\"That's all, folks!\");\n});\n```\n\nSample output:\n\n```bash\n$ REPO=../rails/.git FILE=install.rb node example.js\nline { hash: 'f79f9a74a4b593e8c36d14c43a030b9a12c69255',\n  originalLine: '1',\n  finalLine: '1',\n  content: 'version = ARGV.pop' }\ncommit { hash: 'f79f9a74a4b593e8c36d14c43a030b9a12c69255',\n  author:\n   { name: 'David Heinemeier Hansson',\n     mail: 'david@loudthinking.com',\n     timestamp: 1280178550,\n     tz: '-0500' },\n  committer:\n   { name: 'David Heinemeier Hansson',\n     mail: 'david@loudthinking.com',\n     timestamp: 1280178550,\n     tz: '-0500' },\n  summary: 'Add install script for testing gems locally',\n  filename: 'install.rb' }\nline { hash: 'f79f9a74a4b593e8c36d14c43a030b9a12c69255',\n  originalLine: '2',\n  finalLine: '2',\n  content: '' }\nline { hash: '66258c0e48ed5cf26641a3096272a272611a783c',\n  originalLine: '3',\n  finalLine: '3',\n  content: 'if version.nil?' }\ncommit { hash: '66258c0e48ed5cf26641a3096272a272611a783c',\n  author:\n   { name: 'Tim Raymond',\n     mail: 'xtjraymondx@gmail.com',\n     timestamp: 1357243730,\n     tz: '-0500' },\n  committer:\n   { name: 'Tim Raymond',\n     mail: 'xtjraymondx@gmail.com',\n     timestamp: 1357244064,\n     tz: '-0500' },\n  summary: 'Adding a usage message to install.rb script',\n  previous:\n   { hash: 'a89660947bd5faeef2a741f71f913c352da50cd3',\n     filename: 'install.rb' },\n  filename: 'install.rb' }\nline { hash: '66258c0e48ed5cf26641a3096272a272611a783c',\n  originalLine: '4',\n  finalLine: '4',\n  content: '  puts \"Usage: ruby install.rb version\"' }\nline { hash: '66258c0e48ed5cf26641a3096272a272611a783c',\n  originalLine: '5',\n  finalLine: '5',\n  content: '  exit(64)' }\nline { hash: '66258c0e48ed5cf26641a3096272a272611a783c',\n  originalLine: '6',\n  finalLine: '6',\n  content: 'end' }\nline { hash: '66258c0e48ed5cf26641a3096272a272611a783c',\n  originalLine: '7',\n  finalLine: '7',\n  content: '' }\nline { hash: 'f1637bf2bb00490203503fbd943b73406e043d1d',\n  originalLine: '3',\n  finalLine: '8',\n  content: '%w( activesupport activemodel activerecord actionpack actionmailer railties ).each do |framework|' }\ncommit { hash: 'f1637bf2bb00490203503fbd943b73406e043d1d',\n  author:\n   { name: 'Prem Sichanugrist',\n     mail: 's@sikachu.com',\n     timestamp: 1305488076,\n     tz: '-0400' },\n  committer:\n   { name: 'Prem Sichanugrist',\n     mail: 's@sikachu.com',\n     timestamp: 1331664944,\n     tz: '-0400' },\n  summary: 'Remove Active Resource source files from the repository',\n  previous:\n   { hash: 'a85714a673d2e06b923bd4eba443a3849d332cce',\n     filename: 'install.rb' },\n  filename: 'install.rb' }\nline { hash: 'f79f9a74a4b593e8c36d14c43a030b9a12c69255',\n  originalLine: '4',\n  finalLine: '9',\n  content: '  puts \"Installing #{framework}...\"' }\nline { hash: '2eb89627d844dec2a4ba420ca903bb139b860e43',\n  originalLine: '10',\n  finalLine: '10',\n  content: '  `cd #{framework} \u0026\u0026 gem build #{framework}.gemspec \u0026\u0026 gem install #{framework}-#{version}.gem --no-ri --no-rdoc \u0026\u0026 rm #{framework}-#{version}.gem`' }\ncommit { hash: '2eb89627d844dec2a4ba420ca903bb139b860e43',\n  author:\n   { name: 'Rafael Mendonça França',\n     mail: 'rafaelmfranca@gmail.com',\n     timestamp: 1361803866,\n     tz: '-0300' },\n  committer:\n   { name: 'Rafael Mendonça França',\n     mail: 'rafaelmfranca@gmail.com',\n     timestamp: 1361803909,\n     tz: '-0300' },\n  summary: 'Do not use --local option when installing the gems',\n  previous:\n   { hash: 'c0bc9ce38c6528916f9dd440984a386511e4297d',\n     filename: 'install.rb' },\n  filename: 'install.rb' }\nline { hash: 'f79f9a74a4b593e8c36d14c43a030b9a12c69255',\n  originalLine: '6',\n  finalLine: '11',\n  content: 'end' }\nline { hash: 'f79f9a74a4b593e8c36d14c43a030b9a12c69255',\n  originalLine: '7',\n  finalLine: '12',\n  content: '' }\nline { hash: '2eb89627d844dec2a4ba420ca903bb139b860e43',\n  originalLine: '13',\n  finalLine: '13',\n  content: 'puts \"Installing rails...\"' }\nline { hash: 'f79f9a74a4b593e8c36d14c43a030b9a12c69255',\n  originalLine: '9',\n  finalLine: '14',\n  content: '`gem build rails.gemspec`' }\nline { hash: '2eb89627d844dec2a4ba420ca903bb139b860e43',\n  originalLine: '15',\n  finalLine: '15',\n  content: '`gem install rails-#{version}.gem --no-ri --no-rdoc `' }\nline { hash: '856f13ab053f6b5dfa58d6e6c726d43cc5e73d00',\n  originalLine: '11',\n  finalLine: '16',\n  content: '`rm rails-#{version}.gem`' }\n±±±±±±±±±±±±±±±±±±\nThat's all, folks!\n```\n\n## Options\n\nThe options should be an `object`.\n\n### `rev` (`Boolean` or `String`)\n`\u003crev\u003e` from `git blame`. If empty it will default to `HEAD`. If `false` and `workTree` is set it will use the work tree.\n\n### `workTree` (`String`)\n`--work-tree` from `git`. If empty no work tree will be used. Use full path.\n\n### `ignoreWhitespace` (`Boolean`)\n`-w` from `git blame`.\n\n### `limitLines` (`String`)\n`-L` from `git blame`.\n\n### `detectMoved` (`Boolean` or `Number`)\n`-M` from `git blame`. Requiered for `detectCopy`.\n\n### `detectCopy` (`Boolean` or `Number`)\n`-C` from `git blame`.\n\n### `detectCopyMode` (`String`)\nPossible options:\n* `any` - Look in all files and at all times\n* `created` - Look in files changed in the commit creating the file\n* `default` - Look in the same commit\n\nIf left empty it will default to `default`.\n\n### `file` (`String`)\n`\u003cfile\u003e` in `git blame`.\n\n## gitCommand\n\nThis is an optional 3rd parameter besides the repo path and options.\nIt's the path to the git binary to use (use the one in `PATH` by default).\n\n## Tests\n\n```\nnpm test\n```\n\n## Used by\n\n- [Git Blame VSCode plugin](https://marketplace.visualstudio.com/items?itemName=waderyan.gitblame)\n\n## License\n\n[MIT](http://alessioalex.mit-license.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessioalex%2Fgit-blame","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falessioalex%2Fgit-blame","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessioalex%2Fgit-blame/lists"}