Readit News logoReadit News
martinvonz commented on Awesome-Jj: Jujutsu Things   github.com/Necior/awesome... · Posted by u/n3t
1718627440 · 2 months ago
> `git reset` by itself doesn't split a commit AFAIK.

Git reset splits a single commit, into two "things", another commit with the first part and a second part that is put into a version prepared for a commit (--soft), prepared for further editing (--mixed) or thrown away (--hard). To me that counts as commit splitting, but it may not match with JJ terms. Also splitting into two commits with the same commit message doesn't sound quite useful to me, so the default of Git two require a second commit message is sensible to me.

> Those were rhetorical questions.

Ok, but then what was your point?

martinvonz · 2 months ago
> To me that counts as commit splitting

Correct me I'm I'm wrong but I think were talking about using `git reset HEAD^` for splitting a commit. That will move the current branch backwards one step. With `--mixed`, it will also move the index back one step, so the index is empty (relative to HEAD) and the working copy has the combination of changes that were in the previous HEAD commit and the working copy (relative to the previous HEAD). I think that's more like squashing than splitting because we have fewer "things" after: we have one commit fewer (the previous HEAD commit may of course still be reachable from another branch, in which case we still have the same number of "things" afterwards). It's similar with `--soft` and `--hard`, except that the old changes end up in a different "thing".

At a less technical level, the point of splitting a commit is to end up with some of the changes from one commit in a new commit and the rest of the changes in another commit. That's what meant when I said "`git reset` by itself doesn't split a commit", because you need to do something like this:

  git reset HEAD^
  git add -p
  git commit -C HEAD@{1}
> Ok, but then what was your point?

Just that additional steps are needed.

For example, if you wanted to split the HEAD commit but you had already started working on a new commit so have some changes in the working copy, then you might instead have to do something like this:

  git commit -m tmp
  git rebase -i HEAD^^ # Use the "edit" action for the first commit
  git add -p
  git commit -m first
  git rebase --continue
  git reset HEAD^
The other case I mentioned was if you want to split a commit on another branch. Then you have to insert some additional commands in that sequence. As I said, I know how to do this with Git. I just find it easier to do with jj, where it's `jj split -r xyz` to split commit xyz, whether it's the current working copy, an ancestor commit, or on an unrelated branch.

