git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: "Kristoffer Haugsbakk" <kristofferhaugsbakk@fastmail.com>
Cc: "Peter Morris" <mrpmorris@gmail.com>,  git@vger.kernel.org
Subject: Re: [RFC] git worktree: use filesystem cloning where supported
Date: Fri, 14 Aug 2026 09:29:24 -0700	[thread overview]
Message-ID: <xmqq4igwpswr.fsf@gitster.g> (raw)
In-Reply-To: <7d0e9933-1a5f-4755-8bc5-fa4fea42f61c@app.fastmail.com> (Kristoffer Haugsbakk's message of "Fri, 14 Aug 2026 12:54:02 +0200")

"Kristoffer Haugsbakk" <kristofferhaugsbakk@fastmail.com> writes:

> On Fri, Aug 14, 2026, at 12:40, Peter Morris wrote:
>> I'd like to suggest a change to how git worktree creates files.
>>
>> # Problem
>>[snip]
>
> https://lore.kernel.org/git/pull.2317.git.git.1780685368.gitgitgadget@gmail.com/

In that thread, Brian makes a good point that you cannot "copy"
dirty working tree files from an existing worktree, and also that
you cannot have the same branch checked out in multiple worktrees at
the same time, to avoid making other worktrees out of sync when a
commit is made in one of the worktrees to advance the branch tip.

But these issues only mean that you cannot call it done by just
creating an identical CoW clone of the whole directory.  As long as
you are willing to accept that, instead of CoW-copying all existing
working tree files, you may have to give the new worktree its own
copy of the path by writing unique contents yourself, the above two
are surmountable.

However, when creating a new worktree, what happens is we check out
the working tree files for the new worktree from the index.  The
code paths doing the work to materialize these files on the
filesystem do not have any visibility into what _other_ worktrees,
including the original, have checked out in their working tree.

If anybody wants to work on this, first you'd need to stop thinking
about "there are many unchanged files already checked out in this
worktree so why not CoW copy them?"  Instead, you'd need to think at
the level of the checkout_entry() helper function and devise a way
to teach it not to do its thing, and instead do your CoW thing.

Roughly speaking, checkout_entry() takes an index entry that
records filetype (regular, executable, or symlink) and blob object
name, and the path to store the blob contents in.  It takes the
contents of the blob from the object database and writes them out
to the working tree.  Your enhancement to the system may go like
this:

 - First, iterate over the linked (non-bare) worktrees, examine the
   index of each of them, and make a mapping from each blob object
   to files in the working trees that have clean checkouts (there
   may be more than one such file that has a clean checkout of the
   same blob object).  Make sure you do not include any files with
   local modifications.

 - Hook into checkout_entry() to look at the mapping you created
   above.  When you notice that checkout_entry() is trying to check
   out a blob object known to your mapping, instead of letting it
   write the blob contents out by calling write_entry(), intercept
   the request and do your favorite CoW thing.  Make sure that you
   do not lose the race where somebody else may have updated the
   working tree file you CoW from since you made the above mapping
   while excluding locally modified files.

The TOCTOU issue may turn out to be nasty.  The cleanest way I can
think of to solve it is to hash the resulting file after making the
CoW copy to verify that what you CoW'ed was a good copy against your
index.  I personally am not interested in making such a change to
the system myself, mostly because of this.

If you hook into checkout_entry(), it will be used not only by
"git worktree add".  Anything that goes through checkout_entry(),
which is practically everything in Git that updates files in the
working tree with what is in the object database, will learn to
CoW-borrow from an existing checkout elsewhere in sibling worktrees.

HTH.

      parent reply	other threads:[~2026-08-14 16:29 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-14 10:40 [RFC] git worktree: use filesystem cloning where supported Peter Morris
2026-08-14 10:54 ` Kristoffer Haugsbakk
     [not found]   ` <CAOqWQbLEakpQEPsfw-GB70fdwbxW8EcdZ8EWzaN6ZAaHUU+jGQ@mail.gmail.com>
2026-08-14 11:34     ` Kristoffer Haugsbakk
     [not found]   ` <CAOqWQb+YzvVeqS85qYjQKK8jrUqDwV01eKqC8i1jgT886ixCwA@mail.gmail.com>
2026-08-14 13:29     ` Peter Morris
2026-08-14 16:29   ` Junio C Hamano [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqq4igwpswr.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=kristofferhaugsbakk@fastmail.com \
    --cc=mrpmorris@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).