3 test_description='test separate work tree'
6 test_expect_success 'setup' '
7 EMPTY_TREE=$(git write-tree) &&
8 EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&
9 CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&
10 EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") &&
11 CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") &&
13 mkdir -p work/sub/dir &&
18 test_expect_success 'setup: helper for testing rev-parse' '
20 echo $1 >expected.bare &&
21 echo $2 >expected.inside-git &&
22 echo $3 >expected.inside-worktree &&
25 echo $4 >expected.prefix
28 git rev-parse --is-bare-repository >actual.bare &&
29 git rev-parse --is-inside-git-dir >actual.inside-git &&
30 git rev-parse --is-inside-work-tree >actual.inside-worktree &&
33 git rev-parse --show-prefix >actual.prefix
36 test_cmp expected.bare actual.bare &&
37 test_cmp expected.inside-git actual.inside-git &&
38 test_cmp expected.inside-worktree actual.inside-worktree &&
41 # rev-parse --show-prefix should output
42 # a single newline when at the top of the work tree,
43 # but we test for that separately.
44 test -z "$4" && test_must_be_empty actual.prefix ||
45 test_cmp expected.prefix actual.prefix
50 test_expect_success 'setup: core.worktree = relative path' '
51 sane_unset GIT_WORK_TREE &&
53 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
54 export GIT_DIR GIT_CONFIG &&
55 git config core.worktree ../work
58 test_expect_success 'outside' '
59 test_rev_parse false false false
62 test_expect_success 'inside work tree' '
65 GIT_DIR=../repo.git &&
66 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
67 test_rev_parse false false true ""
71 test_expect_success 'empty prefix is actually written out' '
75 GIT_DIR=../repo.git &&
76 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
77 git rev-parse --show-prefix >../actual
79 test_cmp expected actual
82 test_expect_success 'subdir of work tree' '
85 GIT_DIR=../../../repo.git &&
86 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
87 test_rev_parse false false true sub/dir/
91 test_expect_success 'setup: core.worktree = absolute path' '
92 sane_unset GIT_WORK_TREE &&
93 GIT_DIR=$(pwd)/repo.git &&
94 GIT_CONFIG=$GIT_DIR/config &&
95 export GIT_DIR GIT_CONFIG &&
96 git config core.worktree "$(pwd)/work"
99 test_expect_success 'outside' '
100 test_rev_parse false false false &&
103 test_rev_parse false false false
107 test_expect_success 'inside work tree' '
110 test_rev_parse false false true ""
114 test_expect_success 'subdir of work tree' '
117 test_rev_parse false false true sub/dir/
121 test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' '
122 GIT_DIR=$(pwd)/repo.git &&
123 GIT_CONFIG=$GIT_DIR/config &&
124 git config core.worktree non-existent &&
125 GIT_WORK_TREE=work &&
126 export GIT_DIR GIT_CONFIG GIT_WORK_TREE
129 test_expect_success 'outside' '
130 test_rev_parse false false false &&
133 test_rev_parse false false false
137 test_expect_success 'inside work tree' '
141 test_rev_parse false false true ""
145 test_expect_success 'subdir of work tree' '
148 GIT_WORK_TREE=../.. &&
149 test_rev_parse false false true sub/dir/
153 test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' '
154 mv work repo.git/work &&
155 mv work2 repo.git/work2 &&
156 GIT_DIR=$(pwd)/repo.git &&
157 GIT_CONFIG=$GIT_DIR/config &&
158 GIT_WORK_TREE=$(pwd)/repo.git/work &&
159 export GIT_DIR GIT_CONFIG GIT_WORK_TREE
162 test_expect_success 'outside' '
164 test_rev_parse false false false
167 test_expect_success 'in repo.git' '
170 test_rev_parse false true false
173 cd repo.git/objects &&
174 test_rev_parse false true false
178 test_rev_parse false true false
182 test_expect_success 'inside work tree' '
185 test_rev_parse false true true ""
189 test_expect_success 'subdir of work tree' '
191 cd repo.git/work/sub/dir &&
192 test_rev_parse false true true sub/dir/
196 test_expect_success 'find work tree from repo' '
197 echo sub/dir/untracked >expected &&
198 cat <<-\EOF >repo.git/work/.gitignore &&
203 >repo.git/work/sub/dir/untracked &&
206 git ls-files --others --exclude-standard >../actual
208 test_cmp expected actual
211 test_expect_success 'find work tree from work tree' '
212 echo sub/dir/tracked >expected &&
213 >repo.git/work/sub/dir/tracked &&
215 cd repo.git/work/sub/dir &&
216 git --git-dir=../../.. add tracked
220 git ls-files >../actual
222 test_cmp expected actual
225 test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
227 cd repo.git/work/sub/dir &&
229 GIT_WORK_TREE=../.. &&
231 export GIT_DIR GIT_WORK_TREE GIT_PAGER &&
233 git diff --exit-code tracked &&
234 echo changed >tracked &&
235 test_must_fail git diff --exit-code tracked
239 test_expect_success 'diff-index respects work tree under .git dir' '
240 cat >diff-index-cached.expected <<-EOF &&
241 :000000 100644 $ZERO_OID $EMPTY_BLOB A sub/dir/tracked
243 cat >diff-index.expected <<-EOF &&
244 :000000 100644 $ZERO_OID $ZERO_OID A sub/dir/tracked
249 GIT_WORK_TREE=repo.git/work &&
250 export GIT_DIR GIT_WORK_TREE &&
251 git diff-index $EMPTY_TREE >diff-index.actual &&
252 git diff-index --cached $EMPTY_TREE >diff-index-cached.actual
254 test_cmp diff-index.expected diff-index.actual &&
255 test_cmp diff-index-cached.expected diff-index-cached.actual
258 test_expect_success 'diff-files respects work tree under .git dir' '
259 cat >diff-files.expected <<-EOF &&
260 :100644 100644 $EMPTY_BLOB $ZERO_OID M sub/dir/tracked
265 GIT_WORK_TREE=repo.git/work &&
266 export GIT_DIR GIT_WORK_TREE &&
267 git diff-files >diff-files.actual
269 test_cmp diff-files.expected diff-files.actual
272 test_expect_success 'git diff respects work tree under .git dir' '
273 cat >diff-TREE.expected <<-EOF &&
274 diff --git a/sub/dir/tracked b/sub/dir/tracked
276 index 0000000..$CHANGED_BLOB7
278 +++ b/sub/dir/tracked
282 cat >diff-TREE-cached.expected <<-EOF &&
283 diff --git a/sub/dir/tracked b/sub/dir/tracked
285 index 0000000..$EMPTY_BLOB7
287 cat >diff-FILES.expected <<-EOF &&
288 diff --git a/sub/dir/tracked b/sub/dir/tracked
289 index $EMPTY_BLOB7..$CHANGED_BLOB7 100644
290 --- a/sub/dir/tracked
291 +++ b/sub/dir/tracked
298 GIT_WORK_TREE=repo.git/work &&
299 export GIT_DIR GIT_WORK_TREE &&
300 git diff $EMPTY_TREE >diff-TREE.actual &&
301 git diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&
302 git diff >diff-FILES.actual
304 test_cmp diff-TREE.expected diff-TREE.actual &&
305 test_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&
306 test_cmp diff-FILES.expected diff-FILES.actual
309 test_expect_success 'git grep' '
310 echo dir/tracked >expected.grep &&
312 cd repo.git/work/sub &&
315 export GIT_DIR GIT_WORK_TREE &&
316 git grep -l changed >../../../actual.grep
318 test_cmp expected.grep actual.grep
321 test_expect_success 'git commit' '
324 GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done
328 test_expect_success 'absolute pathspec should fail gracefully' '
331 test_might_fail git config --unset core.worktree &&
332 test_must_fail git log HEAD -- /home
336 test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
338 echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
339 git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
342 test_expect_success 'relative $GIT_WORK_TREE and git subprocesses' '
343 GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \
344 test-tool subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
345 echo "$(pwd)/repo.git/work" >expected &&
346 test_cmp expected actual
349 test_expect_success 'Multi-worktree setup' '
351 mkdir -p repo.git/repos/foo &&
352 cp repo.git/HEAD repo.git/index repo.git/repos/foo &&
353 test_might_fail cp repo.git/sharedindex.* repo.git/repos/foo &&
354 sane_unset GIT_DIR GIT_CONFIG GIT_WORK_TREE
357 test_expect_success 'GIT_DIR set (1)' '
358 echo "gitdir: repo.git/repos/foo" >gitfile &&
359 echo ../.. >repo.git/repos/foo/commondir &&
362 GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
363 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
364 test_cmp expect actual
368 test_expect_success 'GIT_DIR set (2)' '
369 echo "gitdir: repo.git/repos/foo" >gitfile &&
370 echo "$(pwd)/repo.git" >repo.git/repos/foo/commondir &&
373 GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
374 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
375 test_cmp expect actual
379 test_expect_success 'Auto discovery' '
380 echo "gitdir: repo.git/repos/foo" >.git &&
381 echo ../.. >repo.git/repos/foo/commondir &&
384 git rev-parse --git-common-dir >actual &&
385 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
386 test_cmp expect actual &&
389 git ls-files --full-name :/ | grep data1 >actual &&
390 echo work/data1 >expect &&
391 test_cmp expect actual
395 test_expect_success '$GIT_DIR/common overrides core.worktree' '
397 git --git-dir=repo.git config core.worktree "$TRASH_DIRECTORY/elsewhere" &&
398 echo "gitdir: repo.git/repos/foo" >.git &&
399 echo ../.. >repo.git/repos/foo/commondir &&
402 git rev-parse --git-common-dir >actual &&
403 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
404 test_cmp expect actual &&
407 git ls-files --full-name :/ | grep data2 >actual &&
408 echo work/data2 >expect &&
409 test_cmp expect actual
413 test_expect_success '$GIT_WORK_TREE overrides $GIT_DIR/common' '
414 echo "gitdir: repo.git/repos/foo" >.git &&
415 echo ../.. >repo.git/repos/foo/commondir &&
419 git --git-dir=../.git --work-tree=. add data3 &&
420 git ls-files --full-name -- :/ | grep data3 >actual &&
421 echo data3 >expect &&
422 test_cmp expect actual
426 test_expect_success 'error out gracefully on invalid $GIT_WORK_TREE' '
428 GIT_WORK_TREE=/.invalid/work/tree &&
429 export GIT_WORK_TREE &&
430 test_expect_code 128 git rev-parse
434 test_expect_success 'refs work with relative gitdir and work tree' '
436 git -C relative commit --allow-empty -m one &&
437 git -C relative commit --allow-empty -m two &&
439 GIT_DIR=relative/.git GIT_WORK_TREE=relative git reset HEAD^ &&
441 git -C relative log -1 --format=%s >actual &&
443 test_cmp expect actual