зеркало из https://github.com/microsoft/git.git
init: make --separate-git-dir work from within linked worktree
The intention of `git init --separate-work-dir=<path>` is to move the
.git/ directory to a location outside of the main worktree. When used
within a linked worktree, however, rather than moving the .git/
directory as intended, it instead incorrectly moves the worktree's
.git/worktrees/<id> directory to <path>, thus disconnecting the linked
worktree from its parent repository and breaking the worktree in the
process since its local .git file no longer points at a location at
which it can find the object database. Fix this broken behavior.
An intentional side-effect of this change is that it also closes a
loophole not caught by ccf236a23a
(init: disallow --separate-git-dir
with bare repository, 2020-08-09) in which the check to prevent
--separate-git-dir being used in conjunction with a bare repository was
unable to detect the invalid combination when invoked from within a
linked worktree. Therefore, add a test to verify that this loophole is
closed, as well.
Reported-by: Henré Botha <henrebotha@gmail.com>
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
42264bc841
Коммит
59d876ccd6
|
@ -642,6 +642,30 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
|
||||||
if (!git_dir)
|
if (!git_dir)
|
||||||
git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
|
git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When --separate-git-dir is used inside a linked worktree, take
|
||||||
|
* care to ensure that the common .git/ directory is relocated, not
|
||||||
|
* the worktree-specific .git/worktrees/<id>/ directory.
|
||||||
|
*/
|
||||||
|
if (real_git_dir) {
|
||||||
|
int err;
|
||||||
|
const char *p;
|
||||||
|
struct strbuf sb = STRBUF_INIT;
|
||||||
|
|
||||||
|
p = read_gitfile_gently(git_dir, &err);
|
||||||
|
if (p && get_common_dir(&sb, p)) {
|
||||||
|
struct strbuf mainwt = STRBUF_INIT;
|
||||||
|
|
||||||
|
strbuf_addbuf(&mainwt, &sb);
|
||||||
|
strbuf_strip_suffix(&mainwt, "/.git");
|
||||||
|
if (chdir(mainwt.buf) < 0)
|
||||||
|
die_errno(_("cannot chdir to %s"), mainwt.buf);
|
||||||
|
strbuf_release(&mainwt);
|
||||||
|
git_dir = strbuf_detach(&sb, NULL);
|
||||||
|
}
|
||||||
|
strbuf_release(&sb);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_bare_repository_cfg < 0)
|
if (is_bare_repository_cfg < 0)
|
||||||
is_bare_repository_cfg = guess_repository_type(git_dir);
|
is_bare_repository_cfg = guess_repository_type(git_dir);
|
||||||
|
|
||||||
|
|
|
@ -329,6 +329,15 @@ test_expect_success 'implicit bare & --separate-git-dir incompatible' '
|
||||||
test_i18ngrep "incompatible" err
|
test_i18ngrep "incompatible" err
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bare & --separate-git-dir incompatible within worktree' '
|
||||||
|
test_when_finished "rm -rf bare.git linkwt seprepo" &&
|
||||||
|
test_commit gumby &&
|
||||||
|
git clone --bare . bare.git &&
|
||||||
|
git -C bare.git worktree add --detach ../linkwt &&
|
||||||
|
test_must_fail git -C linkwt init --separate-git-dir seprepo 2>err &&
|
||||||
|
test_i18ngrep "incompatible" err
|
||||||
|
'
|
||||||
|
|
||||||
test_lazy_prereq GETCWD_IGNORES_PERMS '
|
test_lazy_prereq GETCWD_IGNORES_PERMS '
|
||||||
base=GETCWD_TEST_BASE_DIR &&
|
base=GETCWD_TEST_BASE_DIR &&
|
||||||
mkdir -p $base/dir &&
|
mkdir -p $base/dir &&
|
||||||
|
@ -405,15 +414,23 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' '
|
||||||
test_path_is_dir realgitdir/refs
|
test_path_is_dir realgitdir/refs
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 're-init to move gitdir with linked worktrees' '
|
sep_git_dir_worktree () {
|
||||||
test_when_finished "rm -rf mainwt linkwt seprepo" &&
|
test_when_finished "rm -rf mainwt linkwt seprepo" &&
|
||||||
git init mainwt &&
|
git init mainwt &&
|
||||||
test_commit -C mainwt gumby &&
|
test_commit -C mainwt gumby &&
|
||||||
git -C mainwt worktree add --detach ../linkwt &&
|
git -C mainwt worktree add --detach ../linkwt &&
|
||||||
git -C mainwt init --separate-git-dir ../seprepo &&
|
git -C "$1" init --separate-git-dir ../seprepo &&
|
||||||
git -C mainwt rev-parse --git-common-dir >expect &&
|
git -C mainwt rev-parse --git-common-dir >expect &&
|
||||||
git -C linkwt rev-parse --git-common-dir >actual &&
|
git -C linkwt rev-parse --git-common-dir >actual &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 're-init to move gitdir with linked worktrees' '
|
||||||
|
sep_git_dir_worktree mainwt
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 're-init to move gitdir within linked worktree' '
|
||||||
|
sep_git_dir_worktree linkwt
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success MINGW '.git hidden' '
|
test_expect_success MINGW '.git hidden' '
|
||||||
|
|
Загрузка…
Ссылка в новой задаче