git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Strange checkout with GIT_WORK_TREE

From
brian m. carlson <sandals@crustytoothpaste.net>
Date
Jan 21, 2022, 22:09 UTC
Message-ID
<YesvAkBnxq3xrHTV@camp.crustytoothpaste.net>
In-Reply-To
<CAHqym3xs_M7BvvFDq2pHM-+DgK_nJcBakVEBL-GiNwnCRzMwWA@mail.gmail.com>
On 2022-01-21 at 16:37:58, Lauri Rooden wrote:
Show 38 quoted lines
> Does the GIT_WORK_TREE get lost on the middle of process
> or I am misunderstand the git checkout?
> 
> What did you do before the bug happened? (Steps to reproduce your issue)
> - I wrote a shell script to reproduce
> 
> ```git-test.sh
> GIT_ROOT=$(mktemp -d)
> GIT_COPY=$(mktemp -d)
> 
> echo "Create git repo with two commits: $GIT_ROOT"
> cd $GIT_ROOT
> git init
> echo 1 > a.txt
> echo 1 > b.txt
> git add *.txt
> git commit -m "Initial commit"
> echo 2 > b.txt
> git add b.txt
> git commit -m "Second commit"
> 
> echo "Checkout to other work-tree: $GIT_COPY"
> GIT_WORK_TREE=$GIT_COPY git checkout HEAD~1
> git status
> 
> echo "ORIGIN $GIT_ROOT"
> ls -la $GIT_ROOT
> echo "COPY $GIT_COPY"
> ls -la $GIT_COPY
> ```
> 
> What did you expect to happen? (Expected behavior)
> - a.txt and b.txt checkouted to $GIT_COPY both with content `1`
> - current folder unchanged
> 
> What happened instead? (Actual behavior)
> - only b.txt checkouted to $GIT_COPY
> - HEAD~1 checkouted in current folder but folder content remains HEAD

Here's what I believe is happening here. When you run "git checkout HEAD~1", Git notices that the only file that's stale in the index compared to what's already present is b.txt; a.txt is up to date. As such, it only writes one file into the working tree, since only one file needs to be updated. This is an optimization, since for large working trees, writing out every file every time would be extremely expensive.

I don't know what our official position is on switching working trees like this. I would generally recommend you pick one and stick to it, but if you want to do this, you'll need to update the index for the working tree first. You can do that by something like this in place of your checkout:

  GIT_WORK_TREE=$GIT_COPY git update-index --refresh
  GIT_WORK_TREE=$GIT_COPY git checkout -f HEAD~1

That will inform Git that your working copy is stale and then the -f flag to checkout will force Git to overwrite the missing files.

If your goal is to have multiple worktrees for one repository, you can do that with "git worktree", which will keep separate indices for your separate directories, provided they're on separate branches. If you just want to create a detached copy of the files for a repository from a commit, you can do this:

  git archive HEAD~1 | tar -C "$GIT_COPY" -xf -

Hopefully that explains what's going on. If you tell us a little bit more about what you wanted to accomplish, we may be able to help you find a way to do it that provides results that are at least less surprising and more predictable.

-- 
brian m. carlson (he/him or they/them)
Toronto, Ontario, CA
Previous: Lauri RoodenNext: Junio C Hamano
Message 2 of 4 in “Strange checkout with GIT_WORK_TREE”
  1. Lauri RoodenJan 21, 2022
  2. brian m. carlsonJan 21, 2022
  3. Junio C HamanoJan 21, 2022
  4. Lauri RoodenJan 22, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.