(Take my Git commands with a grain of salt because I haven't used Git in 10 years.)

martinvonz commented on Awesome-Jj: Jujutsu Things   github.com/Necior/awesome... · Posted by u/n3t
1718627440 · 2 months ago
> `git reset` by itself doesn't split a commit AFAIK. You need to then `git add -p` and `git commit`

If you want to generate two commits with the exact same message, then do:

    git checkout combined-commit
    git reset --soft previous-version
    git commit -C @
> And what happens if you had other changes in the working copy first?

Do something with them. Put them in a commit, put them into a commit in the global stack of todo commits or tell git to do that automatically.

> Or if you want to split a commit that's not at HEAD?

Check it out or do a rebase.

martinvonz · 2 months ago
Those were rhetorical questions. I know how to use Git. Sorry that I was unclear.
martinvonz commented on Awesome-Jj: Jujutsu Things   github.com/Necior/awesome... · Posted by u/n3t
1718627440 · 2 months ago
Sounds like "git reset" to me. Not sure, if it is, but this sounds to be easier in git.
martinvonz · 2 months ago
I have used both Git and jj. I find it easier in jj.

`git reset` by itself doesn't split a commit AFAIK. You need to then `git add -p` and `git commit` (and recover the commit message from the old commit). And what happens if you had other changes in the working copy first? Or if you want to split a commit that's not at HEAD?

martinvonz commented on Awesome-Jj: Jujutsu Things   github.com/Necior/awesome... · Posted by u/n3t
tinodb · 2 months ago
The work needed for the “I included something in a commit I want split out” [0] seems really complex, and it is something I do often.

Eg with stacked git (stg) this is just: goto, spill, and then refresh/create the stuff I want.

[0] https://docs.jj-vcs.dev/latest/faq/#i-accidentally-changed-f...

martinvonz · 2 months ago
You can do that with just `jj split` too. The FAQ entry you linked to is for when you accidentally amended a commit and now you want to restore the bookmark to the old commit and move the changes you amended into a new commit on top instead.
martinvonz commented on Using Git add -p for fun (and profit)   techne98.com/blog/using-g... · Posted by u/fixedprog
y-curious · 2 months ago
It runs on the last commit with the idea that it will all be squashed at merge. Are you worried about reverting some commits but not all?
martinvonz · 2 months ago
That depends on the forge and the configuration of the forge. See the parent of the comment you replied to. Not everyone uses squash merge.
martinvonz commented on Stacked Diffs with git rebase —onto   dineshpandiyan.com/blog/s... · Posted by u/flexdinesh
wakawaka28 · 2 months ago
Amending a commit behind HEAD is not a simple thing in general. You can have conflicts. When it can be done simply, it can be done in 2 steps with git (or less than 2, since you can amend lots of commits with one rebase). What are the 2 steps? After adding what you want, here they are:

- `git commit --fixup HEAD~3`

- `git rebase --autosquash HEAD~4`

The "less than 2 steps" part comes from fixing up more than one commit having no conflicts before the rebase. It is very common to want to stop or run test scripts at various points in the newly modified history, and rebase can trivially help you automate that (but only if you want).

Rebasing literally just does a sequence of steps in the order you specify. You can make those steps complicated, or not, without learning yet another tool. The complexity that is in the rebase tool is practically all necessary.

After using git for many years, I realize now that a lot of thought went into its design. The way it works, especially with the rebase tool, is superior to having a dozen single-purpose tools.

I don't think this particular thing is against the UNIX philosophy either. All of these operations are intimately related just like the operations that a FTP client might do. I can just imagine someone like you looking at FTP or rsync, and saying "This can be 20 different commands! Why don't they make my particular use case into its own command!" There is a place for that kind of logic, but all of the things jj supporters have proposed to me are way too niche to have their own separate commands. My commit edits are complicated, and `git rebase` makes them super simple.

martinvonz · 2 months ago
Maybe you know this already but it's `jj squash --into @----` whether there are conflicts or not.
martinvonz commented on Stacked Diffs with git rebase —onto   dineshpandiyan.com/blog/s... · Posted by u/flexdinesh
wakawaka28 · 2 months ago
Sounds like jj just simplifies the interface of some git commands, mainly. After talking to some jj enthusiasts here, I think we just have a different perspective about what needs to be simple and even what constitutes simple. There is probably some lingering unfamiliarity with git among jj enthusiasts as well. I don't want to teach git to people who are not programmers, but I wouldn't want to teach any programmer's VCS to them honestly. If you are a programmer, I think git is the best.
martinvonz · 2 months ago
> There is probably some lingering unfamiliarity with git among jj enthusiasts as well.

I've heard this a few times. But from what I've seen, it seems like often it's the Git enthusiasts who seem to be unfamiliar with jj. I haven't heard from anyone who used jj for a few months and knew it well and then switched to Git.

martinvonz commented on Stacked Diffs with git rebase —onto   dineshpandiyan.com/blog/s... · Posted by u/flexdinesh
1718627440 · 2 months ago
I think this is generally only useful, if these branches don't need any other change for updating the ancestor. When they need than you need to work on the branch anyway and rebase other commits or add new ones on top, so you gain nothing compared to "rebase --onto" for each branch separately.

If you don't have anything to update then that would be somewhat pointless to me. You can also just rebase them, when you start working on the branch again or want to merge them.

--

For me branches also represent features, that should have clear boundaries, so when I work on one feature and that means, I need to rebase another one on top instead of being able to just merge them later, this indicates a spaghetti codebase where the interfaces between features are not properly defined and things depend on internals of other things.

martinvonz · 2 months ago
Let's say you have this (modified from `git rebase --help`):

``` A---B---C main \ D---E---F feature1 \ \---G---H feature2 \ \---I---J feature3 ```

(sorry about the formatting here. I guess you'll have to copy & paste it to read it)

What I'm saying is that if I want to fix something in D, I do `jj new D` to create a new commit on top of D. Then I make the fix, run tests, etc., and then I run `jj squash` to amend the changes into D. The descendant commits (E through J) then get automatically rebased and the feature bookmarks/branches get updated.

I didn't follow what you about it other changes needed for updating the ancestor. Can you explain in the context of this example?

martinvonz commented on Stacked Diffs with git rebase —onto   dineshpandiyan.com/blog/s... · Posted by u/flexdinesh
feelamee · 2 months ago
isnt jj undo the equivalent of git reflog (+ reset/checkout)?
martinvonz · 2 months ago
Mostly, yes. It also covers changes to the working copy (because jj automatically snapshots changes in the working copy). It's also much easier to use, especially when many refs were updated together. But, to be fair, it's kind of hard to update many refs at once with Git in the first place (there's `git rebase --update-refs` but not much else?), so undoing multiple ref-updates is not as relevant there.
martinvonz commented on Stacked Diffs with git rebase —onto   dineshpandiyan.com/blog/s... · Posted by u/flexdinesh
1718627440 · 2 months ago
I can't comment on the UX of jj, but with git you literally just specify the commit, it doesn't feels tedious to me.

> Also git has no equivalent to the operation log.

For easy cases it's just git reset @{1}, but sure the oplog is a cool thing. I think it will be just added to git eventually, it can't be that hard.

martinvonz · 2 months ago
You can specify a commit, yes, but how do you remember your set of unnamed commits? Once HEAD no longer points to a commit, it will not show up in `git log`.

I agree that Git could gain an operation log. I haven't thought much about it but it feels like it could be done in a backwards-compatible way. It sounds like a ton of work, though, especially if it's going to be a transition from having the current ref storage be the source of truth to making the operation log the source of truth.

u/martinvonz

KarmaCake day312November 15, 2021
About
My name is Martin von Zweigbergk. I work on source control at Google. github.com/martinvonz
View Original