{"id":15686985,"url":"https://github.com/peter-evans/patience","last_synced_at":"2025-06-15T15:35:58.490Z","repository":{"id":42924533,"uuid":"466977212","full_name":"peter-evans/patience","owner":"peter-evans","description":"Go implementation of the Patience Diff algorithm","archived":false,"fork":false,"pushed_at":"2025-05-05T17:12:21.000Z","size":35,"stargazers_count":18,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-07T02:02:01.474Z","etag":null,"topics":["diff","diff-algorithm","go","golang","lcs","line-oriented","longest-common-subsequence","patience","patiencediff","unidiff","unified-diff","unified-format"],"latest_commit_sha":null,"homepage":"","language":"Go","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/peter-evans.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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},"funding":{"github":"peter-evans"}},"created_at":"2022-03-07T06:53:00.000Z","updated_at":"2025-05-05T17:12:19.000Z","dependencies_parsed_at":"2023-12-11T15:30:33.630Z","dependency_job_id":"2ec8aa52-ae5e-42b6-bb21-8a69b8e27275","html_url":"https://github.com/peter-evans/patience","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/peter-evans/patience","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-evans%2Fpatience","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-evans%2Fpatience/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-evans%2Fpatience/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-evans%2Fpatience/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/peter-evans","download_url":"https://codeload.github.com/peter-evans/patience/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-evans%2Fpatience/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259998238,"owners_count":22943778,"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":["diff","diff-algorithm","go","golang","lcs","line-oriented","longest-common-subsequence","patience","patiencediff","unidiff","unified-diff","unified-format"],"created_at":"2024-10-03T17:42:18.693Z","updated_at":"2025-06-15T15:35:58.468Z","avatar_url":"https://github.com/peter-evans.png","language":"Go","readme":"# patience\n\n[![CI](https://github.com/peter-evans/patience/actions/workflows/ci.yml/badge.svg)](https://github.com/peter-evans/patience/actions/workflows/ci.yml)\n[![GoReportCard](https://goreportcard.com/badge/github.com/peter-evans/patience)](https://goreportcard.com/report/github.com/peter-evans/patience)\n[![GoDoc](https://godoc.org/github.com/peter-evans/patience?status.svg)](https://godoc.org/github.com/peter-evans/patience)\n\nGo implementation of the Patience Diff algorithm.\n\nThis library generates line-oriented diffs between source and destination inputs, using the Patience Diff algorithm.\n\n## Features\n\nSupports both plain format and [Unified format](https://en.wikipedia.org/wiki/Diff#Unified_format) (unidiff).\n\nPlain format:\n```diff\n the\n quick\n brown\n-chicken\n+fox\n jumps\n over\n the\n+lazy\n dog\n```\n\nUnified format (unidiff):\n\n```diff\n--- a.txt\n+++ b.txt\n@@ -3,3 +3,3 @@\n brown\n-chicken\n+fox\n jumps\n@@ -7,2 +7,3 @@\n the\n+lazy\n dog\n```\n\n## Installation\n\n```sh\ngo get github.com/peter-evans/patience\n```\n\n## Usage\n\n```go\na := strings.Split(textA, \"\\n\")\nb := strings.Split(textB, \"\\n\")\n\ndiffs := patience.Diff(a, b)\n\n// Combined diff\ndiff := patience.DiffText(diffs)\n\n// Split diffs\ndiffA := patience.DiffTextA(diffs)\ndiffB := patience.DiffTextB(diffs)\n\n// Unified diff\nunidiff := patience.UnifiedDiffText(diffs)\n\n// Unified diff with options\nunidiffopts := patience.UnifiedDiffTextWithOptions(\n     diffs,\n     UnifiedDiffOptions{\n          Precontext: 2, \n          Postcontext: 2,\n          SrcHeader:   \"a.txt\",\n          DstHeader:   \"b.txt\",\n     },\n)\n```\n\n## About\n\nPatience Diff is an algorithm credited to [Bram Cohen](https://bramcohen.livejournal.com/73318.html) that produces diffs tending to be more human-readable than the common diff algorithm.\n\nThe common diff algorithm is based on the [longest common subsequence](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem) problem.\nIt is credited to [Eugene Myers](http://www.xmailserver.org/diff2.pdf) and is the default diff algorithm in Git.\nWhile the diffs generated by this algorithm are efficient, in many cases they tend not to correspond to what humans would naturally identify.\n\nPatience Diff, while also relying on computing the longest common subsequence, takes a different approach. It only computes the longest common subsequence of the *unique*, *common* elements of both texts. This means that lines that are frequently non-unique, such as those containing a single brace or new line character, are ignored. The result is that distinctive lines, such as function declarations, become the anchor points of commonality between the two texts.\n\nThis is an example comparing Patience Diff to the common diff algorithm (Myers).\n\nPatience Diff\n```diff\n #include \u003cstdio.h\u003e\n \n+int fib(int n)\n+{\n+    if(n \u003e 2)\n+    {\n+        return fib(n-1) + fib(n-2);\n+    }\n+    return 1;\n+}\n+\n // Frobs foo heartily\n int frobnitz(int foo)\n {\n     int i;\n     for(i = 0; i \u003c 10; i++)\n     {\n-        printf(\"Your answer is: \");\n         printf(\"%d\\n\", foo);\n     }\n }\n \n-int fact(int n)\n-{\n-    if(n \u003e 1)\n-    {\n-        return fact(n-1) * n;\n-    }\n-    return 1;\n-}\n- \n int main(int argc, char **argv)\n {\n-    frobnitz(fact(10));\n+    frobnitz(fib(10));\n }\n```\n\nCommon diff (Myers)\n```diff\n #include \u003cstdio.h\u003e\n \n-// Frobs foo heartily\n-int frobnitz(int foo)\n+int fib(int n)\n {\n-    int i;\n-    for(i = 0; i \u003c 10; i++)\n+    if(n \u003e 2)\n     {\n-        printf(\"Your answer is: \");\n-        printf(\"%d\\n\", foo);\n+        return fib(n-1) + fib(n-2);\n     }\n+    return 1;\n }\n \n-int fact(int n)\n+// Frobs foo heartily\n+int frobnitz(int foo)\n {\n-    if(n \u003e 1)\n+    int i;\n+    for(i = 0; i \u003c 10; i++)\n     {\n-        return fact(n-1) * n;\n+        printf(\"%d\\n\", foo);\n     }\n-    return 1;\n }\n \n int main(int argc, char **argv)\n {\n-    frobnitz(fact(10));\n+    frobnitz(fib(10));\n }\n```\n\n## References\n\n- [Patience Diff Advantages](https://bramcohen.livejournal.com/73318.html) by Bram Cohen\n- [Patience Diff, a brief summary](https://alfedenzo.livejournal.com/170301.html) by Alfedenzo\n","funding_links":["https://github.com/sponsors/peter-evans"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeter-evans%2Fpatience","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeter-evans%2Fpatience","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeter-evans%2Fpatience/lists"}