summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Elijah Newren <newren@gmail.com>2022-01-26 01:43:45 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2022-01-26 12:01:54 -0800
commitff5b7913f0af62c26682b0376d0aa2d7f5d74b2e (patch)
treeaad74a2cbc13e6a73598b131a115977a56b08689
parentt2501: simplify the tests since we can now assume desired behavior (diff)
downloadtgif-ff5b7913f0af62c26682b0376d0aa2d7f5d74b2e.tar.xz
sequencer, stash: fix running from worktree subdir
In commits bc3ae46b42 ("rebase: do not attempt to remove startup_info->original_cwd", 2021-12-09) and 0fce211ccc ("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 <chooglen@google.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/stash.c6
-rw-r--r--sequencer.c5
-rwxr-xr-xt/t3400-rebase.sh21
3 files changed, 30 insertions, 2 deletions
diff --git a/builtin/stash.c b/builtin/stash.c
index de0e432a4f..a8a543855e 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1485,8 +1485,12 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
- if (startup_info->original_cwd)
+ if (startup_info->original_cwd) {
cp.dir = startup_info->original_cwd;
+ strvec_pushf(&cp.env_array, "%s=%s",
+ GIT_WORK_TREE_ENVIRONMENT,
+ the_repository->worktree);
+ }
strvec_pushl(&cp.args, "clean", "--force",
"--quiet", "-d", ":/", NULL);
if (include_untracked == INCLUDE_ALL_FILES)
diff --git a/sequencer.c b/sequencer.c
index 83f257e7fa..3fa17c98b7 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -4228,8 +4228,11 @@ static int run_git_checkout(struct repository *r, struct replay_opts *opts,
cmd.git_cmd = 1;
- if (startup_info->original_cwd)
+ if (startup_info->original_cwd) {
cmd.dir = startup_info->original_cwd;
+ strvec_pushf(&cmd.env_array, "%s=%s",
+ GIT_WORK_TREE_ENVIRONMENT, r->worktree);
+ }
strvec_push(&cmd.args, "checkout");
strvec_push(&cmd.args, commit);
strvec_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 23dbd3c82e..71b1735e1d 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -416,4 +416,25 @@ 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" &&
+ mkdir -p foo/bar &&
+ test_commit foo/bar/baz &&
+ mkdir -p a/b &&
+ test_commit a/b/c &&
+ # create another branch for our other worktree
+ git branch other &&
+ git worktree add ../other-wt other &&
+ cd ../other-wt &&
+ # create and cd into a subdirectory
+ mkdir -p random/dir &&
+ cd random/dir &&
+ # now do the rebase
+ git rebase --onto HEAD^^ HEAD^ # drops the HEAD^ commit
+ )
+'
+
test_done