4 ms·
I don't have major pain points with git either (mainly just that rebase merge conflicts can get awful to deal with), but I just love jj and I'm not looking back
by Balinares 1y ago
I don't have major pain points with git either (mainly just that rebase merge conflicts can get awful to deal with), but I just love jj and I'm not looking back.
It turns out there were a lot of things that I was not doing with git because with git it would have been painful.
Now my PRs are split into human-sized commits that each contain a set of changes that make sense together, and I keep moving changes around during development to keep the history tidy, until it's time to send the pull request. If a commit introduces a typo, the typo fix should go into that commit so the typo never happened in the first place and you don't get reviews like "please fix this" and then "oh wait I see you fixed it in a later commit".
And sure, with git you could checkout the faulty commit, amend it, then amend -a and hope no one was looking, and rebase your dev branch onto the amended commit and it will often even work. Or rebase -i, sure -- have fun with it if the typo was 12 commits ago.
So I just never did that because augh.
With jj it's trivial. You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
No more rebase hell. No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually -- jj takes snapshots after every mutation and rolling back is easy. No more squashing on merge to sweep the messy commit history under the carpet. No more juggling index and staged files and stashed files and all that messy business. Everything is just suspiciously straightforward. To think this could have been our lives all along!
And I'm not looking back.
It's not that I dislike git. It's just that I love jj.
- 1718627440 1y ago> Now my PRs are split into human-sized commits that each contain a set of changes that make sense together, and I keep moving changes around during development to keep the history tidy, until it's time to send the pull request. If a commit introduces a typo, the typo fix should go into that commit so the typo never happened in the first place and you don't get reviews like "please fix this" and then "oh wait I see you fixed it in a later commit". That's my workflow in Git. It is sometimes painful, but only because other people don't do that. It is less work, if you use git --fixup=old-commit-hash and then use git rebase --autosquash. The --fixup step can even by automated, by using git-absorb, but this needs to be installed separately. > You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it. That sounds the same in Git? > No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually When do you need to do that? The only case in which I messed up my repo, was when I had a harddrive crash and recovered commits manually from git objects, because the other files were corrupted. > rolling back is easy. Yes, that seams a bit easier, but reflog still exists. > No more squashing on merge to sweep the messy commit history under the carpet. This is just as well a stupid idea in Git and I hate that. This seams to be cultural and is not suggested by the tool itself. > No more juggling index and staged files and stashed files I find these useful, but you can also use Git without them. Just always use commit -a and commit instead of stashing.
- shaftway 1y ago> > You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it. > That sounds the same in Git? I've always struggled with this myself, and would like to update my git knowledge. Can you walk me through the commands to do this? Let's say the commit id is `abcd1234` and it's 5 commits ago. In JJ I'd do this: vim file/with/typo.txt jj squash -into abcd1234 file/with/typo.txt Or if I was feeling more pedantic I'd do: jj edit abcd1234 vim file/with/typo.txt jj edit <<my latest commit ID>>
- 1718627440 1y agoYou have the same two options in Git: vim file/with/typo.txt git add file/with/typo.txt git commit --fixup=abcd1234 git rebase --autosquash -i For some reason I need to pass --interactive/-i, even if I don't actually want it to be interactive. I am not sure if this is just a bug in my Git version or if this is intended. The git commit step can also be replaced with git-absorb, if you have this installed and abcd1234 was the last time you modified these lines. The second approach is this: git rebase -i abcd1234~ # do 's/pick abcd1234/edit abcd1234/' in your editor vim file/with/typo.txt git rebase --continue
- kleyd 1y agoI believe this only works when there are no other uncommitted changes. So you would need to stash after the fixup commit and pop the stash after rebase. Or use autostash.
- 1718627440 1y agoSure, but I don't see that as a big deal. It comes down to the fact that git does (interactive) rebases and some merges in the working tree and not in memory. If it is able to do it in memory, then you also don't need to squash, but it needs a point where it could checkout conflicts, without altering data. If you like it to be automatic, you can always set rebase.autoStash or merge.autoStash. As for effect on the workflow, you can just continue to work and commit and then call autosquash in two weeks, when your about to merge. This also has the benefit, that Git (by default) only alters commits nobody has used yet.