Collection of Git utilities that can’t be found in vanilla Git or Magit:
git children
- list all child branches of a commit
git graft
- cut & paste an entire subtree of git branches
git pullfetch
- git fetch and pull combo
git split
- split a commit up into 1 commit per file
To get a list of all subcommands, refer to git hly
:
$ git hly No such command: NIL Valid commands: - children - graft - pullfetch - split For in-depth help, pass --help to a subcommand.
git childen REF
Non inclusive, i.e. the output does not include the branch you passed, itself.
For this repo:
A -> B -> master -> C -> D -> origin/master \ --> E -> branch1 -> F -> branch2 \ -----> G -> branch3
This command:
git children master
Will return:
branch1 branch2 branch3
Typical use case: you have a long list of PRs which depend on each other; when origin/master is updated, you want to rebase all of them to the new origin/master. Instead of rebasing each branch individually, you want to “snip” the bottom off the old master, and “glue” it back onto the new one.
git graft ROOT ONTO
ROOT
- the first commit under (and including) which all local branches will be selected.
ONTO
- the commit onto which the subtree will be moved.
This git-graft won’t actually run the commands: it just prints them to stdout. You’re meant to manually copy & paste them to your shell. This is a temporary hack to allow a human to sanity check the results, and it provides rollback.
Once you get comfortable with the tool, you can pipe directly to bash:
git graft ROOT ONTO | bash
This will print undo commands, so in case of trouble you can always rollback.
say after a git fetch, you end up with:
A -> B -> master -> C -> D -> origin/master \ --> E -> branch1 -> F -> branch2 \ -----> G -> branch3
Execute this:
git graft E origin/master
And you will get a bunch of git commands on stdout. Execute them all, and you should end up with:
... -> D -> origin/master -> E -> branch1 -> F -> branch2 \ -----> G -> branch3
Every local branch under (and including) branch1 will be moved, so be careful choosing something like (e.g.) master. It will work if all branches under master are indeed feature branches that you “own”, but if you locally checked out someone else’s branch, it will also be rebased.
Git-graft also prints “undo” commands, commented out. These are not expected to be necessary for normal operation, but if something goes wrong midway through a big graft, you can use those commands to go back to the pre-graft state.
The argument to git-graft, the root, is inclusive. This is at odds with git conventions, where you normally specify a commit’s “parent”, under which all relevant commits are found. The reason is that sometimes, e.g. the example above, choosing the parent can lead to too many branches being included: you’d get origin/master, and all potential other local branches already ported onto it.
When cooperating with others on a busy repo this command helps “pull all changes.” Update master if it’s been updated, purge deleted branches, etc.
Usage:
git pullfetch
Useful for splitting up a convoluted commit as part of a larger rebase workflow.
See https://stackoverflow.com/questions/40698651/how-to-split-every-commit-by-file.
Tip
This is easiest!
Or you can just invoke it directly, like ./git-hly
.
Note
If you don’t know Nix, don’t worry about this. If you do, this is the way to go!
This project is available through Nix.
Old-school Nix:
Install globally:
nix-env -if https://github.com/hraban/git-hly/archive/master.tar.gz
Or just build it in a temporary directory to play around with it:
nix-build https://github.com/hraban/git-hly/archive/master.tar.gz
The binary can be found in ./result/bin/
. Copy it somewhere to your PATH.
Do you use the hip new Nix Flakes? You can install this package in your profile:
nix profile install github:hraban/git-hly
Or you can just run it stand-alone (but it won’t integrate with the top-level git
CLI):
nix run github:hraban/git-hly -- ...
Or you can build it locally and copy the binary out of ./result/bin
to your PATH:
nix build github:hraban/git-hly
If you use these I’m sure you don’t need my help :)
Warning
This is hard, I can’t think of why anybody would want to do this. Good luck.
Building this project natively is complicated and very dependent on your local setup. You need a more recent version of ASDF than comes bundled with SBCL. I recommend loading the project up in SLIME, with a new ASDF version pre-loaded. You can compile it to a binary using (asdf:make "git-hly")
.
git-hly - Hraban’s Git utilities Copyright © 2022–2024 Hraban Luyat
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.