-
-
Notifications
You must be signed in to change notification settings - Fork 344
gix clean
with -r
or -xd
deletes the repo's own nested worktrees
#1464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
gix clean
commands readily delete the repo's own nested worktreesgix clean
with -p
or -xd
can delete the repo's own nested worktrees
gix clean
with -p
or -xd
can delete the repo's own nested worktreesgix clean
with -r
or -xd
can delete the repo's own nested worktrees
gix clean
with -r
or -xd
can delete the repo's own nested worktreesgix clean
with -r
or -xd
deletes the repo's own nested worktrees
Thanks so much for researching this and the deep analysis - I was particularly impressed by thinking of submodules that have worktrees in the superproject. Regarding the behaviour of With that said, I also believe that it should never touch the worktrees of the repository it is run in, while being unsure of what to do with worktrees of submodules that are reaching into the superproject. My take here is that it would probably be so unlikely that it basically never happens, and if it does it's more of an accident. As such, it should probably show up as eligible to be cleaned. If one day that shouldn't be desired anymore, then implementing this will be trivial by collecting worktrees of all submodules recursively as well. I see two points of action here:
|
Thanks--I was totally unaware of
It occurs to me--and maybe this is what you're already thinking of--that there is case where a submodule's But I guess when doing this one would know they are ignored and not run
Is this just for top-level ignored directories (i.e. those that are not subdirectories of ignored directories and that are ignored because they match an ignore pattern)? If it applies to git repositories in all ignored directories no matter how deep down, then it would make it easier to understand |
Yes, precious files would add a layer of protection (even though you shouldn't take my word for it :)), even though with the already implemented change it would at least detect directly ignored repositories as such, so one has to
No, it's just for the top-level, no nesting. Indeed, this is for performance reasons and there is that warning indicating that ignored directories may include repositories (but they may not be one anymore). This performance I really must protect, as for instance in GitButler with Interestingly,
|
That way it's possibel for them to be equivalent to submodules, which would never be deleted by accident due to their 'tracked' status. This works by passing repository-relative paths of worktree locations that are within this repository.
Please note that this was implemented as breaking change, which will prevent me from publishing a patch release unfortunately. Thus this fix will be released in a month or two with the next regular 'breaking' one. Technically, this is breaking just for |
I've verified that the changes to
I've opened #1469 to suggest further protection for the repository's own worktrees (no matter what they are nested under) that I think need not make things significantly slower. |
…deLabs#1464) That way it's possibel for them to be equivalent to submodules, which would never be deleted by accident due to their 'tracked' status. This works by passing repository-relative paths of worktree locations that are within this repository.
Current behavior 😯
When a worktree has been created with
git worktree add
inside the repository,gix clean
treats it the same as any untracked nested repository, even though it is a working tree of the current repository.gix clean -re
will delete it.*
is listed in.gitignore
, thengix clean -xde
will also delete it, even without-r
.In both cases, this happens even if there is no intermediate ignored directory.
Significance
Users shouldn't usually create worktrees nested inside the main worktree (or inside each other). But it is supported to do so, and users may occasionally do so deliberately.
It is also easy to do by accident if one is not experienced with
git worktree
, since the one-argument form ofgit worktree add
takes a path from which a branch is inferred, rather than taking a branch.git worktree mybranch
creates amybranch
branch if it does not exist, and creates a worktree for it in themybranch
subdirectory of the current directory.Since such a worktree works fine and does not usually interfere with the main worktree, even though the user may have meant to write
git worktree ../mybranch
, the user may proceed to use the nested worktree and to rely on data there not being lost due to cleaning in the main worktree.In addition to being an area where I think the behavior is unexpected and carries some risk of inadvertent data loss, the question of how
gix clean
should treat nested worktrees is relevant to improving the help text for-r
(especially if the recommendation I make below that they be given the same protection as submodule working trees is not followed).Relationship to #1458
In all observations and manual testing described in this issue, I made sure to use a build containing the changes from #1462.
#1462 did fix #1458. The case in this issue is something I had not thought of at that time and did not include in #1458. This issue may be seen as a sequel to that one.
Expected behavior 🤔
It seems to me that:
git worktree
should be protected to the same degree as submodules' working trees.gix clean
is run in should ever be removed by anygix clean
command, regardless of the options passed.It seems to me that this can be avoided without much overhead even for worktrees that are nested inside ignored directories, because worktrees are discoverable by examining the repository.
(They have directories in
.git/worktrees
. This is of course with the usual variations when$GIT_DIR
has a nonstandard value, or when.git
is a regular file due to them being worktrees of a submodule.)Edge cases
Strange edge cases are possible, such as a submodule with a
git worktree
managed worktree in a subdirectory of its superproject's working tree or of a sibling submodule's working tree, or a superproject with agit worktree
managed worktree in a subdirectory of a submodule's working tree.I am not sure what to expect, for what happens when
gix clean
is run the repository whose working tree contains the related repository's extra worktree. I lean slightly toward thinking it should be deleted in this situation, if a nested repository would otherwise be deleted. This seems like the simplest approach to implement.I do not think these edge cases, even if the related repository's working tree is still to be deleted, challenge the expectations given above.
git worktree
managed working trees.gix clean
does not and should not remove submodules is that they are tracked. This is different from the reasongix clean
should not remove its own worktrees, which is that they have the same status as the repository's own main working tree or.git
directory.-r
and in some cases without-r
when also ignored.When the current repository is a submodule, of course its own
git worktree
managed working trees should be protected from deletion whengit clean
commands are run within it. That's conceptually identical to a situation withgit worktree
managed worktrees where no submodules are involved in any way. The only difference is that to find out where to look to find out where the worktrees are, we have to follow the path in the.git
file (or use a mechanism that already takes care of this).Git behavior
git clean
does not remove them with any combination of options.As in #1458, this is area where
git
behavior is not decisive becausegit clean
does not remove nested repositories, ignored or otherwise. However, also as in #1458, thegit clean
behavior is is relevant here because of the expectations it sets about what cleaning means.Steps to reproduce 🕹
With
-r
and not-x
or-d
– instructionsCreate a repository with at least one commit:
Add a worktree for a new feature branch, but place it inside the main worktree instead of alongside it as would ordinarily be preferable:
Observe that, even though
git status
reports it as untracked,git clean
will not remove it, and that, forgit clean
, the reason appears to be that it regards it as a nested repository (optionally use-f
instead of-n
):git status git clean -dn git clean -xdn git status git add . git status
Unstage and check that the situation is back to where it was when the worktree was added:
See what
gix clean
would do, and that it really does it, deleting themybranch
subdirectory that belonged to agit worktree
managed working tree:With
-r
and not-x
or-d
– with outputHere's all that, with output:
Without
-r
, and with-x
and-d
, when.gitignore
has*
– instructionsThis can be done as a variation on the above example, for which separate explication may not be required. This instead produces it on a real-world repository that lists
*
followed by!
exclusions--thecargo-update
repository that was also used as an example in #1458.Get the repository and observe what it ignores:
git clone https://github.com/nabijaczleweli/cargo-update.git cd cargo-update cat .gitignore
Observe that #1458 is fixed (#1462):
Create a nested worktree:
Verify that
git clean
does not delete it, even when told to remove directories and ignored entries:Use a
gix clean
command to delete it, even though this is expected to delete some nested repositories but is intended not to delete any of our worktrees, and verify that it is gone:Without
-r
, and with-x
and-d
, when.gitignore
has*
– outputHere's all that, with output:
The text was updated successfully, but these errors were encountered: