Skip to content

fix(git): Remove Files.isHidden guard in AddExcludedFilesToIndex::prepare#346

Open
ytausch wants to merge 1 commit into
google:masterfrom
ytausch:remove-files-is-hidden
Open

fix(git): Remove Files.isHidden guard in AddExcludedFilesToIndex::prepare#346
ytausch wants to merge 1 commit into
google:masterfrom
ytausch:remove-files-is-hidden

Conversation

@ytausch

@ytausch ytausch commented Jun 17, 2026

Copy link
Copy Markdown

The goal of prepare() is to prepare a TreeSet toExclude which covers a set of arguments to pass to git add that cover all destination-only files in HEAD, without sweeping in any origin-owned file.

A check in line 73 defensively influences the algorithm to not assume that a git add dir also adds dir/.file, which is indicated in a surrounding comment:

if (Files.isHidden(relative)) {
// File is not included but 'git add dir' doesn't work for 'dir/.file'.
addPathAndParents(included, relative.getParent());
}

Therefore, in a minimal example, where tools is destination-owned and contains tools/.keep and tools/script.sh, we would end up with toExclude = {tools/.keep, tools/script.sh}.

However, git does not behave like indicated and a git add dir also adds any hidden subdirectories or files. Thus, it would be sufficient to run git add tools in the example above and not git add tools/.keep tools/script.sh. The code is overdefensive.

Therefore, this PR removes the isHidden check.

The reason why I am fixing this is that, also, Files.isHidden(relative) is broken on Windows: While on POSIX, isHidden simply checks if the basename starts with a dot, it checks a filesystem attribute on Windows. However, since the file path is relative, this happens relative to the current working directory of the JVM, which is not the checked-out repository. This issue could alternatively be fixed by resolving the file path first, but removing the isHidden check is the correct fix.

Testing

I added a regression test, but I am not sure whether you run the CI on Windows as well. I still think it makes sense to keep.

…prepare`

The goal of prepare() is to prepare a TreeSet<Path> `toExclude` which covers a set of arguments to pass to `git add` that cover all *destination-only* files in HEAD, without sweeping in any origin-owned file.

A check in line 73 defensively influences the algorithm to not assume that a `git add dir` also adds `dir/.file`, which is indicated in a surrounding comment.

Therefore, in a minimal example, where `tools` is destination-owned and contains `tools/.keep` and `tools/script.sh`, we would end up with `toExclude = {tools/.keep, tools/script.sh}`.

However, git does not behave like indicated and a `git add dir` also adds any hidden subdirectories or files. Thus, it would be sufficient to run `git add tools` in the example above and not `git add tools/.keep tools/script.sh`. The code is overdefensive.

The reason why I am fixing this is that, also, `Files.isHidden(relative)` is broken on Windows: While on POSIX, `isHidden` simply checks if the basename starts with a dot, it checks a filesystem attribute. However, since the file path is relative, this happens relative to the current working directory of the JVM, which is not the checked-out repository. This issue could alternatively be resolved by resolving the file path first, but removing the `isHidden` check is the correct fix.
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.

1 participant