mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-01 00:50:57 +00:00
restore: add --restore-descendants flag
This commit is contained in:
parent
e8deb08f78
commit
cf7847d784
4 changed files with 100 additions and 7 deletions
|
@ -69,11 +69,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|||
* `jj commit` and `jj describe` now accept `--author` option allowing to quickly change
|
||||
author of given commit.
|
||||
|
||||
* `jj diffedit` now accepts a `--restore-descendants` flag. When used,
|
||||
descendants of the edited commit will keep their original content.
|
||||
|
||||
* `jj abandon` now accepts a `--restore-descendants` flag. When used,
|
||||
descendants of the abandoned commits will keep their original content.
|
||||
* `jj diffedit`, `jj abandon`, and `jj restore` now accept a `--restore-descendants`
|
||||
flag. When used, descendants of the edited or deleted commits will keep their original
|
||||
content.
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
|
|
|
@ -70,6 +70,9 @@ pub(crate) struct RestoreArgs {
|
|||
/// the user might not even realize something went wrong.
|
||||
#[arg(long, short, hide = true)]
|
||||
revision: Option<RevisionArg>,
|
||||
/// Preserve the content (not the diff) when rebasing descendants
|
||||
#[arg(long)]
|
||||
restore_descendants: bool,
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
|
@ -116,13 +119,23 @@ pub(crate) fn cmd_restore(
|
|||
.write()?;
|
||||
// rebase_descendants early; otherwise `new_commit` would always have
|
||||
// a conflicted change id at this point.
|
||||
let num_rebased = tx.repo_mut().rebase_descendants(command.settings())?;
|
||||
let (num_rebased, extra_msg) = if args.restore_descendants {
|
||||
(
|
||||
tx.repo_mut().reparent_descendants(command.settings())?,
|
||||
" (while preserving their content)",
|
||||
)
|
||||
} else {
|
||||
(tx.repo_mut().rebase_descendants(command.settings())?, "")
|
||||
};
|
||||
if let Some(mut formatter) = ui.status_formatter() {
|
||||
write!(formatter, "Created ")?;
|
||||
tx.write_commit_summary(formatter.as_mut(), &new_commit)?;
|
||||
writeln!(formatter)?;
|
||||
if num_rebased > 0 {
|
||||
writeln!(formatter, "Rebased {num_rebased} descendant commits")?;
|
||||
writeln!(
|
||||
formatter,
|
||||
"Rebased {num_rebased} descendant commits{extra_msg}"
|
||||
)?;
|
||||
}
|
||||
}
|
||||
tx.finish(ui, format!("restore into commit {}", to_commit.id().hex()))?;
|
||||
|
|
|
@ -1784,6 +1784,7 @@ See `jj diffedit` if you'd like to restore portions of files rather than entire
|
|||
This undoes the changes that can be seen with `jj diff -r REVISION`. If `REVISION` only has a single parent, this option is equivalent to `jj restore --to REVISION --from REVISION-`.
|
||||
|
||||
The default behavior of `jj restore` is equivalent to `jj restore --changes-in @`.
|
||||
* `--restore-descendants` — Preserve the content (not the diff) when rebasing descendants
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -261,6 +261,87 @@ fn test_restore_conflicted_merge() {
|
|||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_restore_restore_descendants() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
create_commit(&test_env, &repo_path, "base", &[], &[("file", "base\n")]);
|
||||
create_commit(&test_env, &repo_path, "a", &["base"], &[("file", "a\n")]);
|
||||
create_commit(
|
||||
&test_env,
|
||||
&repo_path,
|
||||
"b",
|
||||
&["base"],
|
||||
&[("file", "b\n"), ("file2", "b\n")],
|
||||
);
|
||||
create_commit(
|
||||
&test_env,
|
||||
&repo_path,
|
||||
"ab",
|
||||
&["a", "b"],
|
||||
&[("file", "ab\n")],
|
||||
);
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r#"
|
||||
@ ab
|
||||
├─╮
|
||||
│ ○ b
|
||||
○ │ a
|
||||
├─╯
|
||||
○ base
|
||||
◆
|
||||
"#);
|
||||
insta::assert_snapshot!(
|
||||
std::fs::read_to_string(repo_path.join("file")).unwrap(), @r#"
|
||||
ab
|
||||
"#);
|
||||
|
||||
// Commit "b" was not supposed to modify "file", restore it from its parent
|
||||
// while preserving its child commit content.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["restore", "-c", "b", "file", "--restore-descendants"],
|
||||
);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r#"
|
||||
Created royxmykx 3fd5aa05 b | b
|
||||
Rebased 1 descendant commits (while preserving their content)
|
||||
Working copy now at: vruxwmqv bf5491a0 ab | ab
|
||||
Parent commit : zsuskuln aa493daf a | a
|
||||
Parent commit : royxmykx 3fd5aa05 b | b
|
||||
"#);
|
||||
|
||||
// Check that "a", "b", and "ab" have their expected content by diffing them.
|
||||
// "ab" must have kept its content.
|
||||
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["diff", "--from=a", "--to=ab", "--git"]), @r#"
|
||||
diff --git a/file b/file
|
||||
index 7898192261..81bf396956 100644
|
||||
--- a/file
|
||||
+++ b/file
|
||||
@@ -1,1 +1,1 @@
|
||||
-a
|
||||
+ab
|
||||
diff --git a/file2 b/file2
|
||||
new file mode 100644
|
||||
index 0000000000..6178079822
|
||||
--- /dev/null
|
||||
+++ b/file2
|
||||
@@ -1,0 +1,1 @@
|
||||
+b
|
||||
"#);
|
||||
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["diff", "--from=b", "--to=ab", "--git"]), @r#"
|
||||
diff --git a/file b/file
|
||||
index df967b96a5..81bf396956 100644
|
||||
--- a/file
|
||||
+++ b/file
|
||||
@@ -1,1 +1,1 @@
|
||||
-base
|
||||
+ab
|
||||
"#);
|
||||
}
|
||||
|
||||
fn create_commit(
|
||||
test_env: &TestEnvironment,
|
||||
repo_path: &Path,
|
||||
|
|
Loading…
Reference in a new issue