{"id":16088532,"url":"https://github.com/krobelus/git-branchstack","last_synced_at":"2025-04-07T11:07:53.501Z","repository":{"id":46185103,"uuid":"284787052","full_name":"krobelus/git-branchstack","owner":"krobelus","description":"Efficiently manage Git branches without leaving your local branch","archived":false,"fork":false,"pushed_at":"2025-02-07T12:41:58.000Z","size":82,"stargazers_count":53,"open_issues_count":0,"forks_count":2,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-31T10:01:37.765Z","etag":null,"topics":["branchless-workflow","git","patch-management","patch-stack","pull-request"],"latest_commit_sha":null,"homepage":"https://git.sr.ht/~krobelus/git-branchstack","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/krobelus.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2020-08-03T19:18:57.000Z","updated_at":"2025-02-07T12:42:02.000Z","dependencies_parsed_at":"2024-02-01T06:21:35.884Z","dependency_job_id":"b71eddf0-b362-4c41-b3bf-200db640d3cd","html_url":"https://github.com/krobelus/git-branchstack","commit_stats":{"total_commits":131,"total_committers":3,"mean_commits":"43.666666666666664","dds":0.01526717557251911,"last_synced_commit":"bec403403e35471add91e2c5620018ee33d1bd3f"},"previous_names":["krobelus/git-branchless"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krobelus%2Fgit-branchstack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krobelus%2Fgit-branchstack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krobelus%2Fgit-branchstack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krobelus%2Fgit-branchstack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krobelus","download_url":"https://codeload.github.com/krobelus/git-branchstack/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640463,"owners_count":20971557,"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":["branchless-workflow","git","patch-management","patch-stack","pull-request"],"created_at":"2024-10-09T13:36:50.738Z","updated_at":"2025-04-07T11:07:53.478Z","avatar_url":"https://github.com/krobelus.png","language":"Python","readme":"# git branchstack\n\n**NOTE:** This tool has some limitations, some due to incomplete design and\nothers due to practical limitations in current Git implementations. I have\nswitched to using [jj](https://github.com/martinvonz/jj) instead, which\nprovides a cleaner and more powerful solution.\n\n[![PyPi](https://img.shields.io/pypi/v/git-branchstack.svg)](https://pypi.org/project/git-branchstack)\n\n## Motivation\n\nWhen I am working on multiple changes to a [Git] repository, I usually want to\ncombine all of my changes in a single branch, but send them upstream in small,\nreviewable chunks. As stated in [the related articles](#related-articles)\none advantage is that you can base new work on previous changes, and test\nthem in combination.\n\nGit already supports this workflow via [git format-patch] and [git send-email],\nhowever, many projects prefer to receive patches via pull requests.  To make\nproposed changes easy to review, you'll want to submit a separate pull request\nfor each independent change on your worktree's branch.  This means that you\nwant to create branches containing those independent changes and nothing else.\n\n`git branchstack` creates the desired branches without requiring you to switch\nback and forth between branches (and invalidating builds). This allows you\nto submit small pull requests, while enjoying the benefits of a branchless\nworkflow. After making any changes to your worktree's branch you can easily\nupdate the generated branches: just re-run `git branchstack`.\n\n## Installation\n\n### Via pip\n\n```sh\n$ pip install --user git-branchstack\n```\n\nInstead of the last command you can also run [`./git-branchstack`](./git-branchstack) directly, provided you have `git-revise\u003e=0.7.0`.\n\n### Via [pipx](https://pypa.github.io/pipx/)\n\nUse this instead to avoid breakage when your Python installation is upgraded.\n\n```sh\n$ pipx install git-branchstack\n```\n\n## Usage\n\nCreate some commits with commit messages starting with a topic tag `[...]`.\nThe topic name, `\u003ctopic\u003e`, inside the square bracket tag markers `[\u003ctopic\u003e]`,\nmust be an unused valid branch name.  Then run `git branchstack` to create\nthe branch `\u003ctopic\u003e` with the given commits.\n\nFor example, if you have created a commit history like\n\n    $ git log --graph --oneline\n    * 9629a6c (HEAD -\u003e local-branch) [some-unrelated-fix] Unrelated fix\n    * e764f47 [my-awesome-feature] Some more work on feature\n    * a9a811f [my-awesome-feature] Initial support for feature\n    * 28fcf9c Local commit without topic tag\n    * 5fb0776 (master) Initial commit\n\nThen this command will (re)create two branches:\n\n    $ git branchstack\n    $ git log --graph --oneline --all\n    * 9629a6c (HEAD -\u003e local-branch) [some-unrelated-fix] Unrelated fix\n    * e764f47 [my-awesome-feature] Some more work on feature\n    * a9a811f [my-awesome-feature] Initial support for feature\n    * 28fcf9c Local commit without topic tag\n    | * 7d4d166 (my-awesome-feature) Some more work on feature\n    | * fb0941f Initial support for feature\n    |/\n    | * 1a37fd0 (some-unrelated-fix) Unrelated fix\n    |/\n    * 5fb0776 (master) Initial commit\n\nBy default, `git branchstack` looks only at commits in the range\n`@{upstream}..HEAD`.  It ignores commits whose subject does not start with\na topic tag.\n\nCreated branches are based on the common ancestor of your branch and the\nupstream branch, that is, `git merge-base @{upstream} HEAD`.\n\nTo avoid conflicts, you can specify dependencies between branches.\nFor example use `[child:parent1:parent2]` to base `child` off both `parent1`\nand `parent2`. The order of parents does not matter: the one that occurs\nfirst in the commit log will be added first.\n\nPass `--keep-tags` to mark dependency commits by keeping the commits'\ntopic tags. Use `keep-tags=all` to keep all topic tags. To only keep topic\ntags of select dependencies, prefix them with the `+` character (like\n`[child:+parent]`).\n\nIf a commit cannot be applied cleanly, `git branchstack` will show topics\nthat would avoid the conflict if added as dependencies. You can either\nadd the missing dependencies, or resolve the conflict in your editor. You\ncan tell Git to remember your conflict resolution by enabling `git rerere`\n(use `git config rerere.enabled true; git config rerere.autoUpdate true`).\n\nInstead of the default topic tag delimiters (`[` and `]`), you can\nset Git configuration values `branchstack.subjectPrefixPrefix` and\n`branchstack.subjectPrefixSuffix`, respectively.\n\n## Integrating Commits from Other Branches\n\nYou can use [git-branchstack-pick](./git-branchstack-pick) to integrate\nother commit ranges into your branch:\n\n```sh\n$ git branchstack-pick ..some-branch \n```\n\nThis behaves like `git rebase -i` except it prefills the rebase-todo list to\ncherry-pick all missing commits from `some-branch`, prefixing their commit\nsubjects with `[some-branch]`.  Old commits with such a subject are dropped,\nso this allows you to quickly update to the latest upstream version of a\nref that has been force-pushed.\n\nHere's how you would use this to cherry-pick GitHub pull requests:\n\n```sh\n$ git config --add remote.origin.fetch '+refs/pull/*/head:refs/remotes/origin/pr-*'\n$ git fetch origin\n$ git branchstack-pick ..origin/pr-123\n```\n\n## Tips\n\n- You can use [git revise] to efficiently modify your commit messages\n  to contain the `[\u003ctopic\u003e]` tags. This command lets you edit all commit\n  messages in `@{upstream}..HEAD`.\n\n  ```sh\n  $ git revise --interactive --edit\n  ```\n\n  Like `git revise`, you can use `git branchstack` during an interactive rebase.\n\n- [`git-autofixup`](https://github.com/torbiak/git-autofixup/) can eliminate\n  some of the busywork involved in creating fixup commits.\n\n## Related Articles\n\n- In [Stacked Diffs Versus Pull Requests], Jackson Gabbard\n  describes the advantages of a patch-based workflow (using [Phabricator])\n  over the one-branch-per-reviewable-change model; `git branchstack` can be used\n  to implement the first workflow, even when you have to use pull-requests.\n\n- In [My unorthodox, branchless git workflow], Drew\n  DeVault explains some advantages of a similar workflow.\n\n## Peer Projects\n\nWhile `git branchstack` only offers one command and relies on standard Git\ntools for everything else, there are some tools that offer a more comprehensive\nset of commands to achieve a similar workflow:\n\n- [Stacked Git](https://stacked-git.github.io/)\n- [git ps](https://github.com/uptech/git-ps)\n- [gh-stack](https://github.com/timothyandrew/gh-stack)\n- [git machete](https://github.com/VirtusLab/git-machete)\n- [git-stack](https://github.com/epage/git-stack)\n- [depot-tools](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html)\n\nUnlike its peers, `git branchstack` never modifies any worktree files,\nsince it uses `git revise` internally.  This makes it faster, and avoids\ninvalidating builds.\n\n## Contributing\n\nSubmit feedback at \u003chttps://github.com/krobelus/git-branchstack/\u003e or to the\n[public mailing list](https://lists.sr.ht/~krobelus/git-branchless) by\nsending email to \u003cmailto:~krobelus/git-branchless@lists.sr.ht\u003e.\n\n[Git]: \u003chttps://git-scm.com/\u003e\n[git revise]: \u003chttps://github.com/mystor/git-revise/\u003e\n[git format-patch]: \u003chttps://git-scm.com/docs/git-format-patch\u003e\n[git send-email]: \u003chttps://git-send-email.io/\u003e\n[Stacked Diffs Versus Pull Requests]: \u003chttps://jg.gg/2018/09/29/stacked-diffs-versus-pull-requests/\u003e\n[My unorthodox, branchless git workflow]: \u003chttps://drewdevault.com/2020/04/06/My-weird-branchless-git-workflow.html\u003e\n[Phabricator]: \u003chttps://www.phacility.com/\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrobelus%2Fgit-branchstack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrobelus%2Fgit-branchstack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrobelus%2Fgit-branchstack/lists"}