mirror of
https://github.com/jj-vcs/jj.git
synced 2025-12-23 06:01:01 +00:00
rewrite: add conflict labels for squashed commits
An example of squashing `ysrnknol` into `rtsqusxu`: ``` <<<<<<< conflict 1 of 1 +++++++ rtsqusxu 2768b0b9 "A" (squash destination) updated in destination %%%%%%% diff from: vpxusssl 38d49363 "B" (parents of squashed commit) \\\\\\\ to: ysrnknol 7a20f389 "C" (squashed commit) -base +squashed >>>>>>> conflict 1 of 1 ends ``` Or with only partial changes selected: ``` <<<<<<< conflict 1 of 1 +++++++ rtsqusxu 2768b0b9 "A" (squash destination) updated in destination %%%%%%% diff from: vpxusssl 38d49363 "B" (parents of squashed commit) \\\\\\\ to: selected changes for squash (from ysrnknol 7a20f389 "C") -base +selected changes >>>>>>> conflict 1 of 1 ends ```
This commit is contained in:
parent
225bbe4835
commit
5fd1b2fd5b
2 changed files with 45 additions and 36 deletions
|
|
@ -903,10 +903,10 @@ fn test_squash_from_multiple() {
|
|||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Rebased 2 descendant commits
|
||||
Working copy (@) now at: kpqxywon 0b695306 f | (no description set)
|
||||
Parent commit (@-) : yostqsxw ff064d52 e | (no description set)
|
||||
Working copy (@) now at: kpqxywon eb200347 f | (no description set)
|
||||
Parent commit (@-) : yostqsxw 9475acea e | (no description set)
|
||||
New conflicts appeared in 1 commits:
|
||||
yqosqzyt 61130da4 d | (conflict) (no description set)
|
||||
yqosqzyt 33563014 d | (conflict) (no description set)
|
||||
Hint: To resolve the conflicts, start by creating a commit on top of
|
||||
the conflicted commit:
|
||||
jj new yqosqzyt
|
||||
|
|
@ -916,10 +916,10 @@ fn test_squash_from_multiple() {
|
|||
[EOF]
|
||||
");
|
||||
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
||||
@ 0b6953066ee0 f
|
||||
○ ff064d529578 e
|
||||
@ eb200347027e f
|
||||
○ 9475acea2503 e
|
||||
├─╮
|
||||
× │ 61130da4e714 d
|
||||
× │ 335630141fde d
|
||||
├─╯
|
||||
○ e88768e65e67 a b c
|
||||
◆ 000000000000 (empty)
|
||||
|
|
@ -929,13 +929,15 @@ fn test_squash_from_multiple() {
|
|||
let output = work_dir.run_jj(["file", "show", "-r=d", "file"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
<<<<<<< conflict 1 of 1
|
||||
%%%%%%% diff from base #1 to side #1
|
||||
%%%%%%% diff from: qpvuntsm e88768e6 (parents of squashed commit)
|
||||
\\\\\\\ to: yqosqzyt 8acbb715 (squash destination)
|
||||
-a
|
||||
+d
|
||||
%%%%%%% diff from base #2 to side #2
|
||||
%%%%%%% diff from: qpvuntsm e88768e6 (parents of squashed commit)
|
||||
\\\\\\\ to: kkmpptxz fed4d1a2 (squashed commit)
|
||||
-a
|
||||
+b
|
||||
+++++++ side #3
|
||||
+++++++ mzvwutvl d7e94ec7 (squashed commit)
|
||||
c
|
||||
>>>>>>> conflict 1 of 1 ends
|
||||
[EOF]
|
||||
|
|
@ -1047,10 +1049,10 @@ fn test_squash_from_multiple_partial() {
|
|||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Rebased 2 descendant commits
|
||||
Working copy (@) now at: kpqxywon a724910c f | (no description set)
|
||||
Parent commit (@-) : yostqsxw 1bc405e1 e | (no description set)
|
||||
Working copy (@) now at: kpqxywon a8eee959 f | (no description set)
|
||||
Parent commit (@-) : yostqsxw fac4927e e | (no description set)
|
||||
New conflicts appeared in 1 commits:
|
||||
yqosqzyt 7ddfe685 d | (conflict) (no description set)
|
||||
yqosqzyt 22dccf0d d | (conflict) (no description set)
|
||||
Hint: To resolve the conflicts, start by creating a commit on top of
|
||||
the conflicted commit:
|
||||
jj new yqosqzyt
|
||||
|
|
@ -1060,13 +1062,13 @@ fn test_squash_from_multiple_partial() {
|
|||
[EOF]
|
||||
");
|
||||
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
||||
@ a724910cd361 f
|
||||
○ 1bc405e12b68 e
|
||||
@ a8eee9597ba5 f
|
||||
○ fac4927e5714 e
|
||||
├─┬─╮
|
||||
│ │ ○ e9db15b956c4 b
|
||||
│ ○ │ 83cbe51db94d c
|
||||
│ ├─╯
|
||||
× │ 7ddfe6857387 d
|
||||
× │ 22dccf0db9ab d
|
||||
├─╯
|
||||
○ 64ea60be8d77 a
|
||||
◆ 000000000000 (empty)
|
||||
|
|
@ -1087,13 +1089,15 @@ fn test_squash_from_multiple_partial() {
|
|||
let output = work_dir.run_jj(["file", "show", "-r=d", "file1"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
<<<<<<< conflict 1 of 1
|
||||
%%%%%%% diff from base #1 to side #1
|
||||
%%%%%%% diff from: qpvuntsm 64ea60be (parents of squashed commit)
|
||||
\\\\\\\ to: yqosqzyt f6812ff8 (squash destination)
|
||||
-a
|
||||
+d
|
||||
%%%%%%% diff from base #2 to side #2
|
||||
%%%%%%% diff from: qpvuntsm 64ea60be (parents of squashed commit)
|
||||
\\\\\\\ to: selected changes for squash (from kkmpptxz f2c9709f)
|
||||
-a
|
||||
+b
|
||||
+++++++ side #3
|
||||
+++++++ selected changes for squash (from mzvwutvl aa908686)
|
||||
c
|
||||
>>>>>>> conflict 1 of 1 ends
|
||||
[EOF]
|
||||
|
|
|
|||
|
|
@ -1174,6 +1174,7 @@ impl CommitWithSelection {
|
|||
&self,
|
||||
parent_tree_label: &str,
|
||||
selected_tree_label: &str,
|
||||
full_selection_label: &str,
|
||||
) -> BackendResult<Diff<(MergedTree, String)>> {
|
||||
let parents: Vec<_> = self.commit.parents().try_collect()?;
|
||||
let parent_tree_label = format!(
|
||||
|
|
@ -1183,9 +1184,9 @@ impl CommitWithSelection {
|
|||
|
||||
let commit_label = self.commit.conflict_label();
|
||||
let selected_tree_label = if self.is_full_selection() {
|
||||
format!("{commit_label} ({selected_tree_label})")
|
||||
format!("{commit_label} ({full_selection_label})")
|
||||
} else {
|
||||
format!("{selected_tree_label} (selected from {commit_label})")
|
||||
format!("{selected_tree_label} (from {commit_label})")
|
||||
};
|
||||
|
||||
Ok(Diff::new(
|
||||
|
|
@ -1215,6 +1216,7 @@ pub fn squash_commits<'repo>(
|
|||
) -> BackendResult<Option<SquashedCommit<'repo>>> {
|
||||
struct SourceCommit<'a> {
|
||||
commit: &'a CommitWithSelection,
|
||||
diff: Diff<(MergedTree, String)>,
|
||||
abandon: bool,
|
||||
}
|
||||
let mut source_commits = vec![];
|
||||
|
|
@ -1231,6 +1233,11 @@ pub fn squash_commits<'repo>(
|
|||
// squash -r`)? The source tree will be unchanged in that case.
|
||||
source_commits.push(SourceCommit {
|
||||
commit: source,
|
||||
diff: source.diff_with_labels(
|
||||
"parents of squashed commit",
|
||||
"selected changes for squash",
|
||||
"squashed commit",
|
||||
)?,
|
||||
abandon,
|
||||
});
|
||||
}
|
||||
|
|
@ -1247,12 +1254,11 @@ pub fn squash_commits<'repo>(
|
|||
} else {
|
||||
let source_tree = source.commit.commit.tree();
|
||||
// Apply the reverse of the selected changes onto the source
|
||||
let new_source_tree = source_tree
|
||||
.merge_unlabeled(
|
||||
source.commit.selected_tree.clone(),
|
||||
source.commit.parent_tree.clone(),
|
||||
)
|
||||
.block_on()?;
|
||||
let new_source_tree = MergedTree::merge(Merge::from_diffs(
|
||||
(source_tree, source.commit.commit.conflict_label()),
|
||||
[source.diff.clone().invert()],
|
||||
))
|
||||
.block_on()?;
|
||||
repo.rewrite_commit(&source.commit.commit)
|
||||
.set_tree(new_source_tree)
|
||||
.write()?;
|
||||
|
|
@ -1282,22 +1288,21 @@ pub fn squash_commits<'repo>(
|
|||
};
|
||||
})?;
|
||||
}
|
||||
// Apply the selected changes onto the destination
|
||||
let mut destination_tree = rewritten_destination.tree();
|
||||
for source in &source_commits {
|
||||
destination_tree = destination_tree
|
||||
.merge_unlabeled(
|
||||
source.commit.parent_tree.clone(),
|
||||
source.commit.selected_tree.clone(),
|
||||
)
|
||||
.block_on()?;
|
||||
}
|
||||
let mut predecessors = vec![destination.id().clone()];
|
||||
predecessors.extend(
|
||||
source_commits
|
||||
.iter()
|
||||
.map(|source| source.commit.commit.id().clone()),
|
||||
);
|
||||
// Apply the selected changes onto the destination
|
||||
let destination_tree = MergedTree::merge(Merge::from_diffs(
|
||||
(
|
||||
rewritten_destination.tree(),
|
||||
format!("{} (squash destination)", destination.conflict_label()),
|
||||
),
|
||||
source_commits.into_iter().map(|source| source.diff),
|
||||
))
|
||||
.block_on()?;
|
||||
|
||||
let commit_builder = repo
|
||||
.rewrite_commit(&rewritten_destination)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue