{"id":19466767,"url":"https://github.com/zulip/tinglinggit","last_synced_at":"2025-10-07T07:30:31.408Z","repository":{"id":76288277,"uuid":"81593374","full_name":"zulip/TinglingGit","owner":"zulip","description":"This is a tool which helps to avoid introducing merge conflicts for open PR's in a Github repo by creating new PR's which may get merged sooner","archived":false,"fork":false,"pushed_at":"2019-02-23T21:22:40.000Z","size":23,"stargazers_count":10,"open_issues_count":2,"forks_count":7,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-19T22:48:10.903Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/zulip.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,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-02-10T18:21:05.000Z","updated_at":"2023-08-01T22:25:48.000Z","dependencies_parsed_at":"2024-01-23T21:17:11.787Z","dependency_job_id":"0923ad69-67e6-4faa-8fdd-f4bf47432575","html_url":"https://github.com/zulip/TinglingGit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zulip%2FTinglingGit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zulip%2FTinglingGit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zulip%2FTinglingGit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zulip%2FTinglingGit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zulip","download_url":"https://codeload.github.com/zulip/TinglingGit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235600035,"owners_count":19016193,"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":[],"created_at":"2024-11-10T18:30:05.824Z","updated_at":"2025-10-07T07:30:25.980Z","avatar_url":"https://github.com/zulip.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TinglingGit\n\nTinglingGit is a tool for doing large migrations in a codebase without\ncreating merge conflicts.  Large code migrations (e.g. to adjust code\nformatting, rename something that appears a lot, etc.) can often be\ndone with automated tools.  However, it's often painful to do so,\nbecause they can create huge numbers of merge conflicts with\nin-progress work on the project.\n\nTinglingGit solves this problem by allowing a developer to scan all\nthe open pull requests in a codebase to see which files one can\nmigrate without any merge conflict risk (because 0 open PRs touch the\nfile), which ones can be migrated with minimal risk (because the PRs\ntouching them only make tiny changes), and for those files which are\nlikely to create a lot of merge conflicts, which PRs you should try to\nmerge before migrating them.\n\nWith this technique, one can do major migrations on a large codebase\nwith minimal disruption to the rest of the development community.  The\nZulip project has found this tool invaluable for the following\nmigrations of our codebase, in each case with 100-200 open PRs at the\ntime:\n\n* Updating all of our HTML templates to use consistent 4-space\n  indentation.\n* Migrating our Python codebase from using the Python 2 syntax for\n  mypy type annotations to the PEP-484 Python 3 syntax (which requires\n  changing the `def` line of every function).\n\nAs a side effect of how it works, you can also use it to just get a\nlist of open PRs sorted by size of diffstat, which can be useful if\none is trying to prioritize integrating larger PRs.\n\n# How Things Work here\n\nSo When this tool is run from a terminal with prompt sitting in a Git\ntracked directory, this tool starts to look for Github remote upstream\nand fetches stuff from Github and report whether the files in current\ndirectory are being modified in any of the open PR's. Files safe to\nmodify are green but red otherwise.\n\n# To Run the tool\n\n* Clone or download and extract this repository.\n* Open the TinglingGit Directory in terminal and install dependancies.\u003cbr\u003e\n  ` pip install -r requirements.txt `\n* Configure github settings by creating a personal access token at https://github.com/settings/tokens and adding it to tinglinggit.ini. Note that no special scope privileges are required by TinglingGit.\n* Open a terminal to a git tracked directory with upstream setup for remote repo.\n* Run the tool from within the Directory you wanna analyse files for.\u003cbr\u003e\n  ` python /path/to/TinglingGit/analyse-files.py `\n* One may optionally specify a list of PR numbers to exclude from consideration.\u003cbr\u003e\n  ` python /path/to/TinglingGit/analyse-files.py --ignore-pr 3658 4125` will exclude PR 3658 and 4125 from consideration.\n* `--recursive` could be used when TinglingGit should consider all files recursively in current directory.\n* `--selective` can be used to input selected filenames to be classified as safe and unsafe.\u003cbr\u003eNote: `$` will mark end of input.\n* `--safe-rep` can be used to perform repetitive tasks upon different files and commit only changes which are safe with respect to causing merge conflicts to other PR's. The code to handle repetitive task could be placed by developer under execute_task() function.\n* `--rebase-check` can be used while performing repetitive tasks, we can do a rebase over PR's which might get conflicted by changes to a particular file and see if that actually happens and commit or revert the commit accordingly.\n* After tool successfully completes executing files are displayed with green to represent safe and red to represent possible merge conflicts.\n* If we want to list the PR's in increasing order of changes introduced by the PR. Simple do\u003cbr\u003e\n  ` python /path/to/TinglingGit/analyse-files.py --sort-pr`\n* An output of following patter will come at end\u003cbr\u003e\n    [1]: https://github.com/zulip/zulip/pull/3690\u003cbr\u003e\n    [2]: https://github.com/zulip/zulip/pull/2254\u003cbr\u003e\n    [3]: https://github.com/zulip/zulip/pull/3749\u003cbr\u003e\n    [3]: https://github.com/zulip/zulip/pull/1935\u003cbr\u003e\n\n  Here `[number]` means the number of changes introduced in that PR.\n* We can also list Stale issues by using `--stale-issues` as a argument paramater.\u003cbr\u003e\n  ` python /path/to/TinglingGit/analyse-files.py --stale-issues`\n* The date older then which the issues should be considered stale could be specified by using `--older-then` argument.\u003cbr\u003e\n  ` python /path/to/TinglingGit/analyse-files.py --stale-issues --older-then 20170128`\u003cbr\u003e\n  This will list all issues which are updated before 28-01-2017.\n* We can also filter the issues based on labels defined in the repository.\u003cbr\u003e\n  ` python /path/to/TinglingGit/analyse-files.py --stale-issues --labels 'area: tooling'`\n* A combination could be used as follows\u003cbr\u003e\n  ` python /path/to/TinglingGit/analyse-files.py --stale-issues --older-then 20170128 --labels 'area: tooling'`\n\n# Example output\n\nBelow is example final output from running the tool.  The files in the\ntop list are ones where there are no open PRs touching those files.\n\nThey are followed by all the files that do have open PRs touching\nthose files, with the diffstats of the PRs changes to those files.\n\n\n```\n~/zulip/zerver/views$ python ~/TinglingGit/analyse-files.py\nFetching Diffs Completed\nzerver/__init__.py\nzerver/__init__.pyc\nzerver/filters.py\nzerver/logging_handlers.py\nzerver/signals.py\nzerver/static_header.txt\nzerver/storage.py\nzerver/apps.py [PR#5224(+1-1)](https://github.com/zulip/zulip/pull/5224)\nzerver/context_processors.py\n[PR#5753(+1-0)](https://github.com/zulip/zulip/pull/5753)\n[PR#7234(+2-0)](https://github.com/zulip/zulip/pull/7234)\n[PR#7038(+20-0)](https://github.com/zulip/zulip/pull/7038)\nzerver/decorator.py\n[PR#5753(+24-0)](https://github.com/zulip/zulip/pull/5753)\n[PR#5880(+60-39)](https://github.com/zulip/zulip/pull/5880)\n[PR#6086(+21-21)](https://github.com/zulip/zulip/pull/6086)\n[PR#6737(+3-2)](https://github.com/zulip/zulip/pull/6737)\nzerver/forms.py\n[PR#7437(+51-57)](https://github.com/zulip/zulip/pull/7437)\n[PR#5753(+20-0)](https://github.com/zulip/zulip/pull/5753)\n[PR#7027(+3-3)](https://github.com/zulip/zulip/pull/7027)\n[PR#6084(+36-0)](https://github.com/zulip/zulip/pull/6084)\n[PR#6086(+1-1)](https://github.com/zulip/zulip/pull/6086)\nzerver/middleware.py\n[PR#5880(+60-18)](https://github.com/zulip/zulip/pull/5880)\n[PR#7427(+2-0)](https://github.com/zulip/zulip/pull/7427)\n[PR#6086(+2-2)](https://github.com/zulip/zulip/pull/6086)\nzerver/models.py\n[PR#5633(+28-1)](https://github.com/zulip/zulip/pull/5633)\n[PR#4110(+4-4)](https://github.com/zulip/zulip/pull/4110)\n[PR#5665(+20-0)](https://github.com/zulip/zulip/pull/5665)\n[PR#6492(+2-0)](https://github.com/zulip/zulip/pull/6492)\n[PR#6705(+8-0)](https://github.com/zulip/zulip/pull/6705)\n[PR#6199(+8-0)](https://github.com/zulip/zulip/pull/6199)\n[PR#5224(+2-3)](https://github.com/zulip/zulip/pull/5224)...\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzulip%2Ftinglinggit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzulip%2Ftinglinggit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzulip%2Ftinglinggit/lists"}