Skip to content

Conversation

erjanmx
Copy link
Contributor

@erjanmx erjanmx commented Dec 25, 2020

No description provided.

@martinvonz
Copy link
Member

Thanks!

@martinvonz martinvonz closed this Dec 26, 2020
@martinvonz
Copy link
Member

I've never accepted PRs before. Looks like I chose the wrong button to accept the PR. Sorry. I'll try again.

@martinvonz
Copy link
Member

Hmm, GitHub says that "The repository this pull request was created from has been deleted". I manually fetched the commit and pushed. Sorry about the mess.

ilyagr added a commit that referenced this pull request May 6, 2024
For example, 

```
<<<<<<< Conflict 1 of 3
+++++++ Contents of side #1
left 3.1
left 3.2
left 3.3
%%%%%%% Changes from base to side #2
-line 3
+right 3.1
>>>>>>>
```

or

```
<<<<<<< Conflict 1 of 1
%%%%%%% Changes from base to side #1
-line 3
+right 3.1
+++++++ Contents of side #2
left 3.1
left 3.2
left 3.3
>>>>>>>
```

Currently, there is no way to disable these, this is TODO for a future
PR. Other TODOs for future PRs: make these labels configurable. After
that, we could support a `diff3/git`-like conflict format as well, in
principle.

Counting conflicts helps with knowing whether you fixed all the
conflicts while you are in the editor.

While labeling "side #1", etc, does not tell you the commit id or
description as requested in #1176, I still think it's an improvement.
Most importantly, I hope this will make `jj`'s conflict format less
scary-looking for new users.

I've used this for a bit, and I like it. Without the labels, I would see
that the two conflicts have a different order of conflict markers, but I
wouldn't be able to remember what that means. For longer diffs, it can
be tricky for me to quickly tell that it's a diff as opposed to one of
the sides. This also creates some hope of being able to navigate a
conflict with more than 2 sides.

Another not-so-secret goal for this is explained in
#3109 (comment). The
idea is a little weird, but I *think* it could be helpful, and I'd like
to experiment with it.
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 17, 2024
Adds a new "ui.conflict-marker-style" config option. The "diff" option
is the default jj-style conflict markers with a snapshot and a series of
diffs to apply to the snapshot. New conflict marker style options will
be added in later commits.

The majority of the changes in this commit are from passing the config
option down to the code that materializes the conflicts.

