-
Notifications
You must be signed in to change notification settings - Fork 412
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FAQ: detailed example for the "accidentally changed files in the wron…
…g commit" question It was requested on Discord once. The result is almost a tutorial; we could consider actually moving it into the tutorial and providing a link in the FAQ. That could be done separately. The `jj` commands outputs are faked in a few, hopefully inconspicuous, ways. Hopefully, this is not distracting.
- Loading branch information
Showing
1 changed file
with
180 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -298,14 +298,184 @@ jj config set --user git.private-commits "'''description(glob:'private:*')'''" | |
|
||
### I accidentally changed files in the wrong commit, how do I move the recent changes into another commit? | ||
|
||
Use `jj evolog -p` to see how your working-copy commit has evolved. Find the | ||
commit you want to restore the contents to. Let's say the current commit (with | ||
the changes intended for a new commit) are in commit X and the state you wanted | ||
is in commit Y. Note the commit id (normally in blue at the end of the line in | ||
the log output) of each of them. Now use `jj new` to create a new working-copy | ||
commit, then run `jj restore --from Y --into @-` to restore the parent commit | ||
to the old state, and `jj restore --from X` to restore the new working-copy | ||
commit to the new state. | ||
Let's say we are editing a commit for "featureA", and we forgot to run `jj | ||
new` or `jj commit` before doing some work that belongs in a new commit: | ||
|
||
```console | ||
$ jj log | ||
@ lnvvtrzo [email protected] 2025-02-28 21:01:10 31a347e0 | ||
│ featureA | ||
◆ zzzzzzzz root() 00000000 | ||
$ cat file # Oh no, the work on "feature B" should be in a separate commit! | ||
Done with feature A | ||
Working on feature B | ||
``` | ||
|
||
#### Step 1: Find the commit id for the "last good version" | ||
|
||
<!-- TODO: Reorganize the two related questions, this one and | ||
-- the one linked below | ||
--> | ||
You can find [all the past versions of the working copy revision that `jj` has | ||
saved](#jj-is-said-to-record-the-working-copy-after-jj-log-and-every-other-command-where-can-i-see-these-automatic-saves) | ||
by running `jj evolog`. The obsolete versions will be marked as "hidden" and | ||
will have the same change id, but will have different commit ids. This | ||
represents different [commits] that are all parts of the same [change]. | ||
|
||
For example, this is what the evolog might look like after you made two edits to | ||
the same change: | ||
|
||
```console | ||
$ # Note the word "hidden", the commit ids on the right, | ||
$ # and the unchanging change id on the left. | ||
$ jj evolog | ||
@ lnvvtrzo [email protected] 2025-02-28 21:01:10 31a347e0 | ||
│ featureA | ||
○ lnvvtrzo hidden [email protected] 2025-02-28 21:00:51 b8004ab8 | ||
│ featureA | ||
○ lnvvtrzo hidden [email protected] 2025-02-28 20:50:05 e4d831d | ||
(no description set) | ||
``` | ||
|
||
Since commit `b800` is hidden, it is considered obsolete and `jj log` (without | ||
arguments) will not show it, nor can it be accessed by its change id. However, | ||
most `jj` operations work normally on such commits if you refer to them by their | ||
commit id. | ||
|
||
To find out which of these versions is the last time before we started working | ||
on feature B (the point where we should have created a new change, but failed | ||
to do so), we can look at the actual changes between the `evolog` commits by | ||
running `jj evolog -p`: | ||
|
||
```console | ||
$ # When was the last saved point before we started working on feature B? | ||
$ jj evolog -p --git # We use `--git` to make diffs clear without colors | ||
@ lnvvtrzo [email protected] 2025-02-28 21:01:10 31a347e0 | ||
│ featureA | ||
│ diff --git a/file b/file | ||
│ index 2b455c4207..2a7e05a01a 100644 | ||
│ --- a/file | ||
│ +++ b/file | ||
│ @@ -1,1 +1,2 @@ | ||
│ Done with feature A | ||
│ +Working on feature B | ||
○ lnvvtrzo hidden [email protected] 2025-02-28 21:00:51 b8004ab8 | ||
│ featureA | ||
│ diff --git a/file b/file | ||
│ index cb61245109..2b455c4207 | ||
│ --- a/file | ||
│ +++ b/file | ||
│ @@ -1,1 +1,1 @@ | ||
│ -Working on feature A | ||
│ +Done with feature A | ||
○ lnvvtrzo hidden [email protected] 2025-02-28 20:50:05 e4d831d | ||
(no description set) | ||
diff --git a/file b/file | ||
index 0000000000..cb61245109 | ||
--- /dev/null | ||
+++ b/file | ||
@@ 0,0 +1,1 @@ | ||
+Working on feature A | ||
``` | ||
|
||
The version of the change when we were actually done with "featureA" thus | ||
corresponds to the commit with id `b800`. The following edit (commit `31a3`) | ||
belongs in a new change. | ||
|
||
#### Step 2: Create a new change for the current state and restore the existing change to the older state | ||
|
||
The "featureA" cahnge is currently at commit `31a`: | ||
|
||
```console | ||
$ jj log | ||
@ lnvvtrzo [email protected] 2025-02-28 21:01:10 31a347e0 | ||
│ featureA | ||
◆ zzzzzzzz root() 00000000 | ||
``` | ||
|
||
We'd like to create a new "featureB" change with the contents of the current | ||
commit `31a`, and we'd the "featureA" change to be reverted to its former | ||
state at commit `b80` (see step 1 above for how we found that commit id). | ||
|
||
First, we create a new empty child commit. Since it is empty, it has the same | ||
contents as `31a`. | ||
|
||
```console | ||
$ jj new -m "featureB" | ||
Working copy now at: pvnrkl 47171aa (empty) featureB | ||
Parent commit : lnvvtr 31a347e featureA | ||
$ cat file | ||
Done with feature A | ||
Working on feature B | ||
``` | ||
|
||
Now, we `jj restore` the change `lnvvtr` to its state at commit `b80`. We use | ||
the `--restore-descendants` flag so that the *file contents* (AKA snapshot) of | ||
the "featureB" change is preserved. | ||
|
||
```console | ||
$ # We refer to `lnvvtr` as `@-` for brevity | ||
$ jj restore --from b80 --into @- --restore-descendants | ||
Created lnvvtr 599994e featureA | ||
Rebased 1 descendant commits (while preserving their content) | ||
Working copy now at: pvnrkl 468104c featureB | ||
Parent commit : lnvvtr 599994e featureA | ||
``` | ||
|
||
Even though `@-` was modified, `--restore-descendants` preserved the contents of | ||
the current change: | ||
|
||
```console | ||
$ jj file show -r @ file # Same as `cat file` | ||
Done with feature A | ||
Working on feature B | ||
$ jj file show -r @- file | ||
Done with feature A | ||
``` | ||
|
||
??? info "More details on what `--restore-descendants` does" | ||
|
||
When we ran the `jj restore` command, the working copy change `@` was | ||
at commit `471` and `@` was the only child of `@-`. In this situation, | ||
|
||
```shell | ||
jj restore --from b80 --into @- --restore-descendants | ||
``` | ||
|
||
is equivalent to | ||
|
||
```shell | ||
jj restore --from b80 --into @- | ||
jj restore --from 471 --into @ | ||
``` | ||
|
||
Now, we have achieved the exact state we desired: | ||
|
||
``` | ||
$ jj log -p --git | ||
@ pvnrklkn [email protected] 2025-02-28 21:39:29 468104c2 | ||
│ featureB | ||
│ diff --git a/file b/file | ||
│ index 2b455c4207..2a7e05a01a 100644 | ||
│ --- a/file | ||
│ +++ b/file | ||
│ @@ -1,1 +1,2 @@ | ||
│ Done with feature A | ||
│ +Working on feature B | ||
○ lnvvtrzo [email protected] 2025-02-28 21:39:29 599994ee | ||
│ featureA | ||
│ diff --git a/file b/file | ||
│ new file mode 100644 | ||
│ index 0000000000..2b455c4207 | ||
│ --- /dev/null | ||
│ +++ b/file | ||
│ @@ -0,0 +1,1 @@ | ||
│ +Done with feature A | ||
◆ zzzzzzzz root() 00000000 | ||
$ jj diff --from b80 --to @- # No output means these are identical | ||
$ jj diff --from 31a --to @ # No output means these are identical | ||
``` | ||
|
||
|
||
### How do I resume working on an existing change? | ||
|
||
|
@@ -392,9 +562,11 @@ detect custom backends and more). | |
|
||
[bookmarks_conflicts]: bookmarks.md#conflicts | ||
|
||
[change]: glossary.md#change | ||
[change ID]: glossary.md#change-id | ||
[co-located]: glossary.md#co-located-repos | ||
[commit ID]: glossary.md#commit-id | ||
[commits]: glossary.md#commit | ||
[config]: config.md | ||
|
||
[gerrit-integration]: https://gist.github.com/thoughtpolice/8f2fd36ae17cd11b8e7bd93a70e31ad6 | ||
|