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

[PATCH] sequencer.c: set GIT_WORK_TREE in run_git_checkout

From
Glen Choo <chooglen@google.com>
Date
Jan 25, 2022, 23:36 UTC
Message-ID
<20220125233612.46831-1-chooglen@google.com>

When rebasing in a subdirectory of a worktree, Git fails due to a dirty worktree:

  error: The following untracked working tree files would be overwritten
by merge:
          a/b/c
  Please move or remove them before you merge.

This occurs because "git rebase" invokes a "git checkout" without propagating the GIT_WORK_TREE environment variable, causing the worktree to be assumed to be ".". This was not an issue until bc3ae46b42 (rebase: do not attempt to remove startup_info->original_cwd, 2021-12-09), when the .dir of the "git checkout" child process was changed such that it no longer runs at the root of the worktree.

Propagate GIT_WORK_TREE to the "git checkout" child process and test that rebase in a subdirectory of a worktree succeeds.

Signed-off-by: Glen Choo <chooglen@google.com>
---
Here is a fix for the bug I found in [1]. I didn't look through the rest
of the "preserve cwd" thread for other possible bugs pertaining to
worktrees, but I didn't find any during a cursory glance at sequencer.c.

I'm also not sure if this is the idiomatic way to do it since, I assume, we'd always want to propagate GIT_WORK_TREE, but this is identical to how do_exec() sets GIT_WORK_TREE in the same file (perhaps this is something that should be refactored).

[1] https://lore.kernel.org/git/kl6lilu71rzl.fsf@chooglen-macbookpro.roam.corp.google.com
 sequencer.c       |  2 ++
 t/t3400-rebase.sh | 29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)
diff --git a/sequencer.c b/sequencer.c
index 83f257e7fa..e193dcf846 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -4233,6 +4233,8 @@ static int run_git_checkout(struct repository *r, struct replay_opts *opts,
 	strvec_push(&cmd.args, "checkout");
 	strvec_push(&cmd.args, commit);
 	strvec_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);
+	strvec_pushf(&cmd.env_array, "GIT_WORK_TREE=%s",
+		     absolute_path(get_git_work_tree()));
 
 	if (opts->verbose)
 		ret = run_command(&cmd);
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 23dbd3c82e..8b8b66538b 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -416,4 +416,33 @@ test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink'
 	mv actual_logs .git/logs
 '
 
+test_expect_success 'rebase when inside worktree subdirectory' '
+	git init main-wt &&
+	(
+		cd main-wt &&
+		git commit --allow-empty -m "initial" &&
+		# create commit with foo/bar/baz
+		mkdir -p foo/bar &&
+		touch foo/bar/baz &&
+		git add foo/bar/baz &&
+		git commit -m "add foo/bar/baz" &&
+		# create commit with a/b/c
+		mkdir -p a/b &&
+		touch a/b/c &&
+		git add a/b/c &&
+		git commit -m "add a/b/c" &&
+		# create another branch for our other worktree
+		git branch other &&
+		git worktree add ../other-wt other &&
+		(
+			cd ../other-wt &&
+			mkdir -p random/dir &&
+			(
+				cd random/dir &&
+				git rebase --onto HEAD^^ HEAD^  # drops the HEAD^ commit
+			)
+		)
+	)
+'
+
 test_done

base-commit: bc3ae46b420f58dfe2bfd87714dca096a043d554
-- 
2.33.GIT
Next: Glen Choo
Message 1 of 5 in “sequencer.c: set GIT_WORK_TREE in run_git_checkout”
  1. sequencer.c: set GIT_WORK_TREE in run_git_checkoutGlen Choo, Jan 25, 2022
  2. Glen ChooJan 25, 2022
  3. Elijah NewrenJan 26, 2022
  4. Elijah NewrenJan 26, 2022
  5. Glen ChooJan 26, 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.