Git RFC: Introduce jj-inspired git-history(1) command for easy history editing
73 points by jo3_l
73 points by jo3_l
As a heavy user of git rebase
, this patch series looks very promising! Dropping and reordering commits in a rebase is easy enough, but splitting commits is a bit more involved and I often just don’t do it due to the additional friction. The proposed git history split
command, modelled after jj split
, is thus quite exciting.
Also, although I’m already using the excellent git-absorb tool, I’d be very happy to see jj absorb
or similar built in. (To be clear, this patch series doesn’t implement absorb-like functionality; it’s just mentioned as a potential extension.)
I can recommend git revise for local history editing. It has git revise --cut
for splitting a commit. It lets you interactively select or edit hunks. The hunk-editing feature leaves some user friendliness to be desired, but is actually just an underlying git command.
I love the idea behind git-revise but I stopped using it unfortunately due to the lack of support for --update-refs
(https://github.com/mystor/git-revise/issues/25 / https://github.com/mystor/git-revise/issues/131) and some incompatibilities out of the box with Emacs magit (https://magit.vc/).
It seems it does not keep up with Git upstreams.
Seeing this RFC to take some good parts of jj, I wonder if git-rebase should not take the good parts of git-revise (avoiding touching files on disk unnecessarily).
I also wonder if this RFC for git-history does it, e.g. split should not touch file on disk.
Finally, magit could take inspiration from jj, and have this operations available in the log view directly.
I’ve added things like that out of desperation to my own branch of git-revise:
anordal/git-revise/rebasehappy-integration-tryout
It has both --cut -- <file>
and does --update-refs
implicitly in interactive mode (so I don’t need to forget; you can always opt out interactively).
This is of course in the hope to upstream some of this. Unfortunately, pull requests to git-revise appears to have stalled the last few years. Mystor, are you reading this?
Should I fork git-revise? Or give up and embrace jj?
Yes, avoiding touching files is something other tools desperately need to learn: I’m usually already compiling by the time I want to reorganize my commits. Can any other tool do that?
One reason reorganizing history is so easy in jj is the deferred conflict resolution, so putting things in the order you want is separate from resolving the conflicts you introduced by doing it. I haven’t fully digested this proposal but it seems like it may be just a semi-automated rebase -i
where you have to fix the conflicts immediately.
I agree; jj split
would be a much lesser feature if not for deferred conflict resolution.
I haven’t fully digested this proposal but it seems like it may be just a semi-automated rebase -i where you have to fix the conflicts immediately.
I believe you’re right about this. From the author:
Note: This patch series currently builds on the cherry-pick infra. As such, when one hits a merge conflict one needs to
git cherry-pick --continue
, which is quite suboptimal.
Since this feature is layered on top of cherry-pick
, which also requires a clean working tree, I don’t think its ergonomics will complete with jj split
’s.
Being sub-commands to history
also make these changes feel less first class, like jj’s. Part of git CLI’s ergonomic problems stem from functionality feeling hidden. Top-level commands communicate a lot about idiomatic/blessed workflows to users.
With that said, I’m happy to see these very nice jj features being considered in git. I think many users will welcome them, regardless of what the final form may be.
A nice split
would be great to have. If the other commands are just an alternative to running rebase -i
and spending a few seconds moving lines around in the editor, I actually prefer the ergonomics of doing it that way (which is why I mainly use jjui
).
Why “namespace” these commands. Almost every command in git is working with history. Namespaces can make sense in some cases like git bisect
because it is a group of commands that work in the same workflow. but the “history” word in these commands is adding no value. It would be better to just pick shorter names.
Not an add! 😇
For all history editing lovers, check this app out: https://github.com/git-up/GitUp It’s mac only, but is massively inspiring! Can’t live without it tbh.
My dream is to port it to the native git cli instead of gitkit; and support other platforms 🙏
The code is super gnarly though. I love Gitup and couldn’t live without it but now I use gg most of the time for a similar experience.
I was a huge GitUp user for about 5 years but haven’t touched it since I switched to jj. This is my first time hearing of gg but it seems quite similar. jj is also very mercurial-influenced.
magit honestly does everything I could want and more. Although JJ seems nice, I wish pijul got more love. The only thing stopping me from using pijul more is: poor nix support (while I would be fine patching nix for it, I don’t want to force that burden onto others) and lack of an emacs major mode for it. Hopefully one day!
You’re in a bit of luck: this week I got nix-prefetch-pijul
merged as a step in the better support direction.
In your experience (and without invoking “flake support”—that ship ain’t budging), what is missing for better Pijul support in Nix if we have fetchpijul
in nixpkgs.lib
? In the other direction, I would love it if @pmeunier ’s team would decouple the HTTP server so users could fetch non-Nest code over basic HTTP instead of SSH (without needing to erect an entire code forge), which would help with fetching from Nix but isn’t a Nix issue.
That’s awesome! Last I talked to someone they mentioned there was a “no more fetchers” policy currently but that doesn’t appear to be true (at least not entirely?). I personally find the ergonomics of fetching like that in a flake a pain but I understand it may be necessary. I think having fetchpijul
would be enough for me to be willing to give it a shot! Of course, there wouldn’t be a magit equivalent, but that isn’t a deal breaker.
It depends how we look at this… First & obviously, we have pkgs.fetchpijul
right now which works today, but a) requires Nixpkgs, b) isn’t a builtin. Secondly, there is fetchTree
to replace some of what the separate fetchers in Nix where doing in a unified way (& seem to be the approach behind the now-unmaintained nix-plugin-pijul
). This means a new fetchTree
type = "pijul"
could be added & upstreamed that wouldn’t be a new fetcher—as I think the explosion of fetchers became a maintenance burden, especially when you start making special carve-outs for the likes of gitlab:
, srht:
, & all others which rightfully invites a why not X? response (so hindsight, don’t make such carve-outs & try to stay more agnostic in design as a rule of thumb). If these things are true, I think one could write & upstream the fetchTree
type based on nix-plugin-pijul
if they had some C++ skills.
Prefetchers are a different store being a part of Nixpkgs & should mostly aid in getting the data for pkgs.fetch*
. These little scripts are used & can be hooked into with their stdout which either a string or JSON depending on complexity that can be piped to other tools. Also being a part of Nixpkgs, it isn’t subject to the “no more fetcher” rules for Nix.