However, Git also does not delete files which were previously tracked, but have been removed in the meantime
Yes, with Git 2.22 (Q2 2019) and git checkout --overlay
, it does.
"git checkout --no-overlay
" can be used to trigger a new mode of checking out paths out of the tree-ish, that allows paths that match the pathspec that are in the current index and working tree and are not in the tree-ish.
See commit e92aa0e (04 Feb 2019), commit 1495ff7, commit 091e04b (08 Jan 2019), and commit b7033e7, commit 5160fa0, commit 6fdc205, commit 536ec18, commit b702dd1, commit a0cc584 (20 Dec 2018) by Thomas Gummerer (tgummerer
).
Suggested-by: Jonathan Nieder (artagnon
).
(Merged by Junio C Hamano -- gitster
-- in commit 7d0c1f4, 07 Mar 2019)
checkout
: introduce --{,no-}overlay
option
Currently 'git checkout
' is defined as an overlay operation, which
means that if in 'git checkout <tree-ish> -- [<pathspec>]
' we have an
entry in the index that matches <pathspec>
, but that doesn't exist in
<tree-ish>
, that entry will not be removed from the index or the
working tree.
Introduce a new --{,no-}overlay
option, which allows using 'git checkout
' in non-overlay mode, thus removing files from the working tree if they do not exist in <tree-ish>
but match <pathspec>
.
Note that 'git checkout -p <tree-ish> -- [<pathspec>]
' already works
this way, so no changes are needed for the patch mode.
We disallow 'git checkout --overlay -p
' to avoid confusing users who would expect
to be able to force overlay mode in 'git checkout -p
' this way.
Untracked files are not affected by this change, so 'git checkout --no-overlay HEAD -- untracked' will not remove untracked from the working tree.
This is so e.g. 'git checkout --no-overlay HEAD -- dir/
' doesn't delete all untracked files in dir/
, but rather just resets the state of files that are known to git.
And you have a new git config
setting:
checkout.overlayMode:
In the default overlay mode, git checkout
never removes files from the index or the working tree.
When setting checkout.overlayMode
to false, files that appear in the index and working tree, but not in <tree-ish>
are removed, to make them match <tree-ish>
exactly.
"`git restore/checkout --no-overlay" with wildcarded pathspec mistakenly removed matching paths in subdirectories, which has been corrected with Git 2.29 (Q4 2020).
See commit bfda204 (22 Aug 2020) by René Scharfe (rscharfe
).
(Merged by Junio C Hamano -- gitster
-- in commit c57afd7, 31 Aug 2020)
Reported-by: Sergii Shkarnikov
Initial-test-by: Sergii Shkarnikov
Helped-by: Jeff King
Signed-off-by: René Scharfe
The pathspec given to git checkout
and git restore
(man) and is used with both tree_entry_interesting
(via read_tree_recursive)
and match_pathspec
(via ce_path_match)
.
The latter effectively only supports recursive matching regardless of the value of the pathspec flag "recursive", which is unset here.
That causes different match results for pathspecs with wildcards, and can lead checkout and restore in no-overlay mode to remove entries instead of modifying them.
Enable recursive matching for both checkout and restore to make matching consistent.
Setting the flag in checkout_main()
technically also affects git switch
(man), but since that command doesn't accept pathspecs at all this has no actual consequence.
git rm
– Geoffreygeoffrygit checkout --overlay
. See my answer below. – Bergquist