{"id":24746752,"url":"https://github.com/kraymer/ublame","last_synced_at":"2025-10-10T16:30:41.242Z","repository":{"id":43112559,"uuid":"309814319","full_name":"Kraymer/ublame","owner":"Kraymer","description":"Add some depth to 'git blame'!","archived":false,"fork":false,"pushed_at":"2023-01-11T21:17:11.000Z","size":148,"stargazers_count":9,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-22T23:22:30.125Z","etag":null,"topics":["git-blame"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kraymer.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"ko_fi":"kraymer"}},"created_at":"2020-11-03T21:43:37.000Z","updated_at":"2023-01-26T14:39:15.000Z","dependencies_parsed_at":"2023-02-09T07:01:12.007Z","dependency_job_id":null,"html_url":"https://github.com/Kraymer/ublame","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Kraymer/ublame","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kraymer%2Fublame","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kraymer%2Fublame/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kraymer%2Fublame/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kraymer%2Fublame/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kraymer","download_url":"https://codeload.github.com/Kraymer/ublame/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kraymer%2Fublame/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279004706,"owners_count":26083750,"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","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["git-blame"],"created_at":"2025-01-28T04:33:03.825Z","updated_at":"2025-10-10T16:30:40.784Z","avatar_url":"https://github.com/Kraymer.png","language":"Python","funding_links":["https://ko-fi.com/kraymer"],"categories":[],"sub_categories":[],"readme":".. image:: https://coveralls.io/repos/github/Kraymer/ublame/badge.svg?branch=main\n   :target: https://coveralls.io/github/Kraymer/ublame\n.. image:: https://img.shields.io/pypi/v/ublame.svg\n   :target: https://pypi.python.org/pypi/ublame\n.. image:: https://pepy.tech/badge/ublame  \n   :target: https://pepy.tech/project/ublame\n\nUblame\n======\n\n.. image:: https://github.com/Kraymer/__pub/raw/master/ublame.jpg\n\n*Artist's rendering of the bathyscaphe Trieste -- britannica.com*\n\n    **/ˈublaːm(ə)/** :\n\n    | ``git blame``\\ with some depth.  \n    | Portmanteau word from : \n    | 1. *u-boat*: anglicised version of the German word U-Boot that refers to any submarine  \n    | 2. *blame*: git command that annotate each line in a given file with information from the revision which last modified the line.\n\nInstall\n-------\n\nUblame is written for Python 3.6+ and is tested on Linux.\n\nInstall with pip via ``pip3 install ublame`` command.\n\nWhy\n---\n\n``ublame`` is born from the frustration of using ``git blame`` to track the successive editors of a code segment.  \nIt performs a search on a file commits history and reports all the revisions that contain searched term in their diffs.\n\nSee SO question `Git blame — prior commits? \u003chttps://stackoverflow.com/questions/5098256/git-blame-prior-commits/\u003e`_\n\n.. figure:: https://raw.githubusercontent.com/Kraymer/ublame/main/docs/ublame_why.png\n\nExample\n-------\n\nThe last modification is not always the information you need when you\ntry to grasp a piece of code.\n\n::\n\n    ❯ git blame tests/rsrc/example.py | grep \"if token in diff\"\n\n    e65d24b3 (Fabrice Laporte 2020-11-04 21:51:32 +0100  8)     if token in diff:\n\n    ❯ git show e65d24b3\n    commit e65d24b336570822d33f91847542743969b17fa2 (HEAD -\u003e main)\n    Author: Fabrice Laporte\n    Date:   Wed Nov 4 21:51:32 2020 +0100\n\n        chore: convert tabs to spaces\n\nIn that example, the last commit modified the code only to convert tabs\nto spaces and previous commits that were probably more interesting to\nget the original intention of the developer(s) are not captured by\n``git blame``. So you need to apply ``git blame`` on the version of the\nfile preceding *e65d24b3* and so on ...\n\nWith ``ublame`` the information is instantly available in one command :\n\n::\n\n    ❯ ublame tests/rsrc/example.py \"if token in diff\"\n\n    Commit: e65d24b336570822d33f91847542743969b17fa2\n    Author: Fabrice Laporte\n    Date: 2020-11-04 22:12:33+01:00\n\n        chore: convert tabs to spaces\n\n     def trim_diff(diff, token):\n    -       \"\"\"Keep only context surrounding searched token.\n    -       \"\"\"\n    -       if token in diff:\n    -               LOC_BEFORE = LOC_AFTER = 3\n    -       lines = diff.split(\"\\n\")\n\n    Commit: 01c5f3e2a91bcffbb5bdb24cac20d76f98b33db4\n    Author: Fabrice Laporte \u003cfabrice@yescapa.com\u003e\n    Date: 2020-11-04 22:12:30+01:00\n\n        tests: add example.py\n\n    +def trim_diff(diff, token):\n    +       \"\"\"Keep only context surrounding searched token.\n    +       \"\"\"\n    +       if token in diff:\n    +               LOC_BEFORE = LOC_AFTER = 3\n    +       lines = diff.split(\"\\n\")\n\nScreenshot\n----------\n\n.. figure:: https://raw.githubusercontent.com/Kraymer/ublame/main/docs/ublame_screenshot.png\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkraymer%2Fublame","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkraymer%2Fublame","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkraymer%2Fublame/lists"}