-
-
Notifications
You must be signed in to change notification settings - Fork 313
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
gix clean -xde
deletes the repo's own hidden nested worktrees, but they are not really hidden
#1469
Comments
Thanks for bringing this up! It's true that worktrees in hidden directories would themselves be hidden, and thus could be removed as part of the warning
The algorithm has all the capabilities needed to handle this correctly. Instead of not descending into an ignored directory, it could decide to descend if it detects an included (i.e.
I agree, and this analogy might be a reason that implementing this is easier as one might think after all, if the right classification is found. Out of the back of my head, I really don't know how it works exactly 😅.
Indeed, How to proceed from hereIf possible, would you contribute the documentation change that bluntly alters the warning to also mention worktrees? That way people who have setups like this, worktrees in ignored directories, would be more specifically warned. Then I'd leave this issue open and see if there is demand by users for fixing this properly, because like I said, technically it's all there and it's just a matter of adding a new test - from there the change could 'write itself' especially once it's understood how tracked files in ignored directories cause the algorithm to descend. This might be key for a simple fix, and maybe it's something you would like to try - I'd encourage it only if you think there is something else to learn though. For today, I definitely don't feel like tackling this, but I might return here even before there is user demand as the fix might be easy. For good measure, I will open a PR that at least tests the status quo and maybe play around with it real quick for a chance to a simple fix. |
Actually, I will post a fix for that in a moment, no need to adjust the warning message in that regard. |
Here is how this looks now:
Without the fix, it would delete |
This does not need to get in the way of that, but I'll still open a draft PR with the already-done wording changes, because I did them together with changes to how the relevant options are documented in help text, some of which are relevant even in the absence of this, and this requires no extra effort since I was already just about to click the button to create it. I had been saying I'd update the help text for It may be that no part of those changes will be worthwhile and I will have no objection to the PR being closed without merging, which I may even manage to do shortly myself if the situation is clear enough. If some part of them are good then they can either be included elsewhere (and the PR still closed) or the PR can be modified appropriately. |
Actually, this was fixed by #1470. |
Since GitoxideLabs#1470 (for GitoxideLabs#1469), the repository's own nested worktrees are no longer removed when using `gix clean`, even if they are nested arbitarily under ignored directories. So no new mention of worktrees (separate from "repositories") in the help and warning message is accurate or required. This removes that, which means really we are keeping the warning message the same as it had been earlier, while still otherwise bringing in new explanatory text in the `gix clean` options help.
Since GitoxideLabs#1470 (for GitoxideLabs#1469), the repository's own nested worktrees are no longer removed when using `gix clean`, even if they are nested arbitarily under ignored directories. So no new mention of worktrees (separate from "repositories") in the help and warning message is accurate or required. This removes that, which means really we are keeping the warning message the same as it had been earlier, while still otherwise bringing in new explanatory text in the `gix clean` options help.
Since GitoxideLabs#1470 (for GitoxideLabs#1469), the repository's own nested worktrees are no longer removed when using `gix clean`, even if they are nested arbitarily under ignored directories. So no new mention of worktrees (separate from "repositories") in the help and warning message is accurate or required. This removes that, which means really we are keeping the warning message the same as it had been earlier, while still otherwise bringing in new explanatory text in the `gix clean` options help.
Since GitoxideLabs#1470 (for GitoxideLabs#1469), the repository's own nested worktrees are no longer removed when using `gix clean`, even if they are nested arbitarily under ignored directories. So no new mention of worktrees (separate from "repositories") in the help and warning message is accurate or required. This removes that, which means really we are keeping the warning message the same as it had been earlier, while still otherwise bringing in new explanatory text in the `gix clean` options help.
Current behavior 😯
#1465 fixed #1464 by checking if a git repository encountered during traversal is a worktree of the current repository and declining to delete it
even ifeven if-p
is passed-r
is passed, and also even if-x
and-d
are passed to delete ignored directories. This protects the repository's own worktrees, even if nested, provided that they are encountered during traversal rather than being present below a directory that is found during traversal and determined to be ignored.As described in #1464 (comment),
gix clean
continues to require--skip-hidden-repositories
to avoid deleting nested repositories that require full traversal to discover, and this is important for performance. This behavior holds even when those nested repositories are worktrees of the current repository.But worktrees of the current repository, regardless of their location, should never require much work to discover. This is because the repository knows where its worktrees are. For example, a non-bare repository with
git worktree
managed worktrees, if it is not a submodule, has a.git
directory with aworktrees
subdirectory that contains information about its worktrees.Whether a directory contains any descendants that are worktrees of the current repository should likewise be efficient to determine and likewise does not require full traversal.
Broad implementation idea
I suspect that either there is a simpler and more elegant approach, or maybe I am just expressing this idea poorly and it can be implemented simply? I am not sure. I present this more to clarify why I believe this can be achieved efficiently than to argue for a particular algorithm.
At the beginning of traversal, before actually beginning the walk:
.git/worktrees
directory or equivalent and make a list of its worktrees.gix clean
is operating on. If feasible, remove any that are outside the part of it thatgix clean
is operating on, if that is not the whole thing.For elaboration on that last pre-step:
git add -f
).Then perform the walk and use the knowledge of where the worktrees are and which paths are ancestors of them to refrain from deleting an entire directory tree if any of the repository's own worktrees are anywhere inside it, while still deleting all other files that are eligible for deletion.
Complexity and connection to reusable library features
If this cannot be done in a reasonably simple way, then it might be judged not to be justified on the grounds that it is rarely needed.
However, whether or not that is the case, I wonder if this would become simple if expressed in terms of new directory walk features that would themselves have other applications.
Or maybe it is already simple and my unfamiliarity with the code involved--this is very much a part of the code that I am less familiar with--is what makes it seem complicated to me.
Expected behavior 🤔
Deleting nested worktrees of the same repository, no matter how deep under ignored directories, is something I do not expect to happen. I think the expected behavior is to preserve them. I have two reasons to think so.
1. On hiddenness - analogy to tracked files under ignored directories
As briefly alluded to above, even in the absence of multiple worktrees, one can have tracked files nested arbitrarily deep inside ignored directories by adding their
.gitignore
entries later or by usinggit add -f
. These files are preserved bygix clean
, which has efficient access to knowledge of their existence because their locations, and thus knowledge of their ancestor directories, is present in the repository without requiring a full traversal.Of course, this analogy breaks down in some ways, since there are Git tree objects representing those intermediate directories, while the repository's knowledge of its own
git worktree
managed worktrees is, as far as I know, only ever through its knowledge of their paths. But tree objects don't exist for intermediate directories under which all tracked files are staged but not committed--andgix clean
seems to always do fine with this--so perhaps this analogy is not so bad even at a technical level?Either way, I think the analogy holds in terms of what is intuitive to users, as well as what is being described informationally by the characterization of a directory as hidden.
Since
gix clean
handles that, andgix clean
also seeks to avoid deleting any worktrees of the current repository, I think the intuitively expected behavior is to treat them the same way.2. On performance - inferring expectation from design intent
Because the repository's worktrees are never hidden in the sense of requiring a dirwalk or other inherently slow operations to find them, users who are aware of the performance considerations related to
--skip-hidden-repositories
may intuitively assume that the repository's own worktrees are protected even without it.This assumption would hold even if the implementation details required to protect them efficiently turn out to be unworthwhile. Of course, that does not imply that implementing it must be worthwhile. Further documentation changes could instead be made to avoid giving the impression that they would be protected.
Maybe there are simpler alternatives?
All the foregoing text considers simplicity in terms of whether the behavior I am advocating for could be done in an acceptably simple way. But maybe there is a different improvement that could be made that is inherently simpler.
One idea: The message shown when
-xdn
is passed without--skip-hidden-repositories
is itself clear with respect to separate repositories in ignored directories. Suppose the repository has other worktrees of its own (besides the one being operated in) whose parent directories appear to match any.gitignore
entry. Then that message could be augmented to also cover that. This could be by the addition of a separate trailing sentence or paragraph, or even just by adjusting its wording to say "repositories or worktrees" or something.Another idea is to always have it contain that augmentation, but I think that might be more confusing, and less useful as a reminder that the situation might really apply.
Git behavior
I recently learned that
git clean
accepts-f
twice in which case it does remove nested repositories. When passed with-d
and-x
, this removes ignored nested worktrees as well, both those that are directly visible inside a non-ignored parent directory, and those that are deeper down.But when using only documented features,
git clean
avoids deleting any nested repositories, even those that are unrelated to the current repository. In contrast,gix clean
offers this as a feature explicitly, and provides options to control it.I think both of the above points are of low relevance to determining how
gix
should behave in the specific case this issue covers, and that thegit
behavior, to the extent that it is related, argues neither for nor against the proposal here.Steps to reproduce 🕹
Instructions
I did the following on an Ubuntu 22.04 LTS system.
Build and installing
gitoxide
from the tip of themain
branch, making sure the build is from code that included the changes from #1465.Create a repository specifying an ignored path that will be used for a subdirectory:
Create a worktree in a directory inside that ignored directory, so that the worktree's root is a subdirectory of it:
See what
git clean
would do with-x
and-d
, then observe that it does it:This shows that the worktree is gone, even though it is a worktree of the current repository rather than being an unrelated nested repository.
With output
Here's a transcript of the above, showing the output:
The text was updated successfully, but these errors were encountered: