Skip to content

Commit ff5b791

Browse files
newrengitster
authored andcommitted
sequencer, stash: fix running from worktree subdir
In commits bc3ae46 ("rebase: do not attempt to remove startup_info->original_cwd", 2021-12-09) and 0fce211 ("stash: do not attempt to remove startup_info->original_cwd", 2021-12-09), we wanted to allow the subprocess to know which directory the parent process was running from, so that the subprocess could protect it. However... When run from a non-main worktree, setup_git_directory() will note that the discovered git directory (/PATH/TO/.git/worktree/non-main-worktree) does not match DEFAULT_GIT_DIR_ENVIRONMENT (see setup_discovered_git_dir()), and decide to set GIT_DIR in the environment. This matters because... Whenever git is run with the GIT_DIR environment variable set, and GIT_WORK_TREE not set, it presumes that '.' is the working tree. So... This combination results in the subcommand being very confused about the working tree. Fix it by also setting the GIT_WORK_TREE environment variable along with setting cmd.dir. A possibly more involved fix we could consider for later would be to make setup.c set GIT_WORK_TREE whenever (a) it discovers both the git directory and the working tree and (b) it decides to set GIT_DIR in the environment. I did not attempt that here as such would be too big of a change for a 2.35.1 release. Test-case-by: Glen Choo <[email protected]> Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 324b170 commit ff5b791

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

builtin/stash.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1485,8 +1485,12 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
14851485
struct child_process cp = CHILD_PROCESS_INIT;
14861486

14871487
cp.git_cmd = 1;
1488-
if (startup_info->original_cwd)
1488+
if (startup_info->original_cwd) {
14891489
cp.dir = startup_info->original_cwd;
1490+
strvec_pushf(&cp.env_array, "%s=%s",
1491+
GIT_WORK_TREE_ENVIRONMENT,
1492+
the_repository->worktree);
1493+
}
14901494
strvec_pushl(&cp.args, "clean", "--force",
14911495
"--quiet", "-d", ":/", NULL);
14921496
if (include_untracked == INCLUDE_ALL_FILES)

sequencer.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4228,8 +4228,11 @@ static int run_git_checkout(struct repository *r, struct replay_opts *opts,
42284228

42294229
cmd.git_cmd = 1;
42304230

4231-
if (startup_info->original_cwd)
4231+
if (startup_info->original_cwd) {
42324232
cmd.dir = startup_info->original_cwd;
4233+
strvec_pushf(&cmd.env_array, "%s=%s",
4234+
GIT_WORK_TREE_ENVIRONMENT, r->worktree);
4235+
}
42334236
strvec_push(&cmd.args, "checkout");
42344237
strvec_push(&cmd.args, commit);
42354238
strvec_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);

t/t3400-rebase.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,4 +416,25 @@ test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink'
416416
mv actual_logs .git/logs
417417
'
418418

419+
test_expect_success 'rebase when inside worktree subdirectory' '
420+
git init main-wt &&
421+
(
422+
cd main-wt &&
423+
git commit --allow-empty -m "initial" &&
424+
mkdir -p foo/bar &&
425+
test_commit foo/bar/baz &&
426+
mkdir -p a/b &&
427+
test_commit a/b/c &&
428+
# create another branch for our other worktree
429+
git branch other &&
430+
git worktree add ../other-wt other &&
431+
cd ../other-wt &&
432+
# create and cd into a subdirectory
433+
mkdir -p random/dir &&
434+
cd random/dir &&
435+
# now do the rebase
436+
git rebase --onto HEAD^^ HEAD^ # drops the HEAD^ commit
437+
)
438+
'
439+
419440
test_done

0 commit comments

Comments
 (0)