Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a jj absorb command #170

Closed
martinvonz opened this issue Mar 22, 2022 · 6 comments
Closed

Add a jj absorb command #170

martinvonz opened this issue Mar 22, 2022 · 6 comments
Assignees

Comments

@martinvonz
Copy link
Owner

Description

As suggested by @unrelentingtech in #64, we should have a jj absorb command. There's git absorb, which was inspired by hg absorb. The two are implemented quite differently. Mercurial's is based on weaves, while Git's is based on "commuting" diff hunks. @durin42 tells me weaves are superior. I'd like to understand better what the difference is in practice (i.e. some concrete examples and how they behave with each method). Maybe @quark-zju (the original author of hg absorb) also has some thoughts.

@quark-zju
Copy link
Contributor

I think the superior cases are covered by the tests. If you can port the tests then it's easier to see the differences. Basically weave should behave better when adjacent/context lines are changed.

@martinvonz
Copy link
Owner Author

I can confirm that. Here's a commit created by git absorb:

commit 15d9908f911a5eed7bd4b2a5880f52154eb3dc87 (HEAD -> master)
Author: Martin von Zweigbergk <martinvonz@google.com>
Date:   Tue Mar 22 15:18:42 2022 -0700

    fixup! fourth

diff --git a/file b/file
index 46876d0..48ffd66 100644
--- a/file
+++ b/file
@@ -1,7 +1,7 @@
-a
-b2
-c3
-d4
+a5
+b5
+c5
+d5
 e
 f
 g3

The number on each line is the commit it was added in (e.g. "c3" was added in commit 3, replacing the previous "c*" line). The lines ending in "5" were added in the index. As you can see, all the fixup would move all the edits in the fourth commit instead of spreading the changes out over commits 1-4. It makes sense when you think about how it works, of course. Thanks for explaining.

@martinvonz
Copy link
Owner Author

While not automatic like hg/git absorb, I've found jj move flexible and easy to use, and even more so now that it accepts path arguments. For example, I had some changes in the working copy just now that should go into two different commits. So I ran this:

# Move most changes into the parent
$ jj squash CHANGELOG.md src/commands.rs tests/test_describe_command.rs
# Move remaining changes into the grandparent
$ jj move --to @--

I still think we should have a jj absorb, but I don't miss it as much as would miss hg absorb.

@matts1
Copy link
Collaborator

matts1 commented Nov 16, 2023

For anyone who sorely misses this feature, as a workaround you can install git-absorb and just run "git absorb", then continue using JJ for everything else. It doesn't play well when going branchless though unfortunately :(

@ilyagr
Copy link
Collaborator

ilyagr commented Feb 5, 2024

Some Discord discussions:

Many people express their interest in absorb around https://discord.com/channels/968932220549103686/968932220549103689/1204156637930192927 and link to https://gregoryszorc.com/blog/2018/11/05/absorbing-commit-changes-in-mercurial-4.8/.

I had some vague ideas about absorb on Discord a while ago. Most of those thoughts are about absorbing conflicts or presenting absorbs to users, which may or may not work and can wait until some working version of absorb already exists.

@ilyagr
Copy link
Collaborator

ilyagr commented Feb 7, 2024

I mentioned this on Discord before (TODO: check if it's the above links or more), or maybe in previous discussions, but not here.

I'm still a bit excited about using the conflict resolution machinery for this and/or (maybe) for blame (#2988).

Given

root -> B-> A-> X

we already have machinery that will tell you what becomes conflicted when you rebase X to B. So, I'm thinking that we could split the diff A->X into that part (it would not get absorbed) and the part that doesn't become conflicted (it would be absorbed into either B or an ancestor of A).

If X is already conflicted (or, more interestingly, if X is conflicted and A is not), we'd look at whether rebasing makes the conflict worse.

This might not work as well as weaves right now, but then there's a chance that we could improve absorb and conflict simplification at the same time.

I still need to think about whether this directly applies to having a blame layer.

@yuja yuja self-assigned this Oct 31, 2024
yuja added a commit to yuja/jj that referenced this issue Nov 9, 2024
The destination commits are selected based on annotation, which I think is
basically the same as "hg absorb" (except for handling of consecutive hunks.)
However, we don't compute a full interleaved delta right now, and the hunks are
merged in the same way as "jj squash". This means absorbed hunks might produce
conflicts if no context lines exist. Still I think this is more intuitive than
selecting destination commits based on patch commutativity.

I've left inline comments to the tests where behavior is different from "hg
absorb", but these aren't exhaustively checked.

Closes martinvonz#170
@yuja yuja mentioned this issue Nov 9, 2024
4 tasks
yuja added a commit to yuja/jj that referenced this issue Nov 9, 2024
The destination commits are selected based on annotation, which I think is
basically the same as "hg absorb" (except for handling of consecutive hunks.)
However, we don't compute a full interleaved delta right now, and the hunks are
merged in the same way as "jj squash". This means absorbed hunks might produce
conflicts if no context lines exist. Still I think this is more intuitive than
selecting destination commits based on patch commutativity.

I've left inline comments to the tests where behavior is different from "hg
absorb", but these aren't exhaustively checked.

Closes martinvonz#170
yuja added a commit to yuja/jj that referenced this issue Nov 10, 2024
The destination commits are selected based on annotation, which I think is
basically the same as "hg absorb" (except for handling of consecutive hunks.)
However, we don't compute a full interleaved delta right now, and the hunks are
merged in the same way as "jj squash". This means absorbed hunks might produce
conflicts if no context lines exist. Still I think this is more intuitive than
selecting destination commits based on patch commutativity.

I've left inline comments to the tests where behavior is different from "hg
absorb", but these aren't exhaustively checked.

Closes martinvonz#170
yuja added a commit to yuja/jj that referenced this issue Nov 10, 2024
The destination commits are selected based on annotation, which I think is
basically the same as "hg absorb" (except for handling of consecutive hunks.)
However, we don't compute a full interleaved delta right now, and the hunks are
merged in the same way as "jj squash". This means absorbed hunks might produce
conflicts if no context lines exist. Still I think this is more intuitive than
selecting destination commits based on patch commutativity.

I've left inline comments to the tests where behavior is different from "hg
absorb", but these aren't exhaustively checked.

Closes martinvonz#170
yuja added a commit to yuja/jj that referenced this issue Nov 10, 2024
The destination commits are selected based on annotation, which I think is
basically the same as "hg absorb" (except for handling of consecutive hunks.)
However, we don't compute a full interleaved delta right now, and the hunks are
merged in the same way as "jj squash". This means absorbed hunks might produce
conflicts if no context lines exist. Still I think this is more intuitive than
selecting destination commits based on patch commutativity.

I've left inline comments to the tests where behavior is different from "hg
absorb", but these aren't exhaustively checked.

Closes martinvonz#170
yuja added a commit to yuja/jj that referenced this issue Nov 11, 2024
The destination commits are selected based on annotation, which I think is
basically the same as "hg absorb" (except for handling of consecutive hunks.)
However, we don't compute a full interleaved delta right now, and the hunks are
merged in the same way as "jj squash". This means absorbed hunks might produce
conflicts if no context lines exist. Still I think this is more intuitive than
selecting destination commits based on patch commutativity.

I've left inline comments to the tests where behavior is different from "hg
absorb", but these aren't exhaustively checked.

Closes martinvonz#170
@yuja yuja closed this as completed in ce3436b Nov 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants