{"id":31035955,"url":"https://github.com/thgossler/markdowngitdiffmarker","last_synced_at":"2026-04-11T17:35:22.254Z","repository":{"id":313424380,"uuid":"1051030184","full_name":"thgossler/MarkdownGitDiffMarker","owner":"thgossler","description":"Highlight changes between two Git commits in a Markdown document.","archived":false,"fork":false,"pushed_at":"2025-09-05T22:56:59.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-14T03:57:10.895Z","etag":null,"topics":["change-marker","cli","cross-platform","dotnet","git","linux","macos","markdown","review","windows"],"latest_commit_sha":null,"homepage":"","language":"C#","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/thgossler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-05T10:31:15.000Z","updated_at":"2025-09-05T22:57:02.000Z","dependencies_parsed_at":"2025-09-06T00:26:51.722Z","dependency_job_id":"c4b5b3b9-4c75-4e71-b573-f587497ee341","html_url":"https://github.com/thgossler/MarkdownGitDiffMarker","commit_stats":null,"previous_names":["thgossler/markdowngitdiffmarker"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/thgossler/MarkdownGitDiffMarker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thgossler%2FMarkdownGitDiffMarker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thgossler%2FMarkdownGitDiffMarker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thgossler%2FMarkdownGitDiffMarker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thgossler%2FMarkdownGitDiffMarker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thgossler","download_url":"https://codeload.github.com/thgossler/MarkdownGitDiffMarker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thgossler%2FMarkdownGitDiffMarker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280080708,"owners_count":26268354,"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-20T02:00:06.978Z","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":["change-marker","cli","cross-platform","dotnet","git","linux","macos","markdown","review","windows"],"created_at":"2025-09-14T03:57:07.330Z","updated_at":"2025-10-20T10:58:47.917Z","avatar_url":"https://github.com/thgossler.png","language":"C#","funding_links":["https://github.com/sponsors/thgossler"],"categories":[],"sub_categories":[],"readme":"﻿﻿\u003cdiv align=\"center\"\u003e\n\n[![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![AGPL License][license-shield]][license-url]\n\n\u003c/div\u003e\n\n\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003eMarkdownGitDiffMarker\u003c/h1\u003e\n\n  \u003cp align=\"center\"\u003e\n    Highlight changes between two Git commits in a Markdown document.\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/thgossler/MarkdownGitDiffMarker/issues\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/thgossler/MarkdownGitDiffMarker/issues\"\u003eRequest Feature\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/thgossler/MarkdownGitDiffMarker#contributing\"\u003eContribute\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/sponsors/thgossler\"\u003eSponsor project\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## About The Project\n\nHighlight Markdown changes between two Git commits (or between your workspace and a commit) by inserting visible change markers directly into the .md files. The tool writes changes in-place and can also remove previously added markers to restore clean Markdown.\n\nNote: This tool operates on files tracked in a Git repository and is cross-platform. It preserves original line endings.\n\n## Features\n\n- Compare working directory with HEAD or a specific commit\n- Compare two commits (source vs target) without considering workspace changes\n- In-place annotation of matched .md files using HTML markers\n  - Generic changes: `\u003cmark\u003e**[CHANGE]**\u003c/mark\u003e` banner\n  - Table-aware: `\u003cmark\u003e**[CHANGE] in table**\u003c/mark\u003e` and cell-level highlights\n  - List-aware: banners and inline marking of bullet/numbered list items\n  - Figure-aware: `\u003cmark\u003e**[CHANGE] in figure**\u003c/mark\u003e` with OLD/NEW previews for image lines\n  - Additions wrapped as `\u003cmark\u003e...\u003c/mark\u003e` and deletions wrapped as `\u003cmark\u003e~~...~~\u003c/mark\u003e`\n- Cleanup mode to remove all previously added markers and restore plain Markdown\n- Supports simple glob patterns (e.g., `README.md`, `docs/*.md`, `docs/**/*.md`)\n- Respects Git commit-ish forms like `HEAD`, `HEAD~1`, and full/short hashes\n\n## How it works (high level)\n\n- For the selected files, the tool resolves content from the chosen Git commit(s) using LibGit2Sharp.\n- It removes any existing markers from the new content to avoid compounding.\n- It computes a unified diff using the local Git CLI (`git diff --no-index --unified=0`).\n- It applies intelligent, Markdown-aware wrappers to changed lines and emits context-specific banners.\n- It overwrites the file(s) on disk with the annotated content.\n\n## Requirements / Dependencies\n\n- .NET SDK 9.0 or later\n- Git CLI available on PATH (the tool invokes `git diff`). On Windows, common locations are probed as a fallback.\n- A Git repository (files must reside within a repo).\n- NuGet packages (restored during build):\n  - LibGit2Sharp (0.30.0)\n  - System.CommandLine (2.0.0-beta4.22272.1)\n\n## Safety notes\n\n- Files are modified in place. Commit or back up your work before running.\n- Only `.md` files are processed; non-Markdown files matched by the pattern are skipped.\n\n## Build\n\n- Restore and build:\n  - `dotnet build`\n\nOptionally publish a self-contained or single-file binary for your OS/arch if desired.\n\n## Run\n\nRun from the repository root (or any directory within the repo). The `-f/--file` option is required and accepts simple glob patterns.\n\nSynopsis:\n\n- Compare workspace with HEAD:\n  - `dotnet run -- -f \"docs/**/*.md\"`\n- Compare workspace with a specific commit:\n  - `dotnet run -- -s \u003csourceCommit\u003e -f README.md`\n- Compare two commits (overwrite working file with annotated target content):\n  - `dotnet run -- -s \u003csourceCommit\u003e -t \u003ctargetCommit\u003e -f \"docs/*.md\"`\n- Remove previously added markers:\n  - `dotnet run -- -r -f \"docs/**/*.md\"`\n\n### PowerShell helper scripts\n\n- Run.ps1\n  - Use this script to start the program without rebuilding. It forwards all arguments, so you can pass them naturally.\n  - Examples:\n    - `./Run.ps1 --help`\n    - `./Run.ps1 -f \"docs/**/*.md\"`\n- RevertLastCommit.ps1\n  - Use this script to undo the last Git commit by creating a new revert commit and pushing it to `origin` (you will be prompted to confirm).\n  - Internally runs: `git revert HEAD --no-edit` followed by `git push origin HEAD`.\n\n### Intended workflow\n\n1. Commit all changes to the Markdown document.\n2. Run the tool to add change markers to the Markdown document (e.g., `./Run.ps1 -f README.md`).\n3. Commit the Markdown document with change markers (for review).\n4. Generate PDF with change markers. --\u003e this is the whole point of the tool!\n5. Collect review comments on PDF.\n6. Revert the last commit to remove the change markers again (e.g., `./RevertLastCommit.ps1`).\n7. Incorporate the review feedback into the Markdown document.\n8. Commit the final Markdown document (release).\n\nOptions (from source):\n\n- `-f, --file \u003cpattern\u003e`\n  - Glob pattern for Markdown files to process (e.g., `README.md`, `docs/*.md`, `docs/**/*.md`). Required.\n- `-s, --source-git-hash \u003chash-or-commitish\u003e`\n  - Source commit (e.g., `HEAD`, `HEAD~1`, short/full hash). Optional.\n- `-t, --target-git-hash \u003chash-or-commitish\u003e`\n  - Target commit. Only valid when `--source-git-hash` is also provided.\n\nValid usage patterns:\n\n- File pattern only: compare workspace with `HEAD`.\n- `-s` + file pattern: compare workspace with the specified source commit.\n- `-s` + `-t` + file pattern: compare two commits (workspace ignored). The annotated result for the target commit is written to the working file.\n\n## Pattern/Path behavior\n\n- Relative or absolute paths are accepted. Patterns are matched starting from the current directory unless an absolute path is provided.\n- `**` performs a recursive search from the given base path segment.\n- Only files ending in `.md` are processed.\n\n## Markers and cleanup\n\nExamples of emitted markers:\n\n- Generic change banner: `\u003cmark\u003e**[CHANGE]**\u003c/mark\u003e`\n- Table banner: `\u003cmark\u003e**[CHANGE] in table**\u003c/mark\u003e` (with cell-level `\u003cmark\u003e...\u003c/mark\u003e`/`\u003cmark\u003e~~...~~\u003c/mark\u003e`)\n- Figure banner: `\u003cmark\u003e**[CHANGE] in figure**\u003c/mark\u003e` with `OLD:`/`NEW:` previews\n- Inline additions: `\u003cmark\u003etext\u003c/mark\u003e`\n- Inline deletions: `\u003cmark\u003e~~text~~\u003c/mark\u003e`\n\n## Examples\n\n- Compare workspace with HEAD for a single file:\n  - `dotnet run -- -f README.md`\n- Compare workspace with a previous commit for docs tree:\n  - `dotnet run -- -s HEAD~1 -f \"docs/**/*.md\"`\n- Compare two specific commits for a file:\n  - `dotnet run -- -s a1b2c3d -t d4e5f6a -f \"docs/guide.md\"`\n\n## Troubleshooting\n\n- \"No files found matching pattern\": Verify the pattern and quoting in your shell.\n- \"No Git repository found\": Run inside a Git repo or point to files that are inside one.\n- \"Invalid or non-existent Git hash\": Use valid commit-ish (e.g., `HEAD`, `HEAD~2`, full/short SHA).\n- Nothing happens: Ensure Git is installed and available on PATH. The tool uses `git diff --no-index` under the hood.\n\n\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag \"enhancement\".\nDon't forget to give the project a star :wink: Thanks!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n\n## License\n\nDistributed under the MIT License. See [`LICENSE`](LICENSE.txt) for more information.\n\n\n\u003c!-- MARKDOWN LINKS \u0026 IMAGES (https://www.markdownguide.org/basic-syntax/#reference-style-links) --\u003e\n[contributors-shield]: https://img.shields.io/github/contributors/thgossler/MarkdownGitDiffMarker.svg\n[contributors-url]: https://github.com/thgossler/MarkdownGitDiffMarker/graphs/contributors\n[forks-shield]: https://img.shields.io/github/forks/thgossler/MarkdownGitDiffMarker.svg\n[forks-url]: https://github.com/thgossler/MarkdownGitDiffMarker/network/members\n[stars-shield]: https://img.shields.io/github/stars/thgossler/MarkdownGitDiffMarker.svg\n[stars-url]: https://github.com/thgossler/MarkdownGitDiffMarker/stargazers\n[issues-shield]: https://img.shields.io/github/issues/thgossler/MarkdownGitDiffMarker.svg\n[issues-url]: https://github.com/thgossler/MarkdownGitDiffMarker/issues\n[license-shield]: https://img.shields.io/github/license/thgossler/MarkdownGitDiffMarker.svg\n[license-url]: https://github.com/thgossler/MarkdownGitDiffMarker/blob/main/LICENSE.txt\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthgossler%2Fmarkdowngitdiffmarker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthgossler%2Fmarkdowngitdiffmarker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthgossler%2Fmarkdowngitdiffmarker/lists"}