Skip to content

git-lfs: ignore filtered files in .gitattributes during snapshot#9068

Open
kejadlen wants to merge 3 commits intojj-vcs:mainfrom
kejadlen:lfs
Open

git-lfs: ignore filtered files in .gitattributes during snapshot#9068
kejadlen wants to merge 3 commits intojj-vcs:mainfrom
kejadlen:lfs

Conversation

@kejadlen
Copy link
Contributor

@kejadlen kejadlen commented Mar 9, 2026

Partially addresses #80 by ignoring files matched by configurable .gitattributes filter attributes during snapshot. This lets users work with Git LFS (and git-crypt, etc.) repos in jj by excluding filtered files from tracking, deferring actual file handling to the external tool (e.g. git lfs pull).

History

This work builds on several prior attempts to bring LFS support to jj:

This PR picks up where #7098 left off, per #7098 (comment).

Approach

A new git.ignore-filters setting (defaulting to ["lfs"]) names .gitattributes filter attributes whose matching files should be excluded from snapshots. During snapshot, the working copy reads .gitattributes files from both disk and the tree store, matches paths against gix-attributes, and skips files whose filter attribute matches a configured ignore filter. Skipped files are also omitted from the deleted-files check so they don't appear as spuriously removed.

This only affects the snapshot path (disk → store). Checkout (store → disk) is unaffected, which is intentional: files are still checked out normally so that git lfs pull works afterward.

Known limitations

  • All .gitattributes files in the repo are parsed on every snapshot, regardless of which directories changed.
  • Symlinked .gitattributes files are followed (matching jj's current .gitignore behavior, but diverging from git).
  • No checkout-path filtering — this is snapshot-only.

These are acceptable tradeoffs for an initial implementation and can be refined alongside the broader gitattributes design (#7164, #8144).

Checklist

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, demos/)
  • I have updated the config schema (cli/src/config-schema.json)
  • I have added/updated tests to cover my changes
  • I fully understand the code that I am submitting (what it does,
    how it works, how it's organized), including any code drafted by an LLM.
  • For any prose generated by an LLM, I have proof-read and copy-edited with
    an eye towards deleting anything that is irrelevant, clarifying anything
    that is confusing, and adding details that are relevant. This includes,
    for example, commit descriptions, PR descriptions, and code comments.

(PR summary assisted by Claude Opus 4.6 via pi)

@kejadlen kejadlen requested a review from a team as a code owner March 9, 2026 19:40
@kejadlen kejadlen mentioned this pull request Mar 9, 2026
4 tasks
@kejadlen kejadlen force-pushed the lfs branch 7 times, most recently from 8babab8 to 1d5d597 Compare March 10, 2026 22:27
ignore_filters: &HashSet<String>,
priority: SearchPriority,
) -> bool {
let Ok(result) = self.search(path, ["filter"], priority).await else {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Dropping the Err path here, not sure if this should propagate an error up?

sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 13, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 13, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 13, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 13, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 13, 2026
sjawhar added a commit that referenced this pull request Mar 16, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 16, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 16, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 16, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Mar 16, 2026
@PhilipMetzger
Copy link
Contributor

@kejadlen small q, did you already address the comments from Martin in Gustav's PR here? There's also the lingering question from @06393993 to which the maintainers will need to have an answer for. Thanks.

@kejadlen
Copy link
Contributor Author

I believe I addressed Martin's comments, but I missed this if that's what you're referring to?

@martinvonz
Copy link
Member

I don't know if that's what Philip was referring to, but what's your answer to it anyway? Is it correct that this implementation doesn't handle the update case? What does that even mean? I thought we already handle the update case. Maybe @06393993 can explain what it is that doesn't work.

@06393993
Copy link
Contributor

06393993 commented Mar 20, 2026

What does that even mean? I thought we already handle the update case.

From #9068 (comment):

This only affects the snapshot path (disk → store). Checkout (store → disk) is unaffected, which is intentional: files are still checked out normally so that git lfs pull works afterward.

I am not sure what "already handle the update case" means.

Given that the update path is unaffected, the original questions in #7098 (review) are still valid:

  1. We need maintainers' explicit approval on this confusing behavior.
  2. We should evaluate how this would influence the file_states cache in the TreeState proto.
  3. We need extra document to explain unexpected behaviors. At least for the following case: if the user removes a file ignored in a revision, jumps to a different revision, and jumps back to the revision, they will see that the file appears again and is not removed.

@martinvonz
Copy link
Member

I am not sure what "already handle the update case" means.

Never mind, I was just confused. Sorry.

It sounds like many users are fine with the current PR even though it's limited, so I think it seems fine to get it merged as is. Sorry that I still haven't taken the time to review it.

// See the License for the specific language governing permissions and
// limitations under the License.

#![expect(missing_docs)]
Copy link
Member

Choose a reason for hiding this comment

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

Please document it instead. We use these attributes only for old code that hasn't been documented yet.

Copy link
Member

Choose a reason for hiding this comment

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

git-attributes: add git attributes file support

Could you add some more detail? Reading this, it's not at all obvious what to expect from the patch. I see that there's a FileLoader trait and bunch of switching between loading from disk or tree. It would be good to explain the rationale behind that.

Copy link
Member

Choose a reason for hiding this comment

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

From description:

git-lfs: access git attributes to ignore filtered files

Can you elaborate? What did we do in the previous patch if we didn't do this?

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.

5 participants