]> git.ipfire.org Git - thirdparty/git.git/commitdiff
sequencer, stash: fix running from worktree subdir
authorElijah Newren <newren@gmail.com>
Wed, 26 Jan 2022 01:43:45 +0000 (01:43 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 26 Jan 2022 20:01:54 +0000 (12:01 -0800)
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>
builtin/stash.c
sequencer.c
t/t3400-rebase.sh

index de0e432a4ff901ce48508d879d35dc9d4238b457..a8a543855e8d7afa6c58d1d7742d33101d37f061 100644 (file)
@@ -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)
index 83f257e7fa4187cabf86bb4c3304f952b16e0c61..3fa17c98b71b26201ac0325d82a73aa632bd7e77 100644 (file)
@@ -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);
index 23dbd3c82ed6a21ff7bd883c20a7c45822421250..71b1735e1dd180bb16a72df76b1b49f49a59072d 100755 (executable)
@@ -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