{"id":18005484,"url":"https://github.com/incognito/git-exfiltrator","last_synced_at":"2025-03-26T10:32:07.803Z","repository":{"id":36920304,"uuid":"229474103","full_name":"Incognito/git-exfiltrator","owner":"Incognito","description":"Extract small increments from large changes ","archived":false,"fork":false,"pushed_at":"2022-01-22T12:02:43.000Z","size":29,"stargazers_count":20,"open_issues_count":2,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-07-30T19:24:24.838Z","etag":null,"topics":["branches","git","git-exfiltrator","lean","prs"],"latest_commit_sha":null,"homepage":"","language":"Shell","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/Incognito.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}},"created_at":"2019-12-21T19:33:50.000Z","updated_at":"2022-02-04T18:31:54.000Z","dependencies_parsed_at":"2022-09-12T11:12:22.235Z","dependency_job_id":null,"html_url":"https://github.com/Incognito/git-exfiltrator","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Incognito%2Fgit-exfiltrator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Incognito%2Fgit-exfiltrator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Incognito%2Fgit-exfiltrator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Incognito%2Fgit-exfiltrator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Incognito","download_url":"https://codeload.github.com/Incognito/git-exfiltrator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222138468,"owners_count":16937419,"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":["branches","git","git-exfiltrator","lean","prs"],"created_at":"2024-10-30T00:19:56.035Z","updated_at":"2024-10-30T00:19:56.559Z","avatar_url":"https://github.com/Incognito.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# What is this\n\nA tool to help you when you accidentally wrote too much code in too many places\nin a feature branch. This tool lets you preserve history and break the code\ndown by folders into individual branches. This is really useful for people who\nwork on decoupled component architectures.\n\nIt seems it is a frequent pattern for engineers to get so focused on making\nchanges they often need a way to break it up and release it in smaller chunks\nto make reviews easier for their peers.\n\n# Usage\n\n1. Be sure you have the branch that needs to be broken up checked out\n2. Be sure you are in the project root\n3. Ensure that your branch was not already merged into your project's primary branch (if those changes were already applied, there is nothing to split)\n\n```\nUsage: git-exfiltrator[-h] [-b] against-ref subject-ref pathspec\n   \u003cagainst\u003e The branch you will merge changes into\n   \u003cnew-branch\u003e The branch you want to create\n   \u003cpathspec\u003e the path you wish to split (\"some/path/*\")\n   \u003cbase\u003e (optional) The tool will attempt to auto-detect the common ancestor\n\t  between your branch and the against target. If your branch histories\n          are complicated you can manually provide the original ancestor commit.\n\nBreak a big feature branch into a smaller specific branch with the changes from\none specific folder. Also, preserve your commit history.\n```\n\n# Benefits\n- A late stage fix to development processes (or mindset) which generate massive\n  branches instead of many small ones.\n- Keeping history of work migrated to a new branch.\n- Avoid using primitive cut+paste techniques from one branch to another which\n  remove history and are error prone.\n\n# Known Drawbacks\n- Commit messages will be duplicated into the extracted branch.\n- The user should know how a git-tree works (or have access to someone who\n  does) if there are serious complications.\n- Possibility of introducing multiple root ancestors (unknown if there are practical drawbacks).\n\n# Installation \nYou can install the script using this repo to keep things versioned correctly,\nor you can try and do it the hack way.\n\n## Hacky way: \nCut+paste the script to your home folder and run the bash script whenever you\nwant to use it.\n\n## Supported way:\n1. Clone the repo to your home folder.\n2. Make your `$PATH` envvar able to resolve this script. Once you do, git will\n   understand `git exfiltrate` (without the `-`) anywhere you want to use it. \n3. Then add this repo to your watchlist/subscriptions on GitHub so you know\n   when/if I provide any updates or useful improvements, and you can git-pull\n   the update as needed.\n\n(If someone would like to maintain a `.deb` or `brew` dependency I'd be happy\nto link to it.)\n\n# Example usage\n\nImagine you're faced with a large `feature-branch` and it's making too many\nchanges to too many parts of the code (See \"uses\" below). Consider this trivial\nexample where a feature changes folders `a`, `b`, and `c` inside `feature-branch`.\n\nUsing git-exfiltrate you can extract an entire folder (for example, `b`) into a\nnew branch which will reduce the impact of merging to master, and still\nmaintain a logical commit history.\n\n```\n*   (master)\n|  a/3 | 0\n| *   (feature-branch)\n| |  b/b2 | 1 +\n| |  c/c2 | 1 +\n| * \n|/\n|    a/a1 | 1 +\n|    b/b1 | 1 +\n|    c/c1 | 1 +\n* \n|  a/2 | 1 +\n* \n   a/1 | 1 +\n```\n\nRun git exfiltrate to extract the `b` folder into a new \"extract\" branch:\n\n```\ngit checkout feature-branch\n./git-exfiltrate master feature-branch-extracted \"b/*\"\n```\n\nThe `-extracted` branch will be created with just the contents of `b` from the branch.\n\nNote that the extracted branch has an unrelated history from the original\n`feature-branch`. This means master has all of folder `b`, and a complete\ntimeline of changes related to `b`, but none of the work from `a` or `c` is\nincluded.\n\n```\n*   e01009e  (master)\n|\\\n| * ce4ca64  (feature-branch-extracted)\n| * f3bf092\n* | 4b2ebd6\n|/\n| * d4c374e  (refs/original/refs/heads/feature-branch-extracted, feature-branch)\n| * 4724dbb\n|/\n* 927799f\n* 219e9b2\n```\n\nTypically the next step might be merging the rest of `feature-branch` into\nmaster. Simply `git merge feature-branch` from `master` as you normally would.\n\n\u003e Note: This step is not required to use the tool, and not the only correct way\n\u003e to use the tool. This is simply a common task which users of this tool will\n\u003e perform.\n\n```\n*   078f69a  (master)\n|\\\n| * d4c374e  (refs/original/refs/heads/feature-branch-extracted, feature-branch)\n| * 4724dbb\n* |   e01009e\n|\\ \\\n| * | ce4ca64  (feature-branch-extracted)\n| * | f3bf092\n| |/\n* | 4b2ebd6\n|/\n* 927799f\n* 219e9b2\n```\n\n# Regrets\nI wish I didn't have to create this tool. The reality is that most of this\nindustry is writing massive PRs which are difficult to work with. Changing the\ndefault \"development mindset\" of developers and software managers *globally* is\na hard task. I can't fix the industry with a bash script, but I can fix a git\nbranch.\n\nI hope one day our entire industry (not just some pockets of it) will fully\nembrace and be capable of working only in small incremental changes.\n\nThere was a previous \"Stateless\" version that let you operate on bare repos but\nit proved too unintuitive in practice for a wide audience, so this new version\nrequires that you are checked out on the right branch and in the root folder.\n\nAnd yes, the heart of this program is a 1-liner but the real value here is\ndocumenting how to do that one liner and making it dead-simple to an audience\nwho typically not want to figure it out while needing to deliver more code\nquickly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fincognito%2Fgit-exfiltrator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fincognito%2Fgit-exfiltrator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fincognito%2Fgit-exfiltrator/lists"}