Skip to content

Conversation

@thomasa88
Copy link

Replaces #8176

Fixes #8065.

This commit fixes the problem of jj marking a git submodule as a deleted path,
after the user moves (edit/new) to a commit where the submodule did not exist
and then back to a commit where it existed. Failure to remove a
submodule's directory is no longer considered a conflict - if it was not going
to be replaced by another file.

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • N/A I have updated the documentation (README.md, docs/, demos/)
  • N/A I have updated the config schema (cli/src/config-schema.json)
  • I have added/updated tests to cover my changes

Comment on lines +2013 to +2216
/////// This should only print if files will be found as added --- so check if the submodule path is ignored? How? Can UI print it instead?
if matches!(before.as_normal(), Some(TreeValue::GitSubmodule(_))) {
eprintln!(
"Files from the submodule will appear as added. Add the submodule to `.git/info/exclude` and run `jj file untrack` to ignore the directory contents."
);
}
Copy link
Author

@thomasa88 thomasa88 Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if needs correct logic to check if the path is ignored. Or we just drop the print.

Ideally, I guess some UI code should do the print, but submodule warnings are already printed from the current file and real submodule support is coming to jj in the future.

@thomasa88 thomasa88 force-pushed the existing-submod-ok branch 2 times, most recently from 926a6c5 to 547f80c Compare December 6, 2025 08:22
…eckout

The removal part allows non-initialized submodules to be replaced by files upon
checkout, without leading to a conflict. The add is included for symmetry and to
be more in line with Git.

It is safe to remove an empty submodule directory, as there can be no untracked
info that is lost. If a submodule directory is non-empty, it cannot be safely
removed, as jj does not know the state of the repository in the submodule.

For non-empty directories being in the way of a file, the user will have to
remove the directory and then run `jj restore --from xxxxxx`, as instructed in
the conflict information during the checkout.
Fixes jj-vcs#8065.

This commit fixes the problem of jj marking a git submodule as a deleted path,
after the user moves (edit/new) to a commit where the submodule did not exist
and then back to a commit where it existed. Failure to remove a
submodule's directory is no longer considered a conflict - if it was not going
to be replaced by another file.


The following transition cases during checkout have been modified:


disk: non-commited directory
before: <don't care>
after: submodule

Problem: update() would try to remove the non-empty directory and fail,
indicating a conflict to the user.

Fix: Consider a submodule checkout to be successful even if a directory exists
at the submodule's path. In fact, assume that the directory is the submodule's
directory (possibly left over when moving between commits in the past). This is
in line with Git's behavior.


disk: -
before: submodule
after: submodule/file removed

Problem: update() would try to remove the non-empty directory and fail,
indicating a conflict to the user.

Fix: Consider a failure to remove a submodule directory to not be a failure, if
the commit does not need to put another file in the submodule's place.

In the general case, failing to remove a file, that should not exist after the
checkout is complete, is a failure. However, for a (previous) submodule
directory, there is no safe way to do the remove, as it could contain
non-commited or local-only changes. Therefore, in the case of the commit not
wanting to place a new file at the same path, consider the checkout of the
removed submodule successful. This is in line with Git's behavior.

Note: If the user has forgotten to mark the submodule directory as ignored/
excluded, the directory contents will be picked up as new files (status: `A
<file>`) when the user checks out a commit without the submodule. This behavior
already existed before the change. There is no way for jj to know of "files that
might at some point belong to a submodule but currently doesn't". The solution
for the user is to ignore the submodule directory (e.g. .git/info/exclude).
Handy when the user moves between commits containing and not containing a
certain submodule.
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.

Cannot untrack rediscovered git submodule

1 participant