Example of "diff" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
%%%%%%% Changes from base to side jj-vcs#2
-fn example(w: String) {
+fn example(w: &str) {
     println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 17, 2024
Adds a new "snapshot" conflict marker style which returns a series of
snapshots, similar to Git's "diff3" conflict style. The "snapshot"
option uses a subset of the conflict hunk headers as the "diff" option
(it just doesn't use "%%%%%%%"), meaning that the two options are
trivially compatible with each other (i.e. a file materialized with
"snapshot" can be parsed with "diff" and vice versa).

Example of "snapshot" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
------- Contents of base
fn example(w: String) {
    println!("word is {w}");
+++++++ Contents of side jj-vcs#2
fn example(w: &str) {
    println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 17, 2024
Adds a new "ui.conflict-marker-style" config option. The "diff" option
is the default jj-style conflict markers with a snapshot and a series of
diffs to apply to the snapshot. New conflict marker style options will
be added in later commits.

The majority of the changes in this commit are from passing the config
option down to the code that materializes the conflicts.

Example of "diff" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
%%%%%%% Changes from base to side jj-vcs#2
-fn example(w: String) {
+fn example(w: &str) {
     println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 17, 2024
Adds a new "snapshot" conflict marker style which returns a series of
snapshots, similar to Git's "diff3" conflict style. The "snapshot"
option uses a subset of the conflict hunk headers as the "diff" option
(it just doesn't use "%%%%%%%"), meaning that the two options are
trivially compatible with each other (i.e. a file materialized with
"snapshot" can be parsed with "diff" and vice versa).

Example of "snapshot" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
------- Contents of base
fn example(w: String) {
    println!("word is {w}");
+++++++ Contents of side jj-vcs#2
fn example(w: &str) {
    println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 18, 2024
Adds a new "ui.conflict-marker-style" config option. The "diff" option
is the default jj-style conflict markers with a snapshot and a series of
diffs to apply to the snapshot. New conflict marker style options will
be added in later commits.

The majority of the changes in this commit are from passing the config
option down to the code that materializes the conflicts.

Example of "diff" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
%%%%%%% Changes from base to side jj-vcs#2
-fn example(w: String) {
+fn example(w: &str) {
     println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 18, 2024
Adds a new "snapshot" conflict marker style which returns a series of
snapshots, similar to Git's "diff3" conflict style. The "snapshot"
option uses a subset of the conflict hunk headers as the "diff" option
(it just doesn't use "%%%%%%%"), meaning that the two options are
trivially compatible with each other (i.e. a file materialized with
"snapshot" can be parsed with "diff" and vice versa).

Example of "snapshot" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
------- Contents of base
fn example(w: String) {
    println!("word is {w}");
+++++++ Contents of side jj-vcs#2
fn example(w: &str) {
    println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 22, 2024
Adds a new "ui.conflict-marker-style" config option. The "diff" option
is the default jj-style conflict markers with a snapshot and a series of
diffs to apply to the snapshot. New conflict marker style options will
be added in later commits.

The majority of the changes in this commit are from passing the config
option down to the code that materializes the conflicts.

Example of "diff" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
%%%%%%% Changes from base to side jj-vcs#2
-fn example(w: String) {
+fn example(w: &str) {
     println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 22, 2024
Adds a new "snapshot" conflict marker style which returns a series of
snapshots, similar to Git's "diff3" conflict style. The "snapshot"
option uses a subset of the conflict hunk headers as the "diff" option
(it just doesn't use "%%%%%%%"), meaning that the two options are
trivially compatible with each other (i.e. a file materialized with
"snapshot" can be parsed with "diff" and vice versa).

Example of "snapshot" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn example(word: String) {
    println!("word is {word}");
------- Contents of base
fn example(w: String) {
    println!("word is {w}");
+++++++ Contents of side jj-vcs#2
fn example(w: &str) {
    println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 22, 2024
Adds a new "git-diff3" conflict marker style option. This option matches
Git's "diff3" conflict style, allowing these conflicts to be parsed by
some external tools that don't support JJ-style conflicts. If a conflict
has more than 2 sides, then it falls back to the similar "snapshot"
conflict marker style.

The conflict parsing code now supports parsing Git-style conflict
markers in addition to the normal JJ-style conflict markers, regardless
of the conflict marker style setting. This has the benefit of allowing
the user to switch the conflict marker style while they already have
conflicts checked out, and their old conflicts will still be parsed
correctly.

Example of "git-diff3" conflict markers:

```
<<<<<<< Side jj-vcs#1 (Conflict 1 of 1)
fn example(word: String) {
    println!("word is {word}");
||||||| Base
fn example(w: String) {
    println!("word is {w}");
=======
fn example(w: &str) {
    println!("word is {w}");
>>>>>>> Side jj-vcs#2 (Conflict 1 of 1 ends)
}
```
scott2000 added a commit that referenced this pull request Nov 23, 2024
Adds a new "ui.conflict-marker-style" config option. The "diff" option
is the default jj-style conflict markers with a snapshot and a series of
diffs to apply to the snapshot. New conflict marker style options will
be added in later commits.

The majority of the changes in this commit are from passing the config
option down to the code that materializes the conflicts.

Example of "diff" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side #1
fn example(word: String) {
    println!("word is {word}");
%%%%%%% Changes from base to side #2
-fn example(w: String) {
+fn example(w: &str) {
     println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit that referenced this pull request Nov 23, 2024
Adds a new "snapshot" conflict marker style which returns a series of
snapshots, similar to Git's "diff3" conflict style. The "snapshot"
option uses a subset of the conflict hunk headers as the "diff" option
(it just doesn't use "%%%%%%%"), meaning that the two options are
trivially compatible with each other (i.e. a file materialized with
"snapshot" can be parsed with "diff" and vice versa).

Example of "snapshot" conflict markers:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side #1
fn example(word: String) {
    println!("word is {word}");
------- Contents of base
fn example(w: String) {
    println!("word is {w}");
+++++++ Contents of side #2
fn example(w: &str) {
    println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
scott2000 added a commit that referenced this pull request Nov 23, 2024
Adds a new "git" conflict marker style option. This option matches Git's
"diff3" conflict style, allowing these conflicts to be parsed by some
external tools that don't support JJ-style conflicts. If a conflict has
more than 2 sides, then it falls back to the similar "snapshot" conflict
marker style.

The conflict parsing code now supports parsing Git-style conflict
markers in addition to the normal JJ-style conflict markers, regardless
of the conflict marker style setting. This has the benefit of allowing
the user to switch the conflict marker style while they already have
conflicts checked out, and their old conflicts will still be parsed
correctly.

Example of "git" conflict markers:

```
<<<<<<< Side #1 (Conflict 1 of 1)
fn example(word: String) {
    println!("word is {word}");
||||||| Base
fn example(w: String) {
    println!("word is {w}");
=======
fn example(w: &str) {
    println!("word is {w}");
>>>>>>> Side #2 (Conflict 1 of 1 ends)
}
```
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 25, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously. For instance, if we have a file
explaining the differences between Jujutsu's conflict markers and Git's
conflict markers, it could produce a conflict with long markers like
this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends

<<<<<<<
left
=======
right
>>>>>>>
```

We need to allow conflict markers to be longer than strictly necessary,
because imagine that we are in the process of resolving the conflict
shown above, and we remove the example of Git's conflict markers:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends
```

Now, there is no reason for the conflict markers to be longer than 7
characters, since the text which looked like conflict markers has been
removed. We still want this file to be parsed correctly as a conflict
though, so we need to allow markers which are longer than necessary.
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 25, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously. For instance, if we have a file
explaining the differences between Jujutsu's conflict markers and Git's
conflict markers, it could produce a conflict with long markers like
this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends

<<<<<<<
left
=======
right
>>>>>>>
```

We need to allow conflict markers to be longer than strictly necessary,
because imagine that we are in the process of resolving the conflict
shown above, and we remove the example of Git's conflict markers:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends
```

Now, there is no reason for the conflict markers to be longer than 7
characters, since the text which looked like conflict markers has been
removed. We still want this file to be parsed correctly as a conflict
though, so we need to allow markers which are longer than necessary.
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 25, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously. For instance, if we have a file
explaining the differences between Jujutsu's conflict markers and Git's
conflict markers, it could produce a conflict with long markers like
this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends

<<<<<<<
left
=======
right
>>>>>>>
```

We need to allow conflict markers to be longer than strictly necessary,
because imagine that we are in the process of resolving the conflict
shown above, and we remove the example of Git's conflict markers:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends
```

Now, there is no reason for the conflict markers to be longer than 7
characters, since the text which looked like conflict markers has been
removed. We still want this file to be parsed correctly as a conflict
though, so we need to allow markers which are longer than necessary.
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 25, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously. For instance, if we have a file
explaining the differences between Jujutsu's conflict markers and Git's
conflict markers, it could produce a conflict with long markers like
this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends

<<<<<<<
left
=======
right
>>>>>>>
```

We need to allow conflict markers to be longer than strictly necessary,
because imagine that we are in the process of resolving the conflict
shown above, and we remove the example of Git's conflict markers:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends
```

Now, there is no reason for the conflict markers to be longer than 7
characters, since the text which looked like conflict markers has been
removed. We still want this file to be parsed correctly as a conflict
though, so we need to allow markers which are longer than necessary.
scott2000 added a commit to scott2000/jj that referenced this pull request Nov 25, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously. For instance, if we have a file
explaining the differences between Jujutsu's conflict markers and Git's
conflict markers, it could produce a conflict with long markers like
this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends

<<<<<<<
left
=======
right
>>>>>>>
```

We need to allow conflict markers to be longer than strictly necessary,
because imagine that we are in the process of resolving the conflict
shown above, and we remove the example of Git's conflict markers:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
-Git's conflict markers look like this:
+Unlike Jujutsu, Git's conflict markers look like this:
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git, which just shows the
sides of a conflict without a diff:
>>>>>>>>>>> Conflict 1 of 1 ends
```

Now, there is no reason for the conflict markers to be longer than 7
characters, since the text which looked like conflict markers has been
removed. We still want this file to be parsed correctly as a conflict
though, so we need to allow markers which are longer than necessary.
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 16, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.

When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.

For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
 Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git:

<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```

We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:

https://git-scm.com/docs/gitattributes#_conflict_marker_size

We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:

https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 17, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.

When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.

For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
 Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git:

<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```

We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:

https://git-scm.com/docs/gitattributes#_conflict_marker_size

We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:

https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 17, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.

When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.

For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
 Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git:

<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```

We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:

https://git-scm.com/docs/gitattributes#_conflict_marker_size

We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:

https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 19, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.

When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.

For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
 Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git:

<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```

We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:

https://git-scm.com/docs/gitattributes#_conflict_marker_size

We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:

https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 20, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.

When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.

For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
 Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git:

<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```

We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:

https://git-scm.com/docs/gitattributes#_conflict_marker_size

We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:

https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 21, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.

When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.

For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side jj-vcs#1
 Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side jj-vcs#2
Jujutsu uses different conflict markers than Git:

<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```

We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:

https://git-scm.com/docs/gitattributes#_conflict_marker_size

We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:

https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
scott2000 added a commit that referenced this pull request Dec 21, 2024
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.

When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.

For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:

```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side #1
 Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side #2
Jujutsu uses different conflict markers than Git:

<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```

We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:

https://git-scm.com/docs/gitattributes#_conflict_marker_size

We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:

https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 24, 2024
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is the best solution to the problem because it should
remain understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 24, 2024
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is the best solution to the problem because it should
remain understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 24, 2024
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is the best solution to the problem because it should
remain understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 24, 2024
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is a good solution to the problem because it should remain
understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline. Also, adding a newline to every term of the hunk is easier
than keeping track of which terms have added newlines and which don't,
so it makes materialization/parsing easier.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 24, 2024
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is a good solution to the problem because it should remain
understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline. Also, adding a newline to every term of the hunk is easier
than keeping track of which terms have added newlines and which don't,
so it makes materialization/parsing easier.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 25, 2024
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is a good solution to the problem because it should remain
understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline. Also, adding a newline to every term of the hunk is easier
than keeping track of which terms have added newlines and which don't,
so it makes materialization/parsing easier.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Dec 26, 2024
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is a good solution to the problem because it should remain
understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline. Also, adding a newline to every term of the hunk is easier
than keeping track of which terms have added newlines and which don't,
so it makes materialization/parsing easier.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Jan 2, 2025
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is a good solution to the problem because it should remain
understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline. Also, adding a newline to every term of the hunk is easier
than keeping track of which terms have added newlines and which don't,
so it makes materialization/parsing easier.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Jan 16, 2025
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is a good solution to the problem because it should remain
understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline. Also, adding a newline to every term of the hunk is easier
than keeping track of which terms have added newlines and which don't,
so it makes materialization/parsing easier.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
scott2000 added a commit to scott2000/jj that referenced this pull request Jan 25, 2025
Currently, conflict markers are materialized in a format that cannot be
parsed if a conflict appears at the end of the file, and there is a
non-empty line which doesn't end with a newline character. To fix this
issue, we can add an extra newline to every term of the conflict when
this occurs and then ignore the added newlines when parsing the
conflict. To ensure unambiguous parsing, we can add a "[noeol]" tag to
the start conflict marker (`<<<<<<<`) when this occurs.

I think this is a good solution to the problem because it should remain
understandable to users even if they aren't familiar with file
encodings. Many editors represent newlines at the end of files by
showing an empty line at the end of the editor, so it should be
intuitive that a term ending with an empty line represents a newline,
while a term that doesn't end with an empty line represents the lack of
a newline. Also, adding a newline to every term of the hunk is easier
than keeping track of which terms have added newlines and which don't,
so it makes materialization/parsing easier.

For instance, a conflict with terms `["left\n", "base", "base\nright"]`
would look like:

```
<<<<<<< Conflict 1 of 1 [noeol]
+++++++ Contents of side jj-vcs#1
left

%%%%%%% Changes from base to side jj-vcs#2
 base
+right
>>>>>>>
```
ilyagr added a commit that referenced this pull request Mar 27, 2025
With the default config (if global `conflict-marker-style` is not
customized), this reverts the behavior to that before 7f57866.

`vimdiff` config already shows three panes with the three snapshots for
each conflict, so it's helpful to show jj's diff view in the editing
pane.

In other words, previously the conflict was always shown in the
"snapshot" format in the main pane:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side #1
fn has_tracked_remote_bookmarks(view: &View, bookmark: &RefName) -> bool {
------- Contents of base
fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
+++++++ Contents of side #2
pub fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
>>>>>>> Conflict 1 of 1 ends
```

and now it is shown in whatever format the user set as the default. If
the user didn't pick a default, the "diff" format is used in the main
pane:

```
<<<<<<< Conflict 1 of 1
%%%%%%% Changes from base to side #1
-fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
+fn has_tracked_remote_bookmarks(view: &View, bookmark: &RefName) -> bool {
+++++++ Contents of side #2
pub fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
>>>>>>> Conflict 1 of 1 ends
```

See also the screenshot in #6147 to see
the main pane in the context of the three other panes that always
display the snapshots.
github-merge-queue bot pushed a commit that referenced this pull request Mar 27, 2025
With the default config (if global `conflict-marker-style` is not
customized), this reverts the behavior to that before 7f57866.

`vimdiff` config already shows three panes with the three snapshots for
each conflict, so it's helpful to show jj's diff view in the editing
pane.

In other words, previously the conflict was always shown in the
"snapshot" format in the main pane:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side #1
fn has_tracked_remote_bookmarks(view: &View, bookmark: &RefName) -> bool {
------- Contents of base
fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
+++++++ Contents of side #2
pub fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
>>>>>>> Conflict 1 of 1 ends
```

and now it is shown in whatever format the user set as the default. If
the user didn't pick a default, the "diff" format is used in the main
pane:

```
<<<<<<< Conflict 1 of 1
%%%%%%% Changes from base to side #1
-fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
+fn has_tracked_remote_bookmarks(view: &View, bookmark: &RefName) -> bool {
+++++++ Contents of side #2
pub fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
>>>>>>> Conflict 1 of 1 ends
```

See also the screenshot in #6147 to see
the main pane in the context of the three other panes that always
display the snapshots.
kejadlen pushed a commit to kejadlen/jj that referenced this pull request Apr 16, 2025
With the default config (if global `conflict-marker-style` is not
customized), this reverts the behavior to that before 7f57866.

`vimdiff` config already shows three panes with the three snapshots for
each conflict, so it's helpful to show jj's diff view in the editing
pane.

In other words, previously the conflict was always shown in the
"snapshot" format in the main pane:

```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side jj-vcs#1
fn has_tracked_remote_bookmarks(view: &View, bookmark: &RefName) -> bool {
------- Contents of base
fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
+++++++ Contents of side jj-vcs#2
pub fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
>>>>>>> Conflict 1 of 1 ends
```

and now it is shown in whatever format the user set as the default. If
the user didn't pick a default, the "diff" format is used in the main
pane:

```
<<<<<<< Conflict 1 of 1
%%%%%%% Changes from base to side jj-vcs#1
-fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
+fn has_tracked_remote_bookmarks(view: &View, bookmark: &RefName) -> bool {
+++++++ Contents of side jj-vcs#2
pub fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
>>>>>>> Conflict 1 of 1 ends
```

See also the screenshot in jj-vcs#6147 to see
the main pane in the context of the three other panes that always
display the snapshots.
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request May 10, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [martinvonz/jj](https://github.com/martinvonz/jj) | minor | `v0.27.0` -> `v0.29.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>martinvonz/jj (martinvonz/jj)</summary>

### [`v0.29.0`](https://github.com/jj-vcs/jj/releases/tag/v0.29.0)

[Compare Source](jj-vcs/jj@v0.28.2...v0.29.0)

##### About

jj is a Git-compatible version control system that is both simple and powerful. See the [installation instructions](https://jj-vcs.github.io/jj/v0.29.0/install-and-setup/) to get started.

##### Release highlights

-   Experimental support for transferring the change ID to/from Git remotes behind configuration
    setting `git.write-change-id-header`. If this is enabled, the change ID will be stored in the Git
    commit itself (in a commit header called `change-id`), which means it will be transferred by
    regular `git push` etc. This is an evolving feature that currently defaults to "false". This
    default will likely change in the future as we gain confidence with forge support and user
    expectations.

##### Breaking changes

-   `jj git push -c`/`--change` no longer moves existing local bookmarks.

-   The `editor-*.jjdescription` files passed to your editor by e.g. `jj describe`
    are now written to your system's temporary directory instead of `.jj/repo/`.

##### Deprecations

-   `git.subprocess = false` has been deprecated, and the old `libgit2`
    code path for fetches and pushes will be removed entirely in 0.30.
    Please report any remaining issues you have with the Git
    subprocessing path.

-   `ui.default-description` has been deprecated, and will be migrated to
    `template-aliases.default_commit_description`. Please also consider using
    [`templates.draft_commit_description`](docs/config.md#default-description),
    and/or [`templates.commit_trailers`](docs/config.md#commit-trailers).

-   On macOS, config.toml files in `~/Library/Application Support/jj` are
    deprecated; one should instead use `$XDG_CONFIG_HOME/jj`
    (defaults to `~/.config/jj`)

##### New features

-   Color-words diff has gained [an option to compare conflict pairs without
    materializing](docs/config.md#color-words-diff-options).

-   `jj show` patches can now be suppressed with `--no-patch`.

-   Added `ui.bookmark-list-sort-keys` setting to configure default sort keys for the
    `jj bookmark list` command.

-   New `signed` revset function to filter for cryptographically signed commits.

-   `jj describe`, `jj commit`, `jj new`, `jj squash` and `jj split` add the
    commit trailers, configured in the `commit_trailers` template, to the commit
    description. Use cases include DCO Sign Off and Gerrit Change Id.

-   Added `duplicate_description` template, which allows [customizing the descriptions
    of the commits `jj duplicate` creates](docs/config.md#duplicate-commit-description).

-   `jj absorb` can now squash a deleted file if it was added by one of the
    destination revisions.

-   Added `ui.streampager.show-ruler` setting to configure whether the ruler should be
    shown when the builtin pager starts up.

-   `jj git fetch` now warns instead of erroring for unknown `git.fetch` remotes
    if other remotes are available.

-   Commit objects in templates now have `trailers() -> List<Trailer>`, the Trailer
    objects have `key() -> String` and `value() -> String`.

-   `jj config edit` will now roll back to previous version if a syntax error has been introduced in the new config.

-   When using dynamic command-line completion, revision names will be completed
    in more complex expressions. For example, typing
    `jj log -r first-bookmark..sec` and then pressing Tab could complete the
    expression to `first-bookmark..second-bookmark`.

##### Fixed bugs

-   Fixed crash on change-delete conflict resolution. [#&#8203;6250](jj-vcs/jj#6250)

-   The builtin diff editor now tries to preserve unresolved conflicts. [#&#8203;4963](jj-vcs/jj#4963)

-   Fixed bash and zsh shell completion when completing aliases of multiple arguments. [#&#8203;5377](jj-vcs/jj#5377)

##### Packaging changes

-   Jujutsu now uses [`zlib-rs`](https://github.com/trifectatechfoundation/zlib-rs), a fast compression library written in Rust. Packagers should remove any dependency on CMake and drop the `packaging` Cargo feature.

##### Contributors

Thanks to the people who made this release happen!

-   Aleksey Kuznetsov ([@&#8203;zummenix](https://github.com/zummenix))
-   Austin Seipp ([@&#8203;thoughtpolice](https://github.com/thoughtpolice))
-   Benjamin Brittain ([@&#8203;benbrittain](https://github.com/benbrittain))
-   Benjamin Tan ([@&#8203;bnjmnt4n](https://github.com/bnjmnt4n))
-   Caleb White ([@&#8203;calebdw](https://github.com/calebdw))
-   Daniel Luz ([@&#8203;mernen](https://github.com/mernen))
-   Emily ([@&#8203;emilazy](https://github.com/emilazy))
-   Emily ([@&#8203;neongreen](https://github.com/neongreen))
-   Gaëtan Lehmann ([@&#8203;glehmann](https://github.com/glehmann))
-   George Christou ([@&#8203;gechr](https://github.com/gechr))
-   Ilya Grigoriev ([@&#8203;ilyagr](https://github.com/ilyagr))
-   Jacob Hayes ([@&#8203;JacobHayes](https://github.com/JacobHayes))
-   Jonas Greitemann ([@&#8203;jgreitemann](https://github.com/jgreitemann))
-   Josh Steadmon ([@&#8203;steadmon](https://github.com/steadmon))
-   Martin von Zweigbergk ([@&#8203;martinvonz](https://github.com/martinvonz))
-   Mateus Auler ([@&#8203;mateusauler](https://github.com/mateusauler))
-   Nicole Patricia Mazzuca ([@&#8203;strega-nil](https://github.com/strega-nil))
-   Nils Koch ([@&#8203;nilskch](https://github.com/nilskch))
-   Philip Metzger ([@&#8203;PhilipMetzger](https://github.com/PhilipMetzger))
-   Remo Senekowitsch ([@&#8203;senekor](https://github.com/senekor))
-   Sam ([@&#8203;Samasaur1](https://github.com/Samasaur1))
-   Steve Fink ([@&#8203;hotsphink](https://github.com/hotsphink))
-   Théo Daron ([@&#8203;tdaron](https://github.com/tdaron))
-   TimerErTim ([@&#8203;TimerErTim](https://github.com/TimerErTim))
-   Vincent Ging Ho Yim ([@&#8203;cenviity](https://github.com/cenviity))
-   Winter ([@&#8203;winterqt](https://github.com/winterqt))
-   Yuya Nishihara ([@&#8203;yuja](https://github.com/yuja))

### [`v0.28.2`](https://github.com/jj-vcs/jj/releases/tag/v0.28.2)

[Compare Source](jj-vcs/jj@v0.28.1...v0.28.2)

##### Fixed bugs

-   Fixed problem that old commits could be re-imported from Git.
    GitoxideLabs/gitoxide#1928

### [`v0.28.1`](https://github.com/jj-vcs/jj/releases/tag/v0.28.1)

[Compare Source](jj-vcs/jj@v0.28.0...v0.28.1)

> \[!NOTE]\
> Also see the [v0.28.0 release notes](https://github.com/jj-vcs/jj/releases/tag/v0.28.0).

##### About

jj is a Git-compatible version control system that is both simple and powerful. See the [installation instructions](https://jj-vcs.github.io/jj/v0.28.0/install-and-setup/) to get started.

##### Security fixes

-   Fixed SHA-1 collision attacks not being detected.
    ([GHSA-794x-2rpg-rfgr](GHSA-794x-2rpg-rfgr))

##### Fixed bugs

-   Resolved some potential build issues for packagers.
    [#&#8203;6232](jj-vcs/jj#6232)

-   Fix a bug with `:ours` and `:theirs` merge tools involving conflicted trees
    with more than two sides. [#&#8203;6227](jj-vcs/jj#6227)

##### Contributors

Thanks to the people who made this release happen!

-   Emily ([@&#8203;emilazy](https://github.com/emilazy))
-   Ilya Grigoriev ([@&#8203;ilyagr](https://github.com/ilyagr))
-   Nicole Patricia Mazzuca ([@&#8203;strega-nil](https://github.com/strega-nil))
-   Scott Taylor ([@&#8203;scott2000](https://github.com/scott2000))
-   Yuya Nishihara ([@&#8203;yuja](https://github.com/yuja))

### [`v0.28.0`](https://github.com/jj-vcs/jj/releases/tag/v0.28.0)

[Compare Source](jj-vcs/jj@v0.27.0...v0.28.0)

> \[!IMPORTANT]
> v0.28.0 was yanked from https://crates.io and superseded by [v0.28.1](https://github.com/jj-vcs/jj/releases/tag/v0.28.1).

##### About

jj is a Git-compatible version control system that is both simple and powerful. See the [installation instructions](https://jj-vcs.github.io/jj/v0.28.0/install-and-setup/) to get started.

##### Release highlights

-   jj's configuration can now be split into multiple files more easily.

-   `jj resolve` now accepts built-in tools `:ours` and `:theirs`.

-   In colocated repos, newly-created files will now appear in `git diff`.

-   A long-standing bug relating to empty files in the built-in diff editor was
    fixed. [#&#8203;3702](jj-vcs/jj#3702)

##### Breaking changes

-   The minimum supported Rust version (MSRV) is now 1.84.0.

-   The `git.push-branch-prefix` config has been removed in favor of
    `git.push-bookmark-prefix`.

-   `jj abandon` no longer supports `--summary` to suppress the list of abandoned
    commits. The list won't show more than 10 commits to not clutter the console.

-   `jj unsquash` has been removed in favor of `jj squash` and
    `jj diffedit --restore-descendants`.

-   The `jj untrack` subcommand has been removed in favor of `jj file untrack`.

-   The following deprecated revset functions have been removed:
    -   `branches()`, `remote_branches()`, `tracked_remote_branches()`, and
        `untracked_remote_branches()`, which were renamed to "bookmarks".
    -   `file()` and `conflict()`, which were renamed to plural forms.
    -   `files(x, y, ..)` with multiple patterns. Use `files(x|y|..)` instead.

-   The following deprecated template functions have been removed:
    -   `branches()`, `local_branches()`, and `remote_branches()`, which were
        renamed to "bookmarks".

-   The flags `--all` and `--tracked` on `jj git push` by themself do not cause
    deleted bookmarks to be pushed anymore, as an additional safety measure. They
    can now be combined with `--deleted` instead.

##### Deprecations

-   `core.watchman.register_snapshot_trigger` has been renamed to `core.watchman.register-snapshot-trigger` for consistency with other configuration options.

-   `jj backout` is deprecated in favor of `jj revert`.

##### New features

-   `jj sign` can now sign with [PKCS#12](https://github.com/PKCS/jj/issues/12) certificates through the `gpgsm` backend.

-   `jj sign` will automatically use the gpg key associated with the author's email
    in the absence of a `signing.key` configuration.

-   Multiple user configs are now supported and are loaded in the following precedence order:
    -   `$HOME/.jjconfig.toml`
    -   `$XDG_CONFIG_HOME/jj/config.toml`
    -   `$XDG_CONFIG_HOME/jj/conf.d/*.toml`

-   The `JJ_CONFIG` environment variable can now contain multiple paths separated
    by a colon (or semicolon on Windows).

-   The command `jj config list` now supports showing the origin of each variable
    via the `builtin_config_list_detailed` template.

-   `jj config {edit,set,unset}` now prompt when multiple config files are found.

-   `jj diff -r` now allows multiple revisions (as long as there are no gaps in
    the revset), such as `jj diff -r 'mutable()'`.

-   `jj git push` now accepts a `--named NAME=REVISION` argument to create a named
    bookmark and immediately push it.

-   The 'how to resolve conflicts' hint that is shown when conflicts appear can
    be hidden by setting `hints.resolving-conflicts = false`.

-   `jj op diff` and `jj op log --op-diff` now show changes to which commits
    correspond to working copies.

-   `jj op log -d` is now an alias for `jj op log --op-diff`.

-   `jj bookmark move --to/--from` can now be abbreviated to `jj bookmark move -t/-f`

-   `jj bookmark list` now supports `--sort` option. Similar to `git branch --sort`.
    See `jj bookmark list --help` for more details.

-   A new command `jj revert` is added, which is similar to `jj backout` but
    adds the `--destination`, `--insert-after`, and `--insert-before` options to
    customize the location of reverted commits.

-   A new command `jj git root` is added, which prints the location of the Git
    directory of a repository using the Git backend.

-   In colocated repos, any files that jj considers added in the working copy will
    now show up in `git diff` (as if you had run `git add --intent-to-add` on
    them).

-   Reversing colors is now supported. For example, to highlight words by
    reversing colors rather than underlining, you can set
    `colors."diff token"={ underline = false, reverse = true }` in your config.

-   Added `revsets.log-graph-prioritize`, which can be used to configure
    which branch in the `jj log` graph is displayed on the left instead of `@`
    (e.g. `coalesce(description("megamerge\n"), trunk())`)

-   `jj resolve` now accepts new built-in merge tools `:ours` and `:theirs`.
    These merge tools accept side [#&#8203;1](jj-vcs/jj#1) and side [#&#8203;2](jj-vcs/jj#2) of the conflict respectively.

##### Fixed bugs

-   `jj log -p --stat` now shows diff stats as well as the default color-words/git
    diff output. [#&#8203;5986](jj-vcs/jj#5986)

-   The built-in diff editor now correctly handles deleted files.
    [#&#8203;3702](jj-vcs/jj#3702)

-   The built-in diff editor now correctly retains the executable bit on newly
    added files when splitting. [#&#8203;3846](jj-vcs/jj#3846)

-   `jj config set`/`--config` value parsing rule is relaxed in a way that
    unquoted apostrophes are allowed.
    [#&#8203;5748](jj-vcs/jj#5748)

-   `jj fix` could previously create new conflicts when a descendant of a fixed
    revision was already correctly formatted.

##### Contributors

Thanks to the people who made this release happen!

-   Aleksey Kuznetsov ([@&#8203;zummenix](https://github.com/zummenix))
-   Anton Älgmyr ([@&#8203;algmyr](https://github.com/algmyr))
-   Austin Seipp ([@&#8203;thoughtpolice](https://github.com/thoughtpolice))
-   Baltasar Dinis ([@&#8203;bsdinis](https://github.com/bsdinis))
-   Benjamin Tan ([@&#8203;bnjmnt4n](https://github.com/bnjmnt4n))
-   Brandon Hall ([@&#8203;tenkabuto](https://github.com/tenkabuto))
-   Caleb White ([@&#8203;calebdw](https://github.com/calebdw))
-   Daniel Luz ([@&#8203;mernen](https://github.com/mernen))
-   David Rieber ([@&#8203;drieber](https://github.com/drieber))
-   demize ([@&#8203;demize](https://github.com/demize))
-   Emily ([@&#8203;emilazy](https://github.com/emilazy))
-   Evan Mesterhazy ([@&#8203;emesterhazy](https://github.com/emesterhazy))
-   Fedor Sheremetyev ([@&#8203;sheremetyev](https://github.com/sheremetyev))
-   George Christou ([@&#8203;gechr](https://github.com/gechr))
-   Ilya Grigoriev ([@&#8203;ilyagr](https://github.com/ilyagr))
-   Jakob Hellermann ([@&#8203;jakobhellermann](https://github.com/jakobhellermann))
-   Jo Liss ([@&#8203;joliss](https://github.com/joliss))
-   Joachim Desroches ([@&#8203;jedesroches](https://github.com/jedesroches))
-   Johannes Altmanninger ([@&#8203;krobelus](https://github.com/krobelus))
-   Jonathan Gilchrist ([@&#8203;jgilchrist](https://github.com/jgilchrist))
-   Kenyon Ralph ([@&#8203;kenyon](https://github.com/kenyon))
-   Lucas Garron ([@&#8203;lgarron](https://github.com/lgarron))
-   Martin von Zweigbergk ([@&#8203;martinvonz](https://github.com/martinvonz))
-   Nick Pupko ([@&#8203;npupko](https://github.com/npupko))
-   Philip Metzger ([@&#8203;PhilipMetzger](https://github.com/PhilipMetzger))
-   Raphael Borun Das Gupta ([@&#8203;das-g](https://github.com/das-g))
-   Remo Senekowitsch ([@&#8203;senekor](https://github.com/senekor))
-   Robin Stocker ([@&#8203;robinst](https://github.com/robinst))
-   Scott Taylor ([@&#8203;scott2000](https://github.com/scott2000))
-   Siva Mahadevan ([@&#8203;svmhdvn](https://github.com/svmhdvn))
-   Vincent Ging Ho Yim ([@&#8203;cenviity](https://github.com/cenviity))
-   Yuya Nishihara ([@&#8203;yuja](https://github.com/yuja))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4yIiwidXBkYXRlZEluVmVyIjoiNDAuMTEuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
yuja added a commit that referenced this pull request Jul 14, 2025
This is ugly, but avoids CompositeIndex<'a> lifetime. If CompositeIndex had
a reference, trait bounds in the revset engine would become quite messy.

FWIW, I think a composite index type could be a pair of (Vec<Readonly>,
Option<Mutable>). I'm not going to reorganize the commit index at the moment,
but I assume the changed-paths index will be structured in that way.
Changed-paths index won't have data dependency between segments, and it will
have a commit offset field which only applies to the first segment. So it will
probably make sense to manage segments as an array, not as a linked list.

    commit offset
    segment #0:
      for each commit
        changed paths (interned)
      sstable of paths
    segment #1:
      for each commit
        changed paths (interned)
      sstable of paths
    ...
yuja added a commit that referenced this pull request Jul 17, 2025
This is ugly, but avoids CompositeIndex<'a> lifetime. If CompositeIndex had
a reference, trait bounds in the revset engine would become quite messy.

FWIW, I think a composite index type could be a pair of (Vec<Readonly>,
Option<Mutable>). I'm not going to reorganize the commit index at the moment,
but I assume the changed-paths index will be structured in that way.
Changed-paths index won't have data dependency between segments, and it will
have a commit offset field which only applies to the first segment. So it will
probably make sense to manage segments as an array, not as a linked list.

    commit offset
    segment #0:
      for each commit
        changed paths (interned)
      sstable of paths
    segment #1:
      for each commit
        changed paths (interned)
      sstable of paths
    ...
yuja added a commit that referenced this pull request Jul 18, 2025
This is ugly, but avoids CompositeIndex<'a> lifetime. If CompositeIndex had
a reference, trait bounds in the revset engine would become quite messy.

FWIW, I think a composite index type could be a pair of (Vec<Readonly>,
Option<Mutable>). I'm not going to reorganize the commit index at the moment,
but I assume the changed-paths index will be structured in that way.
Changed-paths index won't have data dependency between segments, and it will
have a commit offset field which only applies to the first segment. So it will
probably make sense to manage segments as an array, not as a linked list.

    commit offset
    segment #0:
      for each commit
        changed paths (interned)
      sstable of paths
    segment #1:
      for each commit
        changed paths (interned)
      sstable of paths
    ...
github-merge-queue bot pushed a commit that referenced this pull request Jul 21, 2025
This is ugly, but avoids CompositeIndex<'a> lifetime. If CompositeIndex had
a reference, trait bounds in the revset engine would become quite messy.

FWIW, I think a composite index type could be a pair of (Vec<Readonly>,
Option<Mutable>). I'm not going to reorganize the commit index at the moment,
but I assume the changed-paths index will be structured in that way.
Changed-paths index won't have data dependency between segments, and it will
have a commit offset field which only applies to the first segment. So it will
probably make sense to manage segments as an array, not as a linked list.

    commit offset
    segment #0:
      for each commit
        changed paths (interned)
      sstable of paths
    segment #1:
      for each commit
        changed paths (interned)
      sstable of paths
    ...
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

Successfully merging this pull request may close these issues.

2 participants