Wow, this scratches a lot of my itches about Git. I teach a Git course at my alma mater, and the things that confuses people the most (the index, how to undo mistakes etc etc) all seem addressed head-on. At first glance, this seems substantially easier to teach than Git.
The Git compat seems like a great idea for this to really take off. My team is totally PR based though so if/when doing (Git compatible) feature branches lands in JJ I'm excited to switch.
While I agree that git could use a rethink from a user tooling perspective, I really appreciate the existence of the index. I’m not tied necessarily to this specific implementation of it, but having a staging area where chunks are added piecemeal is an enormous benefit.
I honestly wish git forced `-p` for operations that support it. I’ve worked on too many teams where people would just commit everything in their working directory, and it would inevitably make reviewing their PRs a nightmare. Particularly with times where changes were accidentally committed wholesale that shouldn’t have been part of that set of changes.
> just commit everything in their working directory
But that's what they've tested. I've had far more problems in the other direction, where the commit doesn't contain the complete set of things that it's supposed to but because all the tooling - every single IDE and compiler - is looking at the working directory not the index, I've missed something.
The index is definitely confusing for new users and users of other VCS.
> having a staging area where chunks are added piecemeal is an enormous benefit.
It would be quite fun if we could have hierarchical commits, so I could add bits to a commit without having to squash/amend. Then you'd see the top-level work item as a "commit" and the individual changes as "subcommits".
> It would be quite fun if we could have hierarchical commits, so I could add bits to a commit without having to squash/amend.
Yes! I've been saying this for years.
Branch merge commits are already this, kind of. However their UI sucks and there's an idea gap which prevents them from being fully understood as such "supercommits" composed of subcommits.
For one, the user should be forced to give meaningful, high level commit messages for merge commits and the tooling should fold commits made on a merge branch into the merge commit by default (effectively linearizing the merged history).
>> hierarchical commits, so I could add bits to a commit without having to squash/amend.
> Branch merge commits are already this, kind of. However their UI sucks and there's an idea gap which prevents them from being fully understood as such "supercommits" composed of subcommits.
Isn't that "idea gap" mainly the fault of all these weird newfangled git workflows that discourage or outright forbid branching? If you have no branches to merge, you can't have a merge commit to act as a "supercommit".
Call your "supercommit" a "feature", and what you need to implement it is... A feature branch.
The history graph not presented as a list but as a collapsible tree, sounds good! Might need a change in merge commit message culture though, or more: in the workflows I have experienced, the best time for writing the message you'd see on the collapsed presentation would be branch time, not merge.
Ideally you'd have a data model that keeps a "what is this" description for branches that can be updated as long as the branch lives and that gets moved to the commit message on merge. Could this be done with some combination of convention and hooks? I guess a file in the root that is always kept on target/into branch state, with the lost file content of the source/from branch moved to the commit message would be all that's needed?
Like I said, I’m not sold on git’s specific implementation. But breaking things into smaller, focused commits is—in my experience—a hallmark of good development practice.
There should absolutely be better tooling around it, so that these piecemeal commits can be tested in isolation from one another. That’s a far better approach than just throwing up our hands and committing everything in the working tree, even if half of it has nothing to do with what’s intended.
How do you even end up in that situation? If you start a new feature or bugfix having random local changes lying around, you are _already_ doing it wrong. Start a feature branch, do clean commits of the current state, test, push, review, merge.
> It would be quite fun if we could have hierarchical commits, so I could add bits to a commit without having to squash/amend. Then you'd see the top-level work item as a "commit" and the individual changes as "subcommits".
Would something like Mercurial's queues be something what you're looking for?
I'm not opposed to carefully crafting a good commit, I'm opposed to a state-heavy, badly named, inconsistent feature to do it. And if you use any decent git UI (including -p on the CLI), you don't really need it to be that persistent very often. It could just be a list of chunks to select in the "make commit" window, which is of course exactly how most git UIs "make commit" window looks. It's a single step then, no intermediary persistent state (with three names).
JJ seems to workaround this in the other direction, by making the concept of commits and rebases much more lightweight, which i think is a refreshing enough take that I'd like to try it.
> I’ve worked on too many teams where people would just commit everything in their working directory, and it would inevitably make reviewing their PRs a nightmare.
And they always claim to review and clean their commits before pushing, or at least before merging, but never do.
> My team is totally PR based though so if/when doing (Git compatible) feature branches lands in JJ I'm excited to switch.
I'm trying to find the part of the docs that refers to this functionality as missing but I can't -- does jj not have the ability to create, update, pull from, merge branches, etc?
1. Create a fork via GitHub's web UI
2. Clone using the SSH protocol (`jj git clone git@github.com:...`)
3. Make your changes and "commit" (`jj close/commit`)
4. Create a branch pointing to the commit you just created (`jj branch my-feature -r @-`)
5. Push it to your fork (`jj git push`)
So that doesn't seem too onerous, I guess? Maybe the "too many manual steps" are to clean up afterwards. I just tried it in a test repo and deleting the branch from the fork and then `jj git fetch` from there does delete the local branch, but it doesn't abandon the commits, so you need to run `jj abandon` on them if you don't want them anymore.
I don't think skrebbel was saying that the branches are not git-compatible, I think they were just wondering if there is support for branches at all, but I'm not sure. Anyway, there is support for branches. They behave more like Mercurial's "bookmarks" in that they are assumed to have the same name on all remotes. That usually works well, but it gets annoying if there are unrelated branches all called e.g. "fix-formatting" on multiple remotes you pull from. Jujutsu would then tell you that the branch has a conflict because it doesn't know where it's supposed to point. I'll probably add some way of telling `jj git fetch` which branches to import, but I'm not sure yet what the best solution is.
I think a lot of git is overkill for what most people use it for it. It's time for a new tool to do these basic operations push/pull/undo/redo. Branching is helpful, but if you work in a relatively small codebase a tool that did cp -r under the hood would work perfectly 99% of times.
The Git compat seems like a great idea for this to really take off. My team is totally PR based though so if/when doing (Git compatible) feature branches lands in JJ I'm excited to switch.