feat(squash): Add --keep-emptied flag

Fixes #3815
This commit is contained in:
Matt Stark 2024-06-05 09:34:50 +10:00 committed by Matt
parent 7682a038a1
commit ca4eb60426
5 changed files with 141 additions and 76 deletions

View file

@ -3,7 +3,8 @@
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
@ -134,7 +135,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Conflict markers now include an explanation of what each part of the conflict
represents.
* `ui.color = "debug"` prints active labels alongside the regular colored output.
* `ui.color = "debug"` prints active labels alongside the regular colored
output.
* `jj branch track` now show conflicts if there are some.
@ -162,6 +164,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `jj git push` now can push commits with empty descriptions with the
`--allow-empty-description` flag
* `jj squash` now accepts a `--keep-emptied` option to keep the source commit.
### Fixed bugs
* Previously, `jj git push` only made sure that the branch is in the expected
@ -176,12 +180,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
fetch` works, `jj` does not suffer from the same problems as Git's `git push
--force-with-lease` in situations when `git fetch` is run in the background.
* When the working copy commit becomes immutable, a new one is automatically created
* When the working copy commit becomes immutable, a new one is automatically
created
on top of it to avoid letting the user edit the immutable one.
* `jj config list` now properly escapes TOML keys (#1322).
* Files with conflicts are now checked out as executable if all sides of the
* Files with conflicts are now checked out as executable if all sides of the
conflict are executable.
* The progress bar (visible when using e.g. `jj git clone`) clears the
@ -220,7 +225,8 @@ Thanks to the people who made this release happen!
### Fixed bugs
* `jj status` no longer scans through the entire history to look for ancestors with conflicts.
* `jj status` no longer scans through the entire history to look for ancestors
with conflicts.
## [0.17.0] - 2024-05-01
@ -279,7 +285,7 @@ Thanks to the people who made this release happen!
`jj debug watchman status` command.
* `jj rebase` now accepts revsets resolving to multiple revisions with the
`--revisions`/`-r` option.
`--revisions`/`-r` option.
* `jj rebase -r` now accepts `--insert-after` and `--insert-before` options to
customize the location of the rebased revisions.
@ -327,7 +333,6 @@ Thanks to the people who made this release happen!
* Théo Daron (@tdaron)
* Yuya Nishihara (@yuja)
## [0.16.0] - 2024-04-03
### Deprecations
@ -345,11 +350,13 @@ Thanks to the people who made this release happen!
* The `jj sparse` subcommands now parse and print patterns as workspace-relative
paths.
* The `jj log` command no longer uses the default revset when a path is specified.
* The `jj log` command no longer uses the default revset when a path is
specified.
### New features
* Config now supports rgb hex colors (in the form `#rrggbb`) wherever existing color names are supported.
* Config now supports rgb hex colors (in the form `#rrggbb`) wherever existing
color names are supported.
* `ui.default-command` now accepts multiple string arguments, for more complex
default `jj` commands.
@ -375,7 +382,8 @@ Thanks to the people who made this release happen!
* `jj git push` now prints messages from the remote.
* `jj branch list` now supports a `--conflicted/-c` option to show only conflicted branches.
* `jj branch list` now supports a `--conflicted/-c` option to show only
conflicted branches.
* `jj duplicate` and `jj abandon` can now take more than a single `-r` argument,
for consistency with other commands.
@ -389,7 +397,8 @@ Thanks to the people who made this release happen!
* `jj split` now supports a `--siblings/-s` option that splits the target
revision into siblings with the same parents and children.
* New function `working_copies()` for revsets to show the working copy commits of all workspaces.
* New function `working_copies()` for revsets to show the working copy commits
of all workspaces.
### Fixed bugs
@ -421,7 +430,6 @@ Thanks to the people who made this release happen!
* TrashCan (@TrashCan69420)
* Yuya Nishihara (@yuja)
## [0.15.1] - 2024-03-06
No code changes (fixing Rust `Cargo.toml` stuff).
@ -496,15 +504,17 @@ No code changes (fixing Rust `Cargo.toml` stuff).
* `jj git init --colocate` can now import an existing Git repository. This is
equivalent to `jj git init --git-repo=.`.
* `jj git fetch` now automatically prints new remote branches and tags by default.
* `jj git fetch` now automatically prints new remote branches and tags by
default.
* `--verbose/-v` is now `--debug` (no short option since it's not intended to be used often)
* `--verbose/-v` is now `--debug` (no short option since it's not intended to be
used often)
* `jj move --from/--to` can now be abbreviated to `jj move -f/-t`
* `jj commit`/`diffedit`/`move`/`resolve`/`split`/`squash`/`unsquash` now accept
`--tool=<NAME>` option to override the default.
[#2575](https://github.com/martinvonz/jj/issues/2575)
[#2575](https://github.com/martinvonz/jj/issues/2575)
* Added completions for [Nushell](https://nushell.sh) to `jj util completion`
@ -520,8 +530,10 @@ No code changes (fixing Rust `Cargo.toml` stuff).
### Fixed bugs
* On Windows, symlinks in the repo are now supported when Developer Mode is enabled.
When symlink support is unavailable, they will be materialized as regular files in the
* On Windows, symlinks in the repo are now supported when Developer Mode is
enabled.
When symlink support is unavailable, they will be materialized as regular
files in the
working copy (instead of resulting in a crash).
[#2](https://github.com/martinvonz/jj/issues/2)
@ -558,7 +570,6 @@ Thanks to the people who made this release happen!
* Vladimir (@0xdeafbeef)
* Yuya Nishihara (@yuja)
## [0.14.0] - 2024-02-07
### Deprecations
@ -587,12 +598,12 @@ Thanks to the people who made this release happen!
**Deadline**: `jj checkout` and `jj merge` will be deleted and are expected
become a **hard error later in 2024**.
* `jj init --git` and `jj init --git-repo` are now deprecated and will be removed
* `jj init --git` and `jj init --git-repo` are now deprecated and will be
removed
in the near future.
Use `jj git init` instead.
### Breaking changes
* (Minor) Diff summaries (e.g. `jj diff -s`) now use `D` for "Deleted" instead
@ -620,7 +631,8 @@ Thanks to the people who made this release happen!
* `jj util gc` now removes unreachable operation, view, and Git objects.
* `jj branch rename` will now warn if the renamed branch has a remote branch, since
* `jj branch rename` will now warn if the renamed branch has a remote branch,
since
those will have to be manually renamed outside of `jj`.
* `jj git push` gained a `--tracked` option, to push all the tracked branches.
@ -684,7 +696,6 @@ Thanks to the people who made this release happen!
* vwkd (@vwkd)
* Yuya Nishihara (@yuja)
## [0.13.0] - 2024-01-03
### Breaking changes
@ -718,7 +729,6 @@ Thanks to the people who made this release happen!
* Waleed Khan (@arxanas)
* Yuya Nishihara (@yuja)
## [0.12.0] - 2023-12-05
### Breaking changes
@ -779,7 +789,6 @@ Thanks to the people who made this release happen!
* Waleed Khan (@arxanas)
* Yuya Nishihara (@yuja)
## [0.11.0] - 2023-11-01
### Breaking changes
@ -827,7 +836,8 @@ Thanks to the people who made this release happen!
### New features
* `jj`'s stable release can now be installed with [`cargo binstall jj-cli`](https://github.com/cargo-bins/cargo-binstall).
* `jj`'s stable release can now be installed
with [`cargo binstall jj-cli`](https://github.com/cargo-bins/cargo-binstall).
* `jj workspace add` now takes a `--revision` argument.
@ -880,14 +890,15 @@ Thanks to the people who made this release happen!
* Waleed Khan (@arxanas)
* Yuya Nishihara (@yuja)
## [0.10.0] - 2023-10-04
### Breaking changes
* A default revset-alias function `trunk()` now exists. If you previously defined
* A default revset-alias function `trunk()` now exists. If you previously
defined
your own `trunk()` alias it will continue to overwrite the built-in one.
Check [revsets.toml](cli/src/config/revsets.toml) and [revsets.md](docs/revsets.md)
Check [revsets.toml](cli/src/config/revsets.toml)
and [revsets.md](docs/revsets.md)
to understand how the function can be adapted.
### New features
@ -943,7 +954,6 @@ Thanks to the people who made this release happen!
* Yuya Nishihara (@yuja)
* Zachary Dremann (@Dr-Emann)
## [0.9.0] - 2023-09-06
### Breaking changes
@ -968,7 +978,8 @@ Thanks to the people who made this release happen!
* The default editor on Windows is now `Notepad` instead of `pico`.
* `jj` will fail attempts to snapshot new files larger than 1MiB by default. This behavior
* `jj` will fail attempts to snapshot new files larger than 1MiB by default.
This behavior
can be customized with the `snapshot.max-new-file-size` config option.
* Author and committer signatures now use empty strings to represent unset
@ -1010,7 +1021,8 @@ Thanks to the people who made this release happen!
* `jj init --git-repo` now works with bare repositories.
* `jj config edit --user` and `jj config set --user` will now pick a default
config location if no existing file is found, potentially creating parent directories.
config location if no existing file is found, potentially creating parent
directories.
* `jj log` output is now topologically grouped.
[#242](https://github.com/martinvonz/jj/issues/242)
@ -1051,7 +1063,8 @@ Thanks to the people who made this release happen!
selects the branch named "main", but not "maint". `description(exact:"")`
selects commits whose description is empty.
* Revsets gained a new function `mine()` that aliases `author(exact:"your_email")`.
* Revsets gained a new function `mine()` that
aliases `author(exact:"your_email")`.
* Added support for `::` and `..` revset operators with both left and right
operands omitted. These expressions are equivalent to `all()` and `~root()`
@ -1059,7 +1072,8 @@ Thanks to the people who made this release happen!
* `jj log` timestamp format now accepts `.utc()` to convert a timestamp to UTC.
* templates now support additional string methods `.starts_with(x)`, `.ends_with(x)`
* templates now support additional string
methods `.starts_with(x)`, `.ends_with(x)`
`.remove_prefix(x)`, `.remove_suffix(x)`, and `.substr(start, end)`.
* `jj next` and `jj prev` are added, these allow you to traverse the history
@ -1068,7 +1082,8 @@ Thanks to the people who made this release happen!
further pending improvements.
* `jj diff --stat` has been implemented. It shows a histogram of the changes,
same as `git diff --stat`. Fixes [#2066](https://github.com/martinvonz/jj/issues/2066)
same as `git diff --stat`.
Fixes [#2066](https://github.com/martinvonz/jj/issues/2066)
* `jj git fetch --all-remotes` has been implemented. It fetches all remotes
instead of just the default remote
@ -1078,7 +1093,8 @@ Thanks to the people who made this release happen!
* Fix issues related to .gitignore handling of untracked directories
[#2051](https://github.com/martinvonz/jj/issues/2051).
* `jj config set --user` and `jj config edit --user` can now be used outside of any repository.
* `jj config set --user` and `jj config edit --user` can now be used outside of
any repository.
* SSH authentication could hang when ssh-agent couldn't be reached
[#1970](https://github.com/martinvonz/jj/issues/1970)
@ -1120,7 +1136,6 @@ Thanks to the people who made this release happen!
* Yuya Nishihara (@yuja)
* Zachary Dremann (@Dr-Emann)
## [0.8.0] - 2023-07-09
### Breaking changes
@ -1165,7 +1180,8 @@ Thanks to the people who made this release happen!
### New features
* `jj git push --deleted` will remove all locally deleted branches from the remote.
* `jj git push --deleted` will remove all locally deleted branches from the
remote.
* `jj restore` without `--from` works correctly even if `@` is a merge
commit.
@ -1321,7 +1337,6 @@ Thanks to the people who made this release happen!
* Waleed Khan (@arxanas)
* Yuya Nishihara (@yuja)
## [0.7.0] - 2023-02-16
### Breaking changes
@ -1505,7 +1520,8 @@ Thanks to the people who made this release happen!
* `jj undo` now works after `jj duplicate`.
* `jj duplicate` followed by `jj rebase` of a tree containing both the original
and duplicate commit no longer crashes. The fix should also resolve any remaining
and duplicate commit no longer crashes. The fix should also resolve any
remaining
instances of https://github.com/martinvonz/jj/issues/27.
* Fix the output of `jj debug completion --help` by reversing fish and zsh text.
@ -1517,25 +1533,25 @@ Thanks to the people who made this release happen!
Thanks to the people who made this release happen!
* Aleksandr Mikhailov (@AM5800)
* Augie Fackler (@durin42)
* Benjamin Saunders (@Ralith)
* Daniel Ploch (@torquestomp)
* Danny Hooper (@hooper)
* David Barnett (@dbarnett)
* Glen Choo (@chooglen)
* Herby Gillot (@herbygillot)
* Ilya Grigoriev (@ilyagr)
* Luke Granger-Brown (@lukegb)
* Martin von Zweigbergk (@martinvonz)
* Michael Forster (@MForster)
* Philip Metzger (@PhilipMetzger)
* Ruben Slabbert (@rslabbert)
* Samuel Tardieu (@samueltardieu)
* Tal Pressman (@talpr)
* Vamsi Avula (@avamsi)
* Waleed Khan (@arxanas)
* Yuya Nishihara (@yuja)
* Aleksandr Mikhailov (@AM5800)
* Augie Fackler (@durin42)
* Benjamin Saunders (@Ralith)
* Daniel Ploch (@torquestomp)
* Danny Hooper (@hooper)
* David Barnett (@dbarnett)
* Glen Choo (@chooglen)
* Herby Gillot (@herbygillot)
* Ilya Grigoriev (@ilyagr)
* Luke Granger-Brown (@lukegb)
* Martin von Zweigbergk (@martinvonz)
* Michael Forster (@MForster)
* Philip Metzger (@PhilipMetzger)
* Ruben Slabbert (@rslabbert)
* Samuel Tardieu (@samueltardieu)
* Tal Pressman (@talpr)
* Vamsi Avula (@avamsi)
* Waleed Khan (@arxanas)
* Yuya Nishihara (@yuja)
## [0.6.1] - 2022-12-05
@ -1660,17 +1676,16 @@ No changes, only changed to a released version of the `thrift` crate dependency.
Thanks to the people who made this release happen!
* Martin von Zweigbergk (@martinvonz)
* Benjamin Saunders (@Ralith)
* Yuya Nishihara (@yuja)
* Glen Choo (@chooglen)
* Ilya Grigoriev (@ilyagr)
* Ruben Slabbert (@rslabbert)
* Waleed Khan (@arxanas)
* Sean E. Russell (@xxxserxxx)
* Pranay Sashank (@pranaysashank)
* Luke Granger-Brown (@lukegb)
* Martin von Zweigbergk (@martinvonz)
* Benjamin Saunders (@Ralith)
* Yuya Nishihara (@yuja)
* Glen Choo (@chooglen)
* Ilya Grigoriev (@ilyagr)
* Ruben Slabbert (@rslabbert)
* Waleed Khan (@arxanas)
* Sean E. Russell (@xxxserxxx)
* Pranay Sashank (@pranaysashank)
* Luke Granger-Brown (@lukegb)
## [0.5.1] - 2022-10-17
@ -1935,9 +1950,9 @@ No changes, only trying to get the automated build to work.
### Fixed bugs
- Fixed crash when `core.excludesFile` pointed to nonexistent file, and made
leading `~/` in that config expand to `$HOME/`
[#131](https://github.com/martinvonz/jj/issues/131)
- Fixed crash when `core.excludesFile` pointed to nonexistent file, and made
leading `~/` in that config expand to `$HOME/`
[#131](https://github.com/martinvonz/jj/issues/131)
## [0.3.0] - 2022-03-12

View file

@ -100,6 +100,7 @@ pub(crate) fn cmd_move(
SquashedDescription::Combine,
false,
&args.paths,
false,
)?;
tx.finish(ui, tx_description)?;
Ok(())

View file

@ -38,8 +38,8 @@ use crate::ui::Ui;
/// commit to the grandparent.
///
/// If, after moving changes out, the source revision is empty compared to its
/// parent(s), it will be abandoned. Without `--interactive`, the source
/// revision will always be empty.
/// parent(s), and `--keep-emptied` is not set, it will be abandoned. Without
/// `--interactive` or paths, the source revision will always be empty.
///
/// If the source became empty and both the source and destination had a
/// non-empty description, you will be asked for the combined description. If
@ -74,6 +74,9 @@ pub(crate) struct SquashArgs {
/// Move only changes to these paths (instead of all paths)
#[arg(conflicts_with_all = ["interactive", "tool"], value_hint = clap::ValueHint::AnyPath)]
paths: Vec<String>,
/// The source revision will not be abandoned
#[arg(long)]
keep_emptied: bool,
}
#[instrument(skip_all)]
@ -132,6 +135,7 @@ pub(crate) fn cmd_squash(
SquashedDescription::from_args(args),
args.revision.is_none() && args.from.is_empty() && args.into.is_none(),
&args.paths,
args.keep_emptied,
)?;
tx.finish(ui, tx_description)?;
Ok(())
@ -177,6 +181,7 @@ pub fn move_diff(
description: SquashedDescription,
no_rev_arg: bool,
path_arg: &[String],
keep_emptied: bool,
) -> Result<(), CommandError> {
tx.base_workspace_helper()
.check_rewritable(sources.iter().chain(std::iter::once(destination)).ids())?;
@ -210,7 +215,7 @@ from the source will be moved into the destination.
let selected_tree_id =
diff_selector.select(&parent_tree, &source_tree, matcher, Some(&instructions))?;
let selected_tree = tx.repo().store().get_root_tree(&selected_tree_id)?;
let abandon = selected_tree.id() == source_tree.id();
let abandon = !keep_emptied && selected_tree.id() == source_tree.id();
if !abandon && selected_tree_id == parent_tree.id() {
// Nothing selected from this commit. If it's abandoned (i.e. already empty), we
// still include it so `jj squash` can be used for abandoning an empty commit in

View file

@ -1732,7 +1732,7 @@ With the `-r` option, moves the changes from the specified revision to the paren
With the `--from` and/or `--into` options, moves changes from/to the given revisions. If either is left out, it defaults to the working-copy commit. For example, `jj squash --into @--` moves changes from the working-copy commit to the grandparent.
If, after moving changes out, the source revision is empty compared to its parent(s), it will be abandoned. Without `--interactive`, the source revision will always be empty.
If, after moving changes out, the source revision is empty compared to its parent(s), and `--keep-emptied` is not set, it will be abandoned. Without `--interactive` or paths, the source revision will always be empty.
If the source became empty and both the source and destination had a non-empty description, you will be asked for the combined description. If either was empty, then the other one will be used.
@ -1753,6 +1753,7 @@ If a working-copy commit gets abandoned, it will be given a new, empty commit. T
* `-u`, `--use-destination-message` — Use the description of the destination revision and discard the description(s) of the source revision(s)
* `-i`, `--interactive` — Interactively choose which parts to squash
* `--tool <NAME>` — Specify diff editor to be used (implies --interactive)
* `--keep-emptied` — The source revision will not be abandoned

View file

@ -259,6 +259,49 @@ fn test_squash_partial() {
insta::assert_snapshot!(stdout, @"");
}
#[test]
fn test_squash_keep_emptied() {
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");
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
// Test the setup
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
@ 382c9bad7d42 c
d5d59175b481 b
184ddbcce5a9 a
000000000000 (empty)
"###);
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["squash", "-r", "b", "--keep-emptied"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Rebased 2 descendant commits
Working copy now at: mzvwutvl 7ee7f18a c | (no description set)
Parent commit : kkmpptxz 9490bd7f b | (empty) (no description set)
"###);
// With --keep-emptied, b remains even though it is now empty.
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
@ 7ee7f18a5223 c
9490bd7f1e6a b (empty)
53bf93080518 a
000000000000 (empty)
"###);
let stdout = test_env.jj_cmd_success(&repo_path, &["file", "show", "file1", "-r", "a"]);
insta::assert_snapshot!(stdout, @r###"
b
"###);
}
#[test]
fn test_squash_from_to() {
let test_env = TestEnvironment::default();