git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/6] t2500: add various tests for nuking untracked files

From
Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>
Date
Sep 18, 2021, 23:15 UTC
Message-ID
<b634136a74b37a6f73bc3038f79031e040423883.1632006923.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1036.git.1632006923.gitgitgadget@gmail.com>
From: Elijah Newren <newren@gmail.com>

Noting that unpack_trees treats reset=1 & update=1 as license to nuke untracked files, I looked for code paths that use this combination and tried to generate testcases which demonstrated unintentional loss of untracked files and directories. I found several.

I also include testcases for `git reset --{hard,merge,keep}`. A hard reset is perhaps the most direct test of unpack_tree's reset=1 behavior, but we cannot make `git reset --hard` preserve untracked files without some migration work.

Also, the two commands `checkout --force` (because of the --force) and `read-tree --reset` (because it's plumbing and we need to keep it backward compatible) were left out as we expect those to continue removing untracked files and directories.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 t/t2500-untracked-overwriting.sh | 244 +++++++++++++++++++++++++++++++
 1 file changed, 244 insertions(+)
 create mode 100755 t/t2500-untracked-overwriting.sh
diff --git a/t/t2500-untracked-overwriting.sh b/t/t2500-untracked-overwriting.sh
new file mode 100755
index 00000000000..a1a6dfa671e
--- /dev/null
+++ b/t/t2500-untracked-overwriting.sh
@@ -0,0 +1,244 @@
+#!/bin/sh
+
+test_description='Test handling of overwriting untracked files'
+
+. ./test-lib.sh
+
+test_setup_reset () {
+	test_create_repo reset_$1 &&
+	(
+		cd reset_$1 &&
+		test_commit init &&
+
+		git branch stable &&
+		git branch work &&
+
+		git checkout work &&
+		test_commit foo &&
+
+		git checkout stable
+	)
+}
+
+test_expect_success 'reset --hard will nuke untracked files/dirs' '
+	test_setup_reset hard &&
+	(
+		cd reset_hard &&
+		git ls-tree -r stable &&
+		git log --all --name-status --oneline &&
+		git ls-tree -r work &&
+
+		mkdir foo.t &&
+		echo precious >foo.t/file &&
+		echo foo >expect &&
+
+		git reset --hard work &&
+
+		# check that untracked directory foo.t/ was nuked
+		test_path_is_file foo.t &&
+		test_cmp expect foo.t
+	)
+'
+
+test_expect_success 'reset --merge will preserve untracked files/dirs' '
+	test_setup_reset merge &&
+	(
+		cd reset_merge &&
+
+		mkdir foo.t &&
+		echo precious >foo.t/file &&
+		cp foo.t/file expect &&
+
+		test_must_fail git reset --merge work 2>error &&
+		test_cmp expect foo.t/file &&
+		grep "Updating.*foo.t.*would lose untracked files" error
+	)
+'
+
+test_expect_success 'reset --keep will preserve untracked files/dirs' '
+	test_setup_reset keep &&
+	(
+		cd reset_keep &&
+
+		mkdir foo.t &&
+		echo precious >foo.t/file &&
+		cp foo.t/file expect &&
+
+		test_must_fail git reset --merge work 2>error &&
+		test_cmp expect foo.t/file &&
+		grep "Updating.*foo.t.*would lose untracked files" error
+	)
+'
+
+test_setup_checkout_m () {
+	test_create_repo checkout &&
+	(
+		cd checkout &&
+		test_commit init &&
+
+		test_write_lines file has some >filler &&
+		git add filler &&
+		git commit -m filler &&
+
+		git branch stable &&
+
+		git switch -c work &&
+		echo stuff >notes.txt &&
+		test_write_lines file has some words >filler &&
+		git add notes.txt filler &&
+		git commit -m filler &&
+
+		git checkout stable
+	)
+}
+
+test_expect_failure 'checkout -m does not nuke untracked file' '
+	test_setup_checkout_m &&
+	(
+		cd checkout &&
+
+		# Tweak filler
+		test_write_lines this file has some >filler &&
+		# Make an untracked file, save its contents in "expect"
+		echo precious >notes.txt &&
+		cp notes.txt expect &&
+
+		test_must_fail git checkout -m work &&
+		test_cmp expect notes.txt
+	)
+'
+
+test_setup_sequencing () {
+	test_create_repo sequencing_$1 &&
+	(
+		cd sequencing_$1 &&
+		test_commit init &&
+
+		test_write_lines this file has some words >filler &&
+		git add filler &&
+		git commit -m filler &&
+
+		mkdir -p foo/bar &&
+		test_commit foo/bar/baz &&
+
+		git branch simple &&
+		git branch fooey &&
+
+		git checkout fooey &&
+		git rm foo/bar/baz.t &&
+		echo stuff >>filler &&
+		git add -u &&
+		git commit -m "changes" &&
+
+		git checkout simple &&
+		echo items >>filler &&
+		echo newstuff >>newfile &&
+		git add filler newfile &&
+		git commit -m another
+	)
+}
+
+test_expect_failure 'git rebase --abort and untracked files' '
+	test_setup_sequencing rebase_abort_and_untracked &&
+	(
+		cd sequencing_rebase_abort_and_untracked &&
+		git checkout fooey &&
+		test_must_fail git rebase simple &&
+
+		cat init.t &&
+		git rm init.t &&
+		echo precious >init.t &&
+		cp init.t expect &&
+		git status --porcelain &&
+		test_must_fail git rebase --abort &&
+		test_cmp expect init.t
+	)
+'
+
+test_expect_failure 'git rebase fast forwarding and untracked files' '
+	test_setup_sequencing rebase_fast_forward_and_untracked &&
+	(
+		cd sequencing_rebase_fast_forward_and_untracked &&
+		git checkout init &&
+		echo precious >filler &&
+		cp filler expect &&
+		test_must_fail git rebase init simple &&
+		test_cmp expect filler
+	)
+'
+
+test_expect_failure 'git rebase --autostash and untracked files' '
+	test_setup_sequencing rebase_autostash_and_untracked &&
+	(
+		cd sequencing_rebase_autostash_and_untracked &&
+		git checkout simple &&
+		git rm filler &&
+		mkdir filler &&
+		echo precious >filler/file &&
+		cp filler/file expect &&
+		git rebase --autostash init &&
+		test_path_is_file filler/file
+	)
+'
+
+test_expect_failure 'git stash and untracked files' '
+	test_setup_sequencing stash_and_untracked_files &&
+	(
+		cd sequencing_stash_and_untracked_files &&
+		git checkout simple &&
+		git rm filler &&
+		mkdir filler &&
+		echo precious >filler/file &&
+		cp filler/file expect &&
+		git status --porcelain &&
+		git stash push &&
+		git status --porcelain &&
+		test_path_is_file filler/file
+	)
+'
+
+test_expect_failure 'git am --abort and untracked dir vs. unmerged file' '
+	test_setup_sequencing am_abort_and_untracked &&
+	(
+		cd sequencing_am_abort_and_untracked &&
+		git format-patch -1 --stdout fooey >changes.mbox &&
+		test_must_fail git am --3way changes.mbox &&
+
+		# Delete the conflicted file; we will stage and commit it later
+		rm filler &&
+
+		# Put an unrelated untracked directory there
+		mkdir filler &&
+		echo foo >filler/file1 &&
+		echo bar >filler/file2 &&
+
+		test_must_fail git am --abort 2>errors &&
+		test_path_is_dir filler &&
+		grep "Updating .filler. would lose untracked files in it" errors
+	)
+'
+
+test_expect_failure 'git am --skip and untracked dir vs deleted file' '
+	test_setup_sequencing am_skip_and_untracked &&
+	(
+		cd sequencing_am_skip_and_untracked &&
+		git checkout fooey &&
+		git format-patch -1 --stdout simple >changes.mbox &&
+		test_must_fail git am --3way changes.mbox &&
+
+		# Delete newfile
+		rm newfile &&
+
+		# Put an unrelated untracked directory there
+		mkdir newfile &&
+		echo foo >newfile/file1 &&
+		echo bar >newfile/file2 &&
+
+		# Change our mind about resolutions, just skip this patch
+		test_must_fail git am --skip 2>errors &&
+		test_path_is_dir newfile &&
+		grep "Updating .newfile. would lose untracked files in it" errors
+	)
+'
+
+test_done
-- 
gitgitgadget
Previous: Elijah Newren via GitGitGadgetNext: Ævar Arnfjörð Bjarmason
Message 2 of 82 in “Fix various issues around removal of untracked files/directories”
  1. 0/6 Fix various issues around removal of untracked files/directoriesElijah Newren via GitGitGadget, Sep 18, 2021
  2. 1/6 t2500: add various tests for nuking untracked filesElijah Newren via GitGitGadget, Sep 18, 2021
  3. Ævar Arnfjörð BjarmasonSep 19, 2021
  4. Elijah NewrenSep 20, 2021
  5. 4/6 unpack-trees: avoid nuking untracked dir in way of locally deleted fileElijah Newren via GitGitGadget, Sep 18, 2021
  6. Ævar Arnfjörð BjarmasonSep 19, 2021
  7. Elijah NewrenSep 20, 2021
  8. 3/6 unpack-trees: avoid nuking untracked dir in way of unmerged fileElijah Newren via GitGitGadget, Sep 18, 2021
  9. 2/6 Split unpack_trees 'reset' flag into two for untracked handlingElijah Newren via GitGitGadget, Sep 18, 2021
  10. Ævar Arnfjörð BjarmasonSep 19, 2021
  11. Elijah NewrenSep 20, 2021
  12. Phillip WoodSep 20, 2021
  13. Elijah NewrenSep 20, 2021
  14. Phillip WoodSep 20, 2021
  15. Elijah NewrenSep 24, 2021
  16. 6/6 Documentation: call out commands that nuke untracked files/directoriesElijah Newren via GitGitGadget, Sep 18, 2021
  17. Philip OakleySep 19, 2021
  18. Philip OakleySep 19, 2021
  19. Elijah NewrenSep 20, 2021
  20. 5/6 Comment important codepaths regarding nuking untracked files/dirsElijah Newren via GitGitGadget, Sep 18, 2021
  21. Luke DiamandSep 24, 2021
  22. Elijah NewrenSep 24, 2021
  23. 0/6 Fix various issues around removal of untracked files/directoriesElijah Newren via GitGitGadget, Sep 24, 2021
  24. 2/6 Change unpack_trees' 'reset' flag into an enumElijah Newren via GitGitGadget, Sep 24, 2021
  25. Junio C HamanoSep 24, 2021
  26. Elijah NewrenSep 26, 2021
  27. 1/6 t2500: add various tests for nuking untracked filesElijah Newren via GitGitGadget, Sep 24, 2021
  28. 3/6 unpack-trees: avoid nuking untracked dir in way of unmerged fileElijah Newren via GitGitGadget, Sep 24, 2021
  29. 4/6 unpack-trees: avoid nuking untracked dir in way of locally deleted fileElijah Newren via GitGitGadget, Sep 24, 2021
  30. 5/6 Comment important codepaths regarding nuking untracked files/dirsElijah Newren via GitGitGadget, Sep 24, 2021
  31. Eric SunshineSep 24, 2021
  32. Elijah NewrenSep 26, 2021
  33. 6/6 Documentation: call out commands that nuke untracked files/directoriesElijah Newren via GitGitGadget, Sep 24, 2021
  34. 00/11 Fix various issues around removal of untracked files/directoriesElijah Newren via GitGitGadget, Sep 27, 2021
  35. 02/11 checkout, read-tree: fix leak of unpack_trees_options.dirElijah Newren via GitGitGadget, Sep 27, 2021
  36. 03/11 read-tree, merge-recursive: overwrite ignored files by defaultElijah Newren via GitGitGadget, Sep 27, 2021
  37. Jack O'ConnorDec 13, 2021
  38. Elijah NewrenDec 13, 2021
  39. 01/11 t2500: add various tests for nuking untracked filesElijah Newren via GitGitGadget, Sep 27, 2021
  40. 06/11 Remove ignored files by default when they are in the wayElijah Newren via GitGitGadget, Sep 27, 2021
  41. 05/11 unpack-trees: make dir an internal-only structElijah Newren via GitGitGadget, Sep 27, 2021
  42. 04/11 unpack-trees: introduce preserve_ignored to unpack_trees_optionsElijah Newren via GitGitGadget, Sep 27, 2021
  43. Ævar Arnfjörð BjarmasonSep 29, 2021
  44. Elijah NewrenSep 29, 2021
  45. Ævar Arnfjörð BjarmasonSep 29, 2021
  46. Elijah NewrenSep 30, 2021
  47. Ævar Arnfjörð BjarmasonSep 30, 2021
  48. Elijah NewrenOct 1, 2021
  49. Ævar Arnfjörð BjarmasonOct 1, 2021
  50. Ævar Arnfjörð BjarmasonOct 1, 2021
  51. Elijah NewrenOct 1, 2021
  52. Ævar Arnfjörð BjarmasonOct 2, 2021
  53. Ævar Arnfjörð BjarmasonOct 3, 2021
  54. Elijah NewrenOct 4, 2021
  55. Elijah NewrenOct 4, 2021
  56. Ævar Arnfjörð BjarmasonOct 4, 2021
  57. Elijah NewrenOct 4, 2021
  58. 07/11 Change unpack_trees' 'reset' flag into an enumElijah Newren via GitGitGadget, Sep 27, 2021
  59. 08/11 unpack-trees: avoid nuking untracked dir in way of unmerged fileElijah Newren via GitGitGadget, Sep 27, 2021
  60. 09/11 unpack-trees: avoid nuking untracked dir in way of locally deleted fileElijah Newren via GitGitGadget, Sep 27, 2021
  61. 10/11 Comment important codepaths regarding nuking untracked files/dirsElijah Newren via GitGitGadget, Sep 27, 2021
  62. 11/11 Documentation: call out commands that nuke untracked files/directoriesElijah Newren via GitGitGadget, Sep 27, 2021
  63. Junio C HamanoSep 27, 2021
  64. Elijah NewrenSep 27, 2021
  65. Elijah NewrenSep 27, 2021
  66. Phillip WoodSep 30, 2021
  67. 00/10 Fix various issues around removal of untracked files/directoriesÆvar Arnfjörð Bjarmason, Oct 4, 2021
  68. 01/10 t2500: add various tests for nuking untracked filesÆvar Arnfjörð Bjarmason, Oct 4, 2021
  69. 02/10 read-tree, merge-recursive: overwrite ignored files by defaultÆvar Arnfjörð Bjarmason, Oct 4, 2021
  70. 03/10 unpack-trees: introduce preserve_ignored to unpack_trees_optionsÆvar Arnfjörð Bjarmason, Oct 4, 2021
  71. 04/10 unpack-trees: rename "dir" to "private_dir"Ævar Arnfjörð Bjarmason, Oct 4, 2021
  72. 05/10 Remove ignored files by default when they are in the wayÆvar Arnfjörð Bjarmason, Oct 4, 2021
  73. 06/10 Change unpack_trees' 'reset' flag into an enumÆvar Arnfjörð Bjarmason, Oct 4, 2021
  74. 07/10 unpack-trees: avoid nuking untracked dir in way of unmerged fileÆvar Arnfjörð Bjarmason, Oct 4, 2021
  75. 08/10 unpack-trees: avoid nuking untracked dir in way of locally deleted fileÆvar Arnfjörð Bjarmason, Oct 4, 2021
  76. 09/10 Comment important codepaths regarding nuking untracked files/dirsÆvar Arnfjörð Bjarmason, Oct 4, 2021
  77. 10/10 Documentation: call out commands that nuke untracked files/directoriesÆvar Arnfjörð Bjarmason, Oct 4, 2021
  78. Elijah NewrenOct 4, 2021
  79. Ævar Arnfjörð BjarmasonOct 4, 2021
  80. Elijah NewrenOct 5, 2021
  81. Junio C HamanoOct 4, 2021
  82. Elijah NewrenOct 1, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.