Skip to content

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

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

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

Conversation

@kejadlen

@kejadlen kejadlen commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

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
Comment thread lib/src/gitattributes.rs
ignore_filters: &HashSet<String>,
priority: SearchPriority,
) -> bool {
let Ok(result) = self.search(path, ["filter"], priority).await else {

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor Author

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

@martinvonz

Copy link
Copy Markdown
Contributor

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

06393993 commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Contributor

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.

Comment thread lib/src/gitattributes.rs
// See the License for the specific language governing permissions and
// limitations under the License.

#![expect(missing_docs)]

Copy link
Copy Markdown
Contributor

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.

Comment thread lib/src/gitattributes.rs

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Contributor

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?

@PhilipMetzger

Copy link
Copy Markdown
Contributor

, but I missed this if that's what you're referring to?

yes, this is pretty much it.

@martinvonz martinvonz mentioned this pull request Mar 21, 2026
6 tasks
sjawhar added a commit that referenced this pull request Mar 26, 2026
CSharperMantle added a commit to CSharperMantle/hdu2026_os_exp that referenced this pull request Apr 4, 2026
Link: https://stackoverflow.com/a/41961459 ("Move Git LFS tracked files
 under regular Git")
Link: jj-vcs/jj#80 ("Add support for Git LFS")
Link: jj-vcs/jj#9068 ("git-lfs: ignore filtered
 files in .gitattributes during snapshot")
sjawhar added a commit that referenced this pull request Apr 12, 2026
sjawhar added a commit that referenced this pull request Apr 12, 2026
@raylu

raylu commented May 1, 2026

Copy link
Copy Markdown
Contributor

one-line fix for the compilation error: raylu@5eb8aad
also, in case anyone wants to try this branch: https://github.com/raylu/jj/releases/tag/0.40.0-kejadlen

@sbarfurth

sbarfurth commented May 1, 2026

Copy link
Copy Markdown
Contributor

I also uploaded a working branch to this repo that's based on the latest non-working snap of this PR:

@kejadlen
kejadlen force-pushed the lfs branch 2 times, most recently from 33216b7 to b31efce Compare May 1, 2026 13:54
@pm-gusmano

Copy link
Copy Markdown

I wanted to mention I'm really excited to see this feature implemented! LFS is one of the biggest sticking points in my mind when I try to evangelize jj 😁. Keep up the good work!

legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request May 25, 2026
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request May 25, 2026
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request May 25, 2026
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request May 25, 2026
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request May 25, 2026
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request May 26, 2026
@sbarfurth

Copy link
Copy Markdown
Contributor

As a backup and given the willingness of maintainers, I have adapted this PR into #9635. It squashes the multiple commits in this PR.

I've also attempted to address the comments from @martinvonz around documentation. I will happily drive my PR forward as many people in my organization are relying on this patched version and I want to lower the friction. I'm also happy to drop my PR and support here if that's better, but it seems this has been dormant for over a month now.

lsp-ableton added a commit to lsp-ableton/jj that referenced this pull request Jun 23, 2026
jj-vcs#9068 was written against jj 0.40. Adapt to 0.42:
- FileLoader uses futures::AsyncRead (Pin<Box<...>>) to match
  Store::read_file; drop the removed file_util::BlockingAsyncReader
  (read .gitattributes fully into a futures::io::Cursor).
- make tokio a non-optional jj-lib dep (gitattributes uses
  tokio::sync::OnceCell unconditionally).
- drop an unused dag_walk_async import.
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request Jul 13, 2026
sjawhar added a commit to sjawhar/jj that referenced this pull request Jul 13, 2026
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request Jul 22, 2026
legion-implementer Bot pushed a commit to sjawhar/jj that referenced this pull request Jul 22, 2026
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.

8 